COMPANION-APP-PHASE-5-SESSION-PROMPT.md markdown
94 lines 6.4 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 2 days ago

Phase 5 Implementation — Next-Session Prompt

Use a fresh session. Model: Claude Sonnet (latest) / Cursor Auto (⚡ — implementation against an already-ratified contract). Escalate to a thinking model ONLY if a security-tier test reveals a genuine ambiguity in the Phase 5 contract — stop and ask rather than guessing.


You are implementing Phase 5 — the Companion App shell on Muse branch feat/companion-app.

This is the ⚡ implementation phase against an already-ratified design. The bind gate docs/COMPANION-APP-PHASE-5-BIND-GATE.md (D5.1–D5.8) was owner-approved 2026-06-06. Do not re-litigate the design — implement it exactly. If you find a real gap in the contract, stop and ask; do not silently deviate (Aaron's Rule #1/#2).

Read first (in full)

  • docs/COMPANION-APP-PHASE-5-BIND-GATE.md — the ratified contract you are implementing (D5.1–D5.8, threat model P-a…P-k, §11 test obligations, §0 scope boundary).
  • The four pure cores you are wiring (do not modify their security invariants):
    • lib/companion-loopback-guard.mjs (Phase 2 — verifyLoopbackRequest)
    • lib/companion-oauth-pkce.mjs + lib/companion-token-custody.mjs (Phase 3)
    • lib/companion-runtime-manager.mjs (Phase 4 — lifecycle/admission/integrity/resources)
    • lib/model-runtime-lane.mjs (Phase 1 — selectLane, companionAvailable seam)
  • hub/gateway/native-oauth-provider.mjs (the server you authenticate against — /api/v1/auth/native, emits iss, loopback variable-port, scope ceiling). ✅ already implemented.
  • lib/daemon-llm.mjs + lib/llm-complete.mjs (the OpenAI-compatible call path the runtime speaks — reuse with base_url = http://127.0.0.1:<port> or the UDS).
  • test/helpers/companion-keychain-fake.mjs (the in-memory keychain fake already on the branch — use it in tests; the real adapters are what you build).

What to build (run-from-source; NOT packaging — that's Phase 7, §0)

Real I/O adapters + the orchestration/shell that wires the pure cores. Suggested module layout (adjust names if a better fit, but keep one concern per file):

  1. Keychain adapter (D5.3)lib/companion-keychain-adapter.mjs (+ per-OS backends): { get, set, delete } on the four KEYCHAIN_ACCOUNTS only; reject unknown accounts; macOS Keychain …WhenUnlockedThisDeviceOnly (no iCloud sync), Windows per-user DPAPI, Linux libsecret; no plaintext fallback (fail-closed when locked/unavailable). Pick the OS backend at runtime; shell out to security/secret-tool or use a vetted native binding — document the choice.
  2. Inference listener + Phase 2 guard front-door (D5.1)lib/companion-inference-listener.mjs: listen(0,'127.0.0.1') (or [::1]), build allowedHosts from the bound port, call verifyLoopbackRequest before any model work, never emit permissive CORS, no SO_REUSEPORT, hard-abort if loopback bind fails.
  3. OAuth redirect listener + flow driver (D5.2)lib/companion-oauth-flow.mjs: separate one-shot ephemeral loopback listener, open the system browser with buildAuthorizationUrl, validate the callback with validateAuthorizationResponse({..., expectedIssuer}), POST the token request over TLS (full cert verification), store via custody.
  4. Spawn adapter (D5.4)lib/companion-spawn-adapter.mjs: spawn/kill/healthCheck; absolute binary path, shell:false, argv array, scrubbed child env (no SESSION_SECRET/*_API_KEY/JWT/ tokens/keychain refs), process-group, loopback/UDS-0600 bind flag; detect-and-reclaim a stale runtime on start.
  5. Download adapter (D5.5)lib/companion-download-adapter.mjs: dumb HTTPS-only streaming byte pump (download(url, onChunk)), full TLS verification, no integrity decision in the adapter. The orchestrator owns createIntegrityAccumulator + finalize(), atomic temp→verified move, and the first-party out-of-band manifest fetch (trust anchor — NOT from the model host).
  6. Resource probe (D5.6)lib/companion-resource-probe.mjs: runtime-PID-scoped RAM/CPU; VRAM aggregate-only, never enumerate other GPU processes; no privilege escalation; ≤500ms cache.
  7. Orchestrator / shell (D5.7, D5.8)lib/companion-shell.mjs: wires everything; computes companionAvailable (true only when integrity-verified ∧ lifecycle ready ∧ recent health round-trip, recency-bounded; false on any doubt); enforces object-capability segregation — the runtime group (spawn/download/health/stat) is constructed with no reference to the authority group (keychain/JWT/canister).

Hard constraints

  • Muse-canonical, stay on feat/companion-app. No git/gh for this tree.
  • Fail-closed at every bind/custody/spawn/download/probe point.
  • No secret in any log, error, adapter interface, or redirect (loopback token, JWT, refresh token, code, code_verifier, SESSION_SECRET, digest, model path).
  • Do not change the pure cores' security invariants or the server-side OAuth provider.
  • Do not do packaging/signing/notarization/auto-update (Phase 7), new storage paths (Phase 6), or new server routes (none needed).

Tests (Aaron's Rule #0 — all 7 tiers before any merge to main)

Per PHASE-5-BIND-GATE.md §11. Centerpiece security tier MUST include: loopback-only bind (reject 0.0.0.0/::/routable); DNS-rebinding + cross-origin still 403 at the front-door; runtime back-end carries no authority + no CORS; keychain surface minimal + device-local; child-env contains no secret; architecture/import test: runtime group imports no authority module (build-blocking); manifest trust-anchor out-of-band from the model host; resource probe never enumerates other GPU processes; companionAvailable fail-closed; no secret in any output.

Suggested order

  1. Keychain adapter (+ 7 tiers) — everything else depends on custody.
  2. Inference listener + guard front-door (+ 7 tiers).
  3. Spawn + download + resource adapters (+ 7 tiers each).
  4. OAuth flow driver (+ 7 tiers; stub the browser-open in tests).
  5. Orchestrator/shell (+ integration/e2e: sign in → manifest → download → verify → spawn → health → companionAvailable=true → enrich locally; plus the architecture/env-scrub security tests).
  6. Run the full suite once, fix all failures, re-run only the failed files, then full suite as the final gate. Commit on feat/companion-app via Muse.
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 2 days ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 2 days ago