docs(openspec): define phase 3d native macos client

This commit is contained in:
sechmachine
2026-08-10 22:52:39 +07:00
parent 6264e9c2dc
commit 57c5310e67
10 changed files with 609 additions and 0 deletions
@@ -0,0 +1,55 @@
## ADDED Requirements
### Requirement: P3D-016 complete MVP input
Input SHALL support keyboard, absolute and relative mouse, high-resolution scroll, and one standard controller with a pressed-state ledger and release-all on every authority/interruption boundary.
#### Scenario: Authority loss with pressed input
- **WHEN** focus, network, session authority, sleep, cancellation, or termination changes while input is pressed
- **THEN** release-all is sent/recorded once and no pressed state remains
### Requirement: P3D-017 Windows password is ordinary input
Windows lock-screen credentials SHALL travel only as normal encrypted input events and SHALL never be collected, stored, autofilled, or separately injected.
#### Scenario: Lock-screen typing
- **WHEN** the user types into a remote Windows credential field
- **THEN** the client handles the keys like any remote input and retains no credential value
### Requirement: P3D-028 controller layouts
Controller input SHALL support user-selectable Xbox, PlayStation, and Nintendo/Switch-style normalized layouts with explicit unsupported-capability behavior.
#### Scenario: Layout selection
- **WHEN** the user changes controller layout
- **THEN** subsequent normalized events use the selected mapping and unsupported controls are surfaced explicitly
### Requirement: P3D-029 bounded text clipboard
The client SHALL expose clipboard enablement/direction and visible failure behavior, permit only bounded text, and reject files, file URLs, folders, binary data, and oversized content.
#### Scenario: File clipboard attempt
- **WHEN** a local or remote clipboard advertises a file or file URL
- **THEN** transfer is rejected without reading or persisting file content
### Requirement: P3D-035 native pointer modes and escape safety
The client SHALL aspect-fit video, emit absolute pointer events only inside the rendered viewport, default to macOS-owned absolute cursor behavior, and provide session-only relative capture with reserved local control chords.
#### Scenario: Letterbox pointer
- **WHEN** the absolute pointer is in a letterbox bar
- **THEN** no remote absolute-pointer event is emitted
#### Scenario: Toggle relative mode
- **WHEN** `Control-Option-Shift-M` is pressed during a session
- **THEN** pressed input is released, the chord is not forwarded, capture switches, and the saved/restored cursor point is clamped inside the rendered viewport
#### Scenario: Emergency release
- **WHEN** `Control-Option-Shift-Escape` is pressed in any input mode
- **THEN** pressed input is released, absolute/local cursor ownership and controls return, and the chord is not forwarded
### Requirement: P3D-036 scoped keyboard mappings
Keyboard mapping SHALL support physical/logical keys and simultaneous chords with Mac-to-Windows and language defaults, deterministic global/resource precedence and modifier order, conflicts, enablement, add/remove, and Restore Defaults; macros and reserved-chord remapping are prohibited.
#### Scenario: Conflicting resource mapping
- **WHEN** an enabled resource mapping conflicts with a global mapping
- **THEN** deterministic resource precedence applies and the conflict is visible/editable
#### Scenario: Reserved mapping attempt
- **WHEN** a mapping targets either local reserved escape chord
- **THEN** the mapping is rejected and the local chord remains intercepted
@@ -0,0 +1,43 @@
## ADDED Requirements
### Requirement: P3D-018 explicit recovery states
The client SHALL distinguish network interruption, reconnectable session, draining, provider cleanup failure, assignment unavailable, capacity queue, entitlement loss, and terminal end with safe actions.
#### Scenario: Reconnectable interruption
- **WHEN** the control authority reports a reconnectable session after network loss
- **THEN** the UI offers only a fresh authorized reconnect path and does not replay the old grant
### Requirement: P3D-019 deterministic lifecycle changes
Sleep/wake, foreground/background, display/audio/controller/network changes, server/gateway restart, and core cancellation SHALL have deterministic tested behavior.
#### Scenario: Sleep during active stream
- **WHEN** the Mac sleeps during an active stream
- **THEN** input is released, owned tasks/resources stop, and wake reconciles authority before reconnect
### Requirement: P3D-021 accessible critical paths
Authentication, resources, brokerage, session, errors, and settings SHALL support VoiceOver, keyboard navigation, visible focus, contrast, reduced motion, dynamic type where applicable, and non-color status cues.
#### Scenario: Keyboard-only connection
- **WHEN** a user navigates the workspace without a pointer
- **THEN** every critical action is reachable with visible focus and meaningful accessibility labels
### Requirement: P3D-022 redacted diagnostics
Errors, telemetry, logs, crashes, and support artifacts SHALL exclude credentials, grants, provider endpoints, raw media/input, clipboard content, and Windows secrets while retaining bounded correlation identifiers.
#### Scenario: Synthetic secret canary
- **WHEN** all diagnostics and support outputs are generated after injecting secret canaries
- **THEN** the scanner finds no secret, media, input, clipboard, or provider-endpoint value
### Requirement: P3D-023 release platform safety
Any distributed release SHALL be signed, notarized, hardened-runtime compatible, signature-verified for update, and rollback-tested.
#### Scenario: Tampered update
- **WHEN** update metadata or the application artifact is modified after signing
- **THEN** update verification fails before installation or execution
### Requirement: P3D-024 explicit uninstall policy
Uninstall SHALL remove documented local application state according to explicit Keychain/cache policy and SHALL NOT silently delete server-side device authority.
#### Scenario: Offline uninstall
- **WHEN** the app is removed while the Server is unreachable
- **THEN** local state follows policy and server-side revocation is not falsely claimed
@@ -0,0 +1,15 @@
## ADDED Requirements
### Requirement: P3D-014 hardware video presentation
Video SHALL use negotiated registered media identifiers, VideoToolbox hardware decode, and Metal presentation without unnecessary copies or persistence.
#### Scenario: Unsupported hardware decode
- **WHEN** the negotiated profile cannot be decoded by supported VideoToolbox hardware
- **THEN** the session fails explicitly without software fallback, remote transcode, or pixel logging
### Requirement: P3D-015 bounded audio playback
Audio SHALL use a proven CoreAudio abstraction with bounded buffering, negotiated channel layout, drift handling, and measurable A/V synchronization.
#### Scenario: Audio device replacement
- **WHEN** the default audio device changes or disappears during an active session
- **THEN** bounded playback state is recreated or fails visibly without persisting streamed audio
@@ -0,0 +1,134 @@
## ADDED Requirements
### Requirement: P3D-001 Apple Silicon platform baseline
The client SHALL target Apple Silicon with macOS 26 primary, macOS 15/14 supported, and a non-release macOS 27 compatibility lane when its SDK/runtime exists.
#### Scenario: Supported platform matrix
- **WHEN** the frozen candidate is qualified
- **THEN** exact native evidence exists for macOS 26, 15, and 14, while Intel is not claimed
### Requirement: P3D-002 isolated SwiftUI state
The shell SHALL use SwiftUI with structured concurrency and isolated authentication, resource, broker, stream, and settings state.
#### Scenario: Concurrent state update
- **WHEN** control and stream events arrive concurrently
- **THEN** owning actors serialize mutation and views receive immutable main-actor projections
### Requirement: P3D-003 no former C++ core
The implementation SHALL NOT restore the superseded C++ core packaging design.
#### Scenario: Core dependency audit
- **WHEN** the native client dependency graph is inspected
- **THEN** no VerseVDI C++ streaming core or wrapper is linked
### Requirement: P3D-004 stable C ABI
The C ABI SHALL use sized versioned tables and define pointer ownership, lifetime, callback thread, cancellation, error, reentrancy, and destroy behavior.
#### Scenario: Older caller table
- **WHEN** a caller supplies a supported older structure size
- **THEN** the core reads only available fields and returns a deterministic compatibility result
### Requirement: P3D-005 Rust core
The platform-neutral streaming core SHALL be Rust, not the superseded C++ implementation.
#### Scenario: Core artifact inspection
- **WHEN** the XCFramework artifact is inventoried
- **THEN** its exported VerseVDI surface is the reviewed C ABI backed by the pinned Rust core
### Requirement: P3D-006 Swift platform ownership
Swift SHALL own HTTPS/WebSocket control, Keychain, navigation, accessibility, Apple decode/render/audio/input objects, signing, and update integration.
#### Scenario: Platform operation routing
- **WHEN** a platform credential, window, decoder, audio device, or input operation occurs
- **THEN** it is owned by Swift/AppKit/Apple frameworks and not by the Rust core
### Requirement: P3D-007 narrow credential storage
Refresh credentials and device private keys SHALL use the narrowest practical Keychain accessibility; access tokens and gateway grants SHALL remain memory-only.
#### Scenario: Relaunch storage audit
- **WHEN** the app terminates and relaunches
- **THEN** no access token or gateway grant is recoverable from persistent client storage
### Requirement: P3D-008 authenticated device enrollment
First use SHALL authenticate before device-key generation/registration and SHALL complete server challenge proof before launch authority.
#### Scenario: Unauthenticated enrollment attempt
- **WHEN** device enrollment is requested without a current authenticated user session
- **THEN** no key is registered and no launch authority is issued
### Requirement: P3D-009 no active LDAP mode
The Phase 3D client SHALL NOT expose an active LDAP login mode before Phase 6.
#### Scenario: Login surface inspection
- **WHEN** the Phase 3D login UI and control requests are exercised
- **THEN** only local login is offered and no LDAP request is made
### Requirement: P3D-010 authorized resources only
The UI SHALL show only assigned desktops and entitled pools, including unavailable assignment, `awaiting_desktop`, and capacity queue state.
#### Scenario: Cross-subject cached resource
- **WHEN** stale local data references another subject's resource
- **THEN** reconciliation removes or withholds it and no action is available
### Requirement: P3D-011 idempotent broker reconciliation
The client SHALL request/cancel idempotently, apply events by sequence, resync gaps through REST, and reconcile current authority after relaunch.
#### Scenario: Event sequence gap
- **WHEN** the next event sequence is not contiguous
- **THEN** incremental application stops and REST reconciliation completes before further action
### Requirement: P3D-012 gateway-only manifest
The client SHALL accept only a gateway-only manifest matching authenticated server, device, session, audience, expiry, and supported tunnel range.
#### Scenario: Wrong manifest context
- **WHEN** any manifest binding or required tunnel capability is wrong
- **THEN** the core rejects it before opening a media/input session
### Requirement: P3D-013 forbidden provider details
The client SHALL reject and safely report any manifest containing a provider/VM endpoint or credential-like field.
#### Scenario: Provider field injection
- **WHEN** a manifest contains a provider address or credential-shaped field
- **THEN** launch fails closed and diagnostics contain no injected value
### Requirement: P3D-020 callback isolation
Core callbacks SHALL transfer bounded immutable values to their owning actor and SHALL NOT mutate SwiftUI state directly.
#### Scenario: Callback storm
- **WHEN** callbacks arrive rapidly from a non-main core thread
- **THEN** bounded bridge delivery preserves order/ownership without direct view-state mutation
### Requirement: P3D-025 fake-core-first candidate
The client SHALL pass fake-core UI behavior before real-core fixture integration and SHALL freeze a platform-qualified candidate before owner live Apollo acceptance.
#### Scenario: Live provider unavailable
- **WHEN** deterministic implementation gates pass without owner Apollo access
- **THEN** the candidate can reach engineering review with live interoperability recorded `deferred-owner-e2e`
### Requirement: P3D-026 XCFramework packaging
The Rust core SHALL be packaged as a static library within an XCFramework behind one stable C ABI and thin Swift wrapper.
#### Scenario: Unsafe-call audit
- **WHEN** Swift source is inspected
- **THEN** only the designated bridge owns direct C ABI pointer and callback translation
### Requirement: P3D-027 core responsibility boundary
The Rust core SHALL own tunnel negotiation, cryptography, reconstruction, encoded delivery, input encoding, policy updates, statistics, and core errors without owning product authorization or Apple UI/media devices.
#### Scenario: Responsibility audit
- **WHEN** the core dependency/module graph is inspected
- **THEN** no SwiftUI, Apple decoder/renderer/audio device, or product-auth implementation is linked into it
### Requirement: P3D-030 registered media dispatch
Core and client SHALL dispatch framing, reconstruction, decode, and render from registered negotiated identifiers and SHALL fail stably on unsupported/stale combinations.
#### Scenario: Unsupported profile combination
- **WHEN** framing and media identifiers have no supported explicit intersection
- **THEN** the session fails before decoder allocation without guessing, fallback, or transcode
### Requirement: P3D-031 local authentication lifecycle
The MVP SHALL support local login, rotating refresh, logout, device-revocation response, and generic anti-enumeration errors.
#### Scenario: Refresh-family revocation
- **WHEN** the Server reports refresh reuse or device revocation
- **THEN** local authority and active input/stream state are cleared and generic reauthentication is shown
@@ -0,0 +1,23 @@
## ADDED Requirements
### Requirement: P3D-032 native desktop workspace
The app SHALL expose Favorites, Desktops, Pools, and Settings in a native split workspace without Apps, Add PC, manual endpoint, or direct-provider surfaces. Desktop cards SHALL remain `328 x 205 pt`, use full-bleed previews and subtle readable metadata treatment, and adapt only the grid column count.
#### Scenario: Narrow and wide resize
- **WHEN** the workspace moves between narrow, medium, and wide widths
- **THEN** card geometry remains fixed, the column count changes, and text/actions do not overflow
#### Scenario: Accessible card actions
- **WHEN** a card receives hover or keyboard focus
- **THEN** Favorite and settings controls become available without adding a connect button; double-click or Return connects
### Requirement: P3D-037 private favorites and previews
Favorites, search, sort, filters, diagnostics, and previews SHALL reveal only current authorized resources. A stable desktop MAY retain one `656 x 410` mode-`0600` preview only after an active session ends cleanly; pool art is generic and preview bytes are excluded from backup/telemetry/log/crash/support data.
#### Scenario: Failed launch and clean end
- **WHEN** a launch fails and a later active session ends cleanly
- **THEN** the failed launch preserves the old preview and only the clean end atomically replaces it
#### Scenario: Entitlement loss
- **WHEN** logout or reconciliation removes a desktop entitlement
- **THEN** its preview is cleared and cannot appear through Favorites, search, cache, or diagnostics
@@ -0,0 +1,27 @@
## ADDED Requirements
### Requirement: P3D-033 requested and effective display mode
The client SHALL offer global and desktop/pool overrides for Automatic, detected/common preset, Custom, and Full Native width/height/FPS. A display-aware request SHALL be feature-gated; the Server SHALL validate, include it in idempotency identity, resolve immutable policy, proportionally clamp to even dimensions and maximum FPS, persist requested/effective values atomically, and disclose both without provider details.
#### Scenario: Oversized custom request
- **WHEN** a requested mode exceeds either policy dimension or FPS
- **THEN** the Server applies one proportional scale, floors both dimensions to even pixels, caps FPS, persists the result, and returns the requested and accepted modes
#### Scenario: Legacy request
- **WHEN** a client omits the feature and requested display object
- **THEN** the Server preserves the legacy response shape and provider work uses the existing exact policy mode
#### Scenario: Same idempotency key with different mode
- **WHEN** two requests reuse an idempotency key but contain different requested display modes
- **THEN** the Server rejects the mismatch rather than returning or mutating the earlier session
### Requirement: P3D-034 native detection and reconnect semantics
Automatic mode SHALL derive physical pixels and maximum FPS from the screen where the session window opens, prefer a defensible notch-safe built-in mode, otherwise disclose Full Native, and SHALL NOT mutate an active mode after a display move. Reconnect to match the new display SHALL end the prior session and use a new request/idempotency key. Owner E2E SHALL prove accepted values on Apollo/SudoMaker IDD through the gateway-only route.
#### Scenario: Move active session to another display
- **WHEN** an Automatic session window moves to a display with different native capability
- **THEN** the active mode remains unchanged and the user may explicitly reconnect with a newly detected request
#### Scenario: Exact owner virtual-display acceptance
- **WHEN** the owner runs the frozen client, Server, gateway, and Apollo candidate
- **THEN** retained evidence binds requested and accepted width/height/FPS to the actual SudoMaker virtual display without a direct client-provider route