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,2 @@
schema: spec-driven
created: 2026-08-10
@@ -0,0 +1,176 @@
## Context
Phase 3C freezes a gateway-only control/media baseline, but the Data Plane macOS target is
still a template and the shared Protocol has no requested display mode, absolute pointer, or
high-resolution scroll contract. The closed Server already owns broker persistence,
allocation policy, manifest disclosure, and provider-work. The GPLv3 Data Plane owns the
pure-Go gateway/Apollo translation plus the future Rust core and native client. The Protocol
repository remains the only wire authority.
The implementation must preserve strict legacy JSON decoding, exact immutable Protocol pins,
no direct client-to-provider path, encoded-media relay without gateway decode/transcode, and
bounded release-all behavior. UI references are retained in the Planning repository as
review evidence only.
## Goals / Non-Goals
**Goals:**
- Deliver one native Apple-Silicon SwiftUI/AppKit client for macOS 26 with macOS 15/14
compatibility, built against a deterministic fake core before real streaming integration.
- Carry a client-requested display mode through Server allocation to provider work, while the
Server remains the only policy/clamp authority and both requested/effective values remain
visible to the client.
- Add provider-neutral absolute pointer and high-resolution scroll events without changing
the gateway-only route or coupling the public contract to Apollo packet shapes.
- Keep lifecycle, input release, local preview storage, secrets, media, and diagnostics
bounded and testable at their trust boundaries.
- Preserve a small, sized/versioned Rust C ABI and a single Swift unsafe bridge.
**Non-Goals:**
- Remote apps, manual PC/direct provider connections, live display renegotiation,
multi-monitor remote topology, HDR, microphone, file/folder redirection, image clipboard,
macros/timed sequences, Intel, provider-specific UI, or a plugin framework.
- Gateway decode, encode, transcode, render, cgo, native sidecar, insecure retry, or silent
capability fallback.
- Public release, signing credentials, deployment, promotion, or agent access to the owner's
Apollo host. Live Apollo/SudoMaker evidence remains owner E2E.
## Decisions
### 1. Repository and compatibility ownership
- Protocol adds a reusable `DisplayMode` object and optional request/response fields while
retaining control wire version 1. Generated Go represents optional referenced objects as
pointers so `nil` is omitted; Rust/Swift use optionals. A legacy request receives the
legacy response shape, while a display-aware request requires `display.request.v1` and a
display-aware manifest contains the accepted value.
- Protocol registers `display.request.v1`, `input.absolute.v1`, and `input.scroll.v1` and
extends VGI1 only behind those negotiated features. Old gateways continue to reject
unknown kinds; clients therefore never send an unadvertised kind.
- Protobuf remains unchanged unless an observed consumer or verification gate proves that
the JSON control route actually depends on it. This avoids an unrelated second contract.
- A verified-unused immutable Phase 3D Protocol RC is frozen before Server/Data pins advance
together. No sibling `replace` or local wire fork is committed.
### 2. Server-owned display decision
- Broker sessions gain nullable requested/effective width, height, and FPS columns plus the
immutable policy-version identity needed to replay allocation/reconnect. Dedicated columns
keep the decision queryable and avoid overloading the existing bandwidth policy JSON.
- Request validation accepts width 320..16384, height 200..8640, and FPS 1..240. Requested
mode participates in every idempotency identity, including waiting sessions.
- Allocation selects the machine, resolves the immutable machine/pool/global policy, computes
the accepted mode, and atomically persists the allocation and accepted values. Reconnect
reuses the persisted result; it does not re-clamp against later policy.
- Clamp is proportional and deterministic:
`scale = min(policyWidth/requestWidth, policyHeight/requestHeight, 1)`;
`effectiveWidth = floorToEven(requestWidth * scale)`;
`effectiveHeight = floorToEven(requestHeight * scale)`;
`effectiveFPS = min(requestedFPS, policyFPS)`.
- Provider work uses the persisted effective dimensions/FPS and the selected immutable
policy's codec/bitrate/audio. Legacy sessions retain today's exact policy dimensions.
### 3. Provider-neutral input
- VGI1 kind `0x06` has exactly eight body bytes: big-endian unsigned `x`, `y`, viewport
width, and viewport height. Width/height must be nonzero; x < width and y < height.
- VGI1 kind `0x07` has exactly four body bytes: big-endian signed 16-bit vertical and
horizontal high-resolution scroll deltas.
- Protocol docs, fixtures, Go/Rust/Swift classifiers, Data encode/decode, fuzzing, transport,
and Apollo translation share the same vectors. Apollo packet details remain private to the
adapter and must be justified by pinned reference source before implementation.
- Absolute/scroll events do not enter the pressed-state ledger. Keys, buttons, and controllers
continue to release through the existing ledger on every authority/lifecycle exit.
### 4. Native workspace, display discovery, and input ownership
- The client uses `NavigationSplitView`, native controls/materials, and standard macOS 26
Liquid Glass APIs conditionally. macOS 15/14 retain identical hierarchy with native
materials; no custom glass framework is introduced.
- Desktop cards remain `328 x 205 pt`; an adaptive grid only changes column count. Card
actions remain accessible without hover, and no direct-connect button or endpoint entry is
added.
- Automatic mode reads physical pixels for the screen where the session window opens and
uses its maximum FPS. A defensible notch-safe built-in mode is preferred; otherwise Full
Native is disclosed. A display move offers a new-session reconnect and never mutates the
active stream.
- The renderer aspect-fits. Absolute coordinates originate only inside the rendered viewport;
letterbox bars produce no pointer event.
- Native `NSWindow` fullscreen preserves top-edge system UI in absolute mode. Relative mode
hides/captures the cursor. Reserved mode-toggle and emergency-release chords are handled
before mapping and never cross the core boundary. Mode switches release pressed input and
clamp cursor restoration to the rendered viewport.
### 5. State, Rust core, and platform boundaries
- Swift actors own authentication, resources, brokerage, streaming, and settings; immutable
projections reach `MainActor` views. One bridge owns every C pointer/callback/lifetime.
- The Rust core owns tunnel negotiation, authenticated framing, packet reconstruction,
encoded media delivery, input encoding, statistics, cancellation, and structured errors.
Apple frameworks own decode/render/audio/device/input capture and product state.
- The C ABI uses fixed-width values, explicit lengths, opaque handles, sized/versioned tables,
a declared callback queue, caught panics, cancellation, and late-callback/destroy rules.
- Fakes cover every external boundary before real core/media integration. No speculative
adapter/factory/plugin layer is added beyond interfaces already needed for deterministic
tests.
### 6. Preview and diagnostic privacy
- Stable desktop previews are downscaled to `656 x 410`, stored in the sandbox cache as mode
`0600`, and written only after an active session ends cleanly. Failed launch retains the
prior preview. Pool cards use generic art.
- Logout or entitlement loss clears affected previews. Hide/Clear settings are explicit.
Backup, telemetry, OSLog, crashes, support bundles, and default diagnostics exclude preview
and raw media bytes.
- Diagnostics are allowlisted structured state/correlation/performance summaries; tokens,
grants, provider endpoints, media, input, clipboard, and Windows secrets never enter them.
### 7. Delivery and evidence
- Land capability-sized commits in order: Planning/OpenSpec, Protocol, Server, gateway input,
fake-core native shell, Rust/core integration, platform media, then full qualification.
- Every nontrivial boundary starts with a focused failing test/vector and ends with the
narrow affected gate; one complete clean-source gate runs only after freeze.
- macOS 26/15/14 native behavior, accessibility, lifecycle, privacy, and platform media require
real target evidence. The owner later runs the only live Apollo/SudoMaker acceptance.
## Risks / Trade-offs
- [Strict legacy decoders reject additive response fields] -> Emit display fields only for a
negotiated display-aware request; retain legacy shapes and cross-version fixtures.
- [Requested dimensions exceed policy or change aspect] -> Apply one Server-owned
proportional/even clamp, persist it atomically, and disclose both values.
- [Absolute coordinates mismatch presentation] -> Normalize against the rendered viewport,
reject letterbox coordinates, and test edge/scale/display cases.
- [Relative capture strands local input] -> Keep an unremappable emergency release, release
before every mode/authority transition, and test focus/sleep/cancel/revocation paths.
- [Preview bytes leak user media] -> Minimize one local file, mode `0600`, clean-session-only
writes, lifecycle clearing, and explicit exclusion/secret-canary tests.
- [Apollo input semantics are guessed] -> Stop until the pinned provider source establishes
the exact packet; do not encode provider assumptions into VGI.
- [macOS API rendering differs by release/accessibility setting] -> Test deterministic
geometry and state automatically; use bounded manual material review without snapshots of
OS-owned pixels as the sole gate.
- [The full client scope is large] -> Keep serial capability commits and stop at the first
failed contract/environment gate rather than introducing fallbacks or partial claims.
## Migration Plan
1. Freeze Planning/OpenSpec and visual references.
2. Implement/freeze an immutable Protocol RC with legacy and new feature fixtures.
3. Apply the forward-only Server migration and update Server/Data Protocol pins together.
4. Deploy no schema or runtime automatically; validate clean install/upgrade/legacy rows and
gateway fixtures locally/private CI first.
5. Build the native shell against fakes, then integrate the frozen core/gateway surfaces.
6. Roll back application binaries only while schema compatibility permits; nullable additive
fields preserve legacy row behavior. Never down-migrate or rewrite applied migrations.
7. Keep signing, publication, deployment, promotion, and live owner E2E under separate
authorization.
## Open Questions
None at proposal time. Exact Apollo absolute-pointer/scroll packet vectors must be established
from the approved pinned source before the adapter step; absence of that evidence is an
implementation hard stop, not a design choice to guess.
@@ -0,0 +1,65 @@
## Why
Phase 3C has frozen the gateway and Connection Server image-engineering baseline, so the first
native VerseVDI endpoint can now be built against an immutable gateway-only authority model.
Phase 3D must add the user-facing macOS workspace, exact display negotiation, safe native
input, and streaming core without exposing Apollo/provider details or weakening the existing
control and transport boundaries.
## What Changes
- Build the Apple-Silicon SwiftUI/AppKit client and platform-neutral Rust Streaming Core
behind one sized/versioned C ABI (`P3D-001``P3D-031`).
- Implement the reviewed native workspace, fixed preview cards, Favorites, search/sort,
settings, accessibility, and privacy-bounded desktop previews (`P3D-032`, `P3D-037`).
- Add feature-gated requested/effective display modes, Server-owned policy clamping,
client display detection/disclosure, and explicit reconnect-on-display-change behavior
(`P3D-033``P3D-034`).
- Add provider-neutral absolute pointer and high-resolution scroll input while preserving
relative input, release-all, reserved local escape chords, letterbox exclusion, and scoped
keyboard mapping (`P3D-035``P3D-036`).
- Keep authentication, manifests, media, input, and clipboard on the authenticated
gateway-only route. The client receives no provider endpoint, provider credential, or
Windows credential outside normal encrypted input.
- Defer remote apps, manual PC/direct-provider connections, live display renegotiation,
multi-monitor remote topology, HDR, microphone, file/folder redirection, image clipboard,
macros, Intel, public release, and provider-specific client UI.
## Capabilities
### New Capabilities
- `macos-native-foundation`: Platform baseline, Swift/Rust/C ABI ownership, authentication,
resource/broker authority, gateway-only manifest validation, and fake-core-first delivery.
- `macos-media-presentation`: Registered media dispatch, hardware video presentation, audio,
bounded queues, and observable quality without media persistence.
- `macos-input-control`: Provider-neutral keyboard, pointer, scroll, controller, text
clipboard, mappings, reserved local chords, and release-all behavior.
- `macos-lifecycle-quality`: Interruption, reconnect, accessibility, privacy, diagnostics,
packaging, rollback, uninstall, and candidate qualification behavior.
- `macos-workspace`: Screenshot-backed workspace/card/settings interactions, Favorites,
search/sort, and privacy-bounded previews.
- `session-display-mode`: Feature-gated requested/effective display mode, Server policy
clamping, client detection/disclosure, and owner Apollo IDD acceptance.
### Modified Capabilities
None. Existing Phase 3C gateway capabilities remain unchanged; this change consumes and
extends their separately owned Protocol surfaces without redefining their requirements.
## Impact
- **Protocol repository:** additive strict JSON display objects, feature identifiers, VGI1
absolute/scroll grammar, cross-language bindings, fixtures, and compatibility tests.
- **Connection Server:** additive broker-session migration/query fields, request identity,
allocation transaction/clamp, manifest disclosure, and provider-work projection.
- **Data Plane:** Protocol pin update, Go gateway input validation/Apollo translation, Rust
core/C ABI/XCFramework, SwiftUI/AppKit client, tests, documentation, and private build
configuration.
- **Provenance and license boundary:** Apollo, Moonlight, Microsoft Windows App, and Omnissa
material remains reference evidence only. No proprietary Server or Planning content is
copied into the GPLv3 Data Plane.
- **Hard stops:** unknown provider packet semantics, incompatible legacy response behavior,
direct-provider routing, secret/media/input persistence, unsupported platform safety, or
a failed deterministic gate blocks the affected capability. Live Apollo/macOS/firewall
interoperability remains `deferred-owner-e2e` until the owner runs the frozen candidate.
@@ -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
@@ -0,0 +1,69 @@
## 1. Contract Freeze
- [ ] 1.1 Add Protocol `DisplayMode`, negotiated display fields/features, VGI1 absolute/scroll grammar, strict valid/invalid cross-language fixtures, and optional-field omission regressions
- [ ] 1.2 Regenerate Go/Rust/Swift outputs twice, pass Protocol `make verify`, freeze a verified-unused immutable Phase 3D RC, and record its fixture/generated hashes
- [ ] 1.3 Update Server and Data Plane to the exact Protocol RC without a filesystem replacement and prove clean-cache module resolution before consumer implementation
## 2. Server Display Authority
- [ ] 2.1 Add the forward-only nullable requested/effective display and policy-version migration plus clean-install/upgrade/schema/grant tests
- [ ] 2.2 Add strict request validation and requested-mode idempotency identity, including waiting-session mismatch regressions
- [ ] 2.3 Implement one proportional even-pixel/FPS clamp at allocation and atomically persist the immutable requested/effective decision
- [ ] 2.4 Disclose display-aware broker/manifest values only to negotiated clients, preserve legacy response shapes, and reuse the persisted mode on reconnect
- [ ] 2.5 Project persisted effective width/height/FPS through existing provider work with selected immutable codec/bitrate/audio and pass focused repository/E2E tests
## 3. Gateway Input Translation
- [ ] 3.1 Add red VGI absolute/scroll encode/decode/bounds/fuzz/transport tests and prove unadvertised kinds fail before provider translation
- [ ] 3.2 Establish exact Apollo absolute-pointer and scroll vectors from the approved pinned source; hard-stop without that evidence
- [ ] 3.3 Implement the smallest provider-neutral VGI validation and Apollo adapter translation without adding pressed-state or direct-provider surfaces
- [ ] 3.4 Pass focused input vectors/fuzz/transport/fake-provider tests, then one affected Data Plane `make verify`
## 4. Rust Core and Stable ABI
- [ ] 4.1 Pin Rust toolchain/dependencies and add minimal core modules with bounded fake transport, Protocol fixtures, cancellation, errors, queues, and redaction
- [ ] 4.2 Specify and test the sized/versioned C ABI ownership, callback thread, panic, reentrancy, cancellation, late-callback, and destroy contracts before implementation
- [ ] 4.3 Implement gateway-only manifest/QUIC/framing/media/input behavior against fixtures with no provider endpoint, decoder, renderer, transcode, or product-auth path
- [ ] 4.4 Package deterministic Apple-Silicon static XCFramework output and one Swift bridge; pass Cargo format/Clippy/tests plus applicable fuzz/Miri/sanitizer and ABI stress gates
## 5. Native Foundation Against Fakes
- [ ] 5.1 Reconcile the Xcode project to macOS 14 deployment, Xcode 26.6/Swift 6.3 Swift-6 mode, Apple Silicon, and conditional macOS 26 APIs
- [ ] 5.2 Implement isolated auth/resource/broker/stream/settings owners and deterministic control/event/core/credential/platform fakes with unit tests before views
- [ ] 5.3 Implement local login, device proof, serialized rotating refresh, Keychain/memory-only policy, logout/revocation, and anti-enumeration tests
- [ ] 5.4 Implement resource/broker/event-gap/relaunch/idempotency reconciliation and cross-subject fixture negatives
## 6. Workspace and Display UX
- [ ] 6.1 Build the screenshot-backed Favorites/Desktops/Pools/Settings shell with fixed `328 x 205 pt` cards, adaptive columns, safe truncation, native focus/VoiceOver, and no Apps/Add-PC/direct endpoint surfaces
- [ ] 6.2 Add global and resource Automatic/preset/Custom/Full Native settings, physical-pixel/FPS detection, notch-safe disclosure, and requested/accepted projections with deterministic display fakes
- [ ] 6.3 Add aspect-fit viewport math, letterbox pointer exclusion, display-move reconnect offer, and new-session/idempotency behavior tests
- [ ] 6.4 Pass geometry/hierarchy/visibility/responsive/accessibility automation and bounded macOS 26/15/14 native-material review
## 7. Native Input and Preview Privacy
- [ ] 7.1 Implement absolute and relative pointer capture with native fullscreen, top-edge local controls, pressed-state release, bounded cursor restore, HUD, and unremappable local toggle/emergency chords
- [ ] 7.2 Implement physical/logical and language-aware global/resource keyboard mappings, deterministic conflicts/precedence/modifier order, add/remove/enable/restore, and no-macro/reserved-chord negatives
- [ ] 7.3 Implement normalized controller layouts and bounded text-only clipboard with file/binary/oversize/loop/permission negatives
- [ ] 7.4 Implement atomic clean-session-only mode-`0600` desktop previews, generic pool art, hide/clear/logout/entitlement behavior, and backup/log/crash/support exclusion tests
## 8. Platform Media and Lifecycle
- [ ] 8.1 Implement registered VideoToolbox decode and Metal aspect-fit presentation with bounded latency-first queues, configuration/IDR/discontinuity/device-loss tests, and no pixel persistence
- [ ] 8.2 Implement bounded CoreAudio playback/synchronization with device/format/sleep/cancel tests and retained timing summaries without audio persistence
- [ ] 8.3 Implement deterministic sleep/wake, foreground/background, display/audio/controller/network change, server/gateway restart, cancellation, reconnect, and release-all behavior
- [ ] 8.4 Complete accessible errors/actions, allowlisted diagnostics, privacy manifest, secret-canary support-bundle tests, and 100-cycle ownership/leak stress
## 9. Real-Core Integration
- [ ] 9.1 Replace fake-core session transport only at the existing client seam and pass the same state/UI/lifecycle suites unchanged
- [ ] 9.2 Run shared Protocol manifest/framing/media/input fixtures through Go, Rust, Swift, gateway transport, and fake Apollo without payload or provider-detail leakage
- [ ] 9.3 Pass fixture-backed gateway-only video/audio/input/reconnect/cancel/revocation integration and reject every direct-route/provider-field/downgrade case
## 10. Freeze and Qualification
- [ ] 10.1 Freeze exact source, Protocol/core artifacts, locks, settings, Xcode/toolchain, fake/provider fixtures, and environment; any change invalidates only its affected evidence plus the final gate
- [ ] 10.2 Run the single final clean-source Protocol `make verify`, Server generated-SQL/OpenSpec/full serial Go suite, Data `make verify`/race/resource gates, Cargo gates, and Swift/XCTest/XCUITest/accessibility suites
- [ ] 10.3 Qualify macOS 26/15/14 Apple Silicon platform behavior, lifecycle, performance/energy, privacy, uninstall/rollback preparation, and clean checkout; keep signing/publication/deployment/promotion separately authorized
- [ ] 10.4 Retain versions, hashes, logs, inventories, redacted metrics, failures, and exact requirement mapping; archive this change only when canonical specs match
- [ ] 10.5 Package but do not execute the owner E2E that binds Automatic/Custom requested and accepted width/height/FPS to the Apollo/SudoMaker virtual display through the gateway-only route; retain it as `deferred-owner-e2e`