42 lines
6.6 KiB
Markdown
42 lines
6.6 KiB
Markdown
# Compact Menu and Session Indicator Implementation Plan
|
|
|
|
**Intent:** Implement the approved compact macOS menu mockup with Yandex Key import and a small configurable session indicator.
|
|
**Current Behavior:** MenuBarExtra uses a plain menu, shield plus H:MM, dense module diagnostics and a login Terminal action. CLI stores started_at but does not expose it to events/status and resets it on repeated expiry lines.
|
|
**Expected Outcome:** A native 298-point popover matching the approved layout; import/login actions, preserved connection actions, a persisted ring/clock/time preference (16-point ring default), exact remaining time in menu, elapsed fill and green/amber/red urgency.
|
|
**Target-Perspective Output:** Synthetic CLI transcript produces stable started_at plus real expiry; compiled presentation checks demonstrate progress/time/color boundaries, reset/legacy handling and correctly quoted Terminal commands. Release app compiles. Native visual acceptance remains explicitly untested because no GUI testing was requested.
|
|
**Truth Owner:** CLI owns connection start/expiry metadata; Swift session model computes derived presentation. UserDefaults owns the indicator preference. CLI/Keychain still own import and credentials.
|
|
**Contract Boundary:** Add optional started_at to existing events and connected status; preserve all old fields and auth modes. Swift falls back to the first observed connection time with older CLI, never to an assumed duration.
|
|
**Cutover:** Replace the existing plain menu and shield+time connected presentation in place with the approved popover and selected indicator. Reuse the Terminal launcher for import; no second credential UI.
|
|
**Displaced Path:** Unconditional shield+time becomes a selected style; dense healthy module details leave the default surface, actionable setup/tunnel warnings remain visible. No new VPN connection/reconnect logic.
|
|
**Value Density:** Native SwiftUI window menu, AppStorage and AppKit image drawing; no dependencies, app installation or platform rewrite.
|
|
**Acceptance Evidence:** Automated event/status transcript, pure Foundation session checks, generated Zsh script execution against a fake CLI, existing regression suites and Swift build.
|
|
**Evidence Lane:** Automated only. No app/Terminal launch, GUI, screenshot, live VPN, real Keychain or installation.
|
|
**Kill Criteria:** No fixed 8h duration, repeated timing events cannot reset fill, disabled/disconnected states cannot show stale time, imported secret never enters Swift, new sources ship in installer, existing auth/cancel/copy/log/quit actions remain reachable.
|
|
**Architecture Slice:** `bin/vpn-lemanapro.sh` -> VPNEvent -> `VPNManager.swift` -> new Foundation `SessionTiming.swift` -> `LemanaVPNApp.swift`; installer explicitly downloads the new source; focused tests and README describe behavior. Existing dirty work is preserved.
|
|
**Plan Review Gate:** Requires PRE review before execution.
|
|
|
|
## Tasks
|
|
|
|
1. Root: persist one start timestamp per `_filter_output` connection, include it in connected/session_info/status output, test repeated expiry lines and status round-trip with fake tools. No SSO/DNS/reconnect changes.
|
|
2. Root: add session timing model, optional event timestamp, reset on lifecycle transitions, update presentation once per second, preserve legacy timestamp fallback; fix JSON line buffering if required to deliver the new contract through real pipe chunks. Test timing independently and via decoded event fixtures.
|
|
3. Root: approved native popover, 16px ring/clock and compact time option, persisted preference, localized accessible status, visible setup/tunnel failures, all existing actions. Reuse Terminal script builder for import and login, fixing the existing read-only Zsh `status` variable and using per-action success text; setup launch failure must not replace an active VPN state.
|
|
4. Root: update source packaging, README and narrow smoke wiring expectations; run automated checks and POST correctness/maintainability review. Review agents are read-only; implementation stays with root.
|
|
|
|
## Behavior details
|
|
|
|
- Fill = clamp((now - started_at) / (expires - started_at), 0...1) for valid positive duration. Unknown/invalid expiry uses a normal connection symbol and “Срок сессии неизвестен”.
|
|
- Remaining >60min green; <=60min amber; <=15min red, including expiry. Exact menu text and accessibility labels accompany color. No continuous decorative spinner.
|
|
- Expiry alone does not start another session or pretend the process ended; keep disconnect while the process is still connected. Disconnected/reconnecting/error use distinct system symbols and no stale countdown.
|
|
- Start/end reset on an actual new connection attempt and terminal states; repeated connected/session_info data in one attempt retains its origin. RefreshStatus remains a module refresh, without attaching to external VPN processes.
|
|
- Approved reference: `/Users/dokril/.codex/visualizations/2026/10/07/01a117e8-cae9-7f02-9dc7-c177c368a223/vpn-menu.html`. Mock-specific demonstration controls are not shipped.
|
|
|
|
## Completed implementation and evidence
|
|
|
|
- Native `.window` menu, 298 pt layout, AppStorage ring/clock/time preference, 16 pt AppKit ring/clock image, exact remaining-time labels, import/login Terminal actions and all connection/cancel/copy/log/quit paths implemented. Healthy raw module summaries removed; actionable failures remain visible.
|
|
- CLI event, status file and status response share a stable start timestamp. Foundation timing logic handles observed legacy starts, real duration, clamping, unknown/invalid intervals and 60/15-minute thresholds. Lifecycle transitions reset timing, and the UI updates once per second.
|
|
- `tests/menu.py`: PASS. Real shell filter/status transcript with synthetic dates, repeated expiry and reconnect; compiled Swift model, every byte boundary in UTF-8/JSON framing, old CLI sole manual-full action; generated Terminal scripts executed in Zsh against a fake quoted-path CLI for success and exit 7. No Terminal application launched.
|
|
- `tests/smoke.sh`, `tests/logging.py`, `tests/configuration.py` (10 checks), `tests/yandex_import.py`, shell syntax and `git diff --check`: PASS.
|
|
- Final `swift build -c release --package-path app`: PASS (3.07 s). One restricted attempt was blocked by the compiler cache sandbox; an approved build escalation succeeded.
|
|
- PRE and POST correctness/maintainability reviews completed. Fixed the sole legacy-action regression and made invalid timing consistently unknown; removed newly unused statusBarTitle/moduleSummary/summary paths.
|
|
- Native UI is implemented but unproven visually: no GUI, screenshots, real Terminal/import, installation or live VPN acceptance was run. Existing unrelated dirty changes remain intact.
|