Pi Daemon Dash v1 acceptance

Pi Daemon Dash v1 acceptance

This is the release receipt for bd-7de9ec. Its successful closure completes the parent Dash v1 epic bd-ba3623. It records measured production artifacts and live embedded/dedicated behavior rather than fixture-only claims. The final wall-clock soak is tracked at the end.

Exact candidate

Browser and backend evidence

The packaged production SPA presents an input-only web-credential screen. The credential is exchanged through same-origin POST /dash/v1/login; browser code receives an opaque HttpOnly, SameSite=Strict cookie and keeps only the CSRF token in memory. The service bearer never enters JavaScript, the URL, browser storage, static assets, logs, or workspace records.

Authenticated embedded acceptance loaded 100 bounded real inventory rows with a continuation cursor, no FIXTURE/Local fixture marker, and a real persisted Pi active-branch transcript. Double-clicking an unmanaged session painted preview records while the status remained not hydrated; an immediate service session listing remained empty, proving that preview submitted no model turn and opened no runtime.

A separate live pi-daemon web process on port 7475 connected to the same API through RemoteDashboardBackend, authenticated its own browser credential, rendered the same non-fixture production inventory, and then stopped without a listener leak. This proves the same SPA/BFF behavior in embedded and dedicated modes without in-process coupling.

Live Rich hydration reads Pi's supported active-context usage rather than inventing a value from transcript totals. The browser renders the SDK percentage when available, refreshes it after turn/model/compaction/tree/reconnect changes, and renders Unknown while the SDK estimate is absent. A missing field can therefore never appear as 0%; an actual zero remains distinguishable and measured.

Performance and bundle receipts

Machine-readable values are checked in at ../web/artifacts/performance.json.

Measure Result Contract Outcome
Navigation to first rows, p95 11.1 ms <150 ms pass
App-ready to first rows, p95 1.3 ms <150 ms pass
10k in-app search work 0.3 ms <100 ms pass
Max stream/workspace/TUI commit 1.9 ms <16 ms pass
Initial production gzip 123,722 bytes <1.5 MiB pass
Complete production gzip 370,748 bytes <1.5 MiB pass

The inventory implementation independently passes persisted 10,000-session hot bootstrap, bounded search, stale-index, reconcile, tamper and cache limits. The browser virtualizes both session and transcript rows; retained TUI state remains a 64-entry/32 MiB LRU with a 512 KiB per-frame contract.

Automated gates

The macOS default temporary directory can exceed Unix sun_path after the long managed checkout prefix; adapter socket acceptance therefore uses canonical fixture roots and the explicit /tmp test environment. Product socket path, owner, mode and symlink checks remain strict and were not weakened.

Post-v1 session-tree receipt

The bd-4b2415 follow-on adds the full branch navigator without changing the active-branch transcript contract. The checked-in visual receipt is ../web/artifacts/nord-midnight-session-tree.png: it shows the exact active path/leaf beside a selected abandoned branch, controller-gated fork/edit/navigate/summarize/clone actions, and side-by-side divergence from their common ancestor.

The refreshed machine receipt records an 801–803 ms cold lazy-chunk + command + paint path for the representative tree and a 902 ms cold 10,000-entry tree path. Only 30 tree rows existed in the DOM for the 10,000-entry fixture. Pure bounded 10,000-node validation/projection has a 250 ms unit budget, animation-frame p95 was 9.2 ms against the 16 ms frame-work contract, and stream/workspace commit work remained 1.3 ms. Current follow-on gates are Node 389/389, Web unit 76/76, and Playwright 20/20. Focused Playwright acceptance covers keyboard Home/End/Left/Right selection, active-leaf ARIA truth, filtering, branch compare, edit-resubmit prefill, summarize/navigation, and O(visible) DOM behavior.

Security and failure-state evidence

Acceptance covers exact Host/Origin/CSRF checks, CSP and immutable hash assets, input-only credentials, traversal/symlink/writable-file refusal, malformed and oversized HTTP/WebSocket frames, connection capacity, slow clients, replay gaps, stale generation/host identity, controller conflicts, idempotency conflicts, indeterminate accepted commands, external-write conflicts, bounded preview caches, settings/workspace revisions, reduced motion, forced colors, keyboard navigation, Vim/IME input, and screen-reader-labelled dialogs.

The current Pi SDK still lacks the supported host-safe InteractiveSessionView factory. TUI capability therefore fails closed in production instead of starting a child Pi, PTY, second extension binding or second JSONL writer. The complete canonical ShadowTuiHost, authenticated TUI adapter, browser grid and component fixtures pass their frame, replay, controller, accessibility and performance gates and become available only when that public seam is injected.

Wall-clock performance budgets are opt-in

Every millisecond budget in this document is verified by explicit manual acceptance, never by the standard suite, package build, Nix evaluation, or installation gate. Percentile bounds are meaningful only on a quiet reference machine; on a shared or Nix builder host a correct implementation can miss them purely through scheduling contention, which produces a red gate that says nothing about the code and has already blocked a release pin once.

The measurements still run in the standard suite and print as diagnostics, so regressions stay visible, and the exercised code paths keep their full correctness coverage. Only the assertion is deferred. Enforce budgets on an idle host with:

npm run test:manual:performance
npm run test:manual:inventory-performance

The first sets PI_DAEMON_PERFORMANCE_BUDGETS=1, which turns the shared reportPerformanceBudget helper from a diagnostic into a hard assertion for transcript projection, remote Rich streaming, the Shadow TUI host, and the virtual terminal. The second runs the 10,000-session inventory percentile acceptance. A failure in either is a real regression signal.

Browser-safe diagnostics acceptance

The diagnostics slice proves service-bearer authentication on GET /v1/dashboard/diagnostics, browser-cookie authentication plus global administrator authorization on GET /dash/v1/diagnostics, Cache-Control: no-store, capability gating, and endpoint parity in embedded/dedicated modes. A bounded-ring test overflows 128 events and confirms old entries are evicted; malicious identifiers/error strings are reduced to route templates, fixed messages, and safe codes. Contract fixtures assert rawLogsExposed: false and scan for credentials/private paths. Browser acceptance verifies the discreet button remains below Settings, opens an accessible modal, refreshes, reports policy/config status, renders recent failures, and closes without mutating service state.

Multi-user authorization administration acceptance

The administration slice proves that session/workspace policy reads require resource admin; grant set/revoke and ownership transfer require matching CSRF, request/idempotency headers, body keys and policy ETags; retained retries do not repeat a mutation; and a conflicting key fails. Shared workspace listing exposes only authorized workspaces, selection changes only server-side browser session state, and revocation immediately invalidates matching cookies and streams. Absent and unauthorized policy paths retain the same content-free response.

Controller acceptance uses two live identities and records the call order: old controller release completes before target grant begins. A failed target grant leaves no controller and never silently restores the old one. Successful handoff requires target control, exact policy and controller revisions, retains one idempotent result, and persists exactly one content-free audit event. The accessible Access dialog exercises grants, revocation, owner transfer, workspace selection, active participant selection and audit without receiving credentials, canonical paths or the daemon bearer.

Installed Pi package inheritance acceptance

Package inheritance is absent by default and activated only by the persisted inheritInstalledPackages resource authority. Acceptance uses local and managed npm package fixtures with real Pi manifests/filters, proves only enabled extension/skill/prompt/theme paths reach the isolated session resource loader, and verifies browser defaults contain neither package declarations nor install paths. Missing packages, insecure settings and malformed filters fail with content-free typed errors before SDK session creation.

A fake npm executable and marker prove both installed and missing npm cases invoke no package-manager process. The resolver first maps configured npm/git/ local declarations to existing user-scope install paths, then gives the Pi SDK absolute local paths only, making install/update/reconcile/network paths structurally unreachable. The configured package cache remains a bounded read-only source; Pi CLI is its sole installer.

Multi-user activation and migration acceptance

The final activation matrix runs the same configured static provider through embedded and dedicated server construction and through the dedicated CLI. Strict main YAML and provider-document parsers accept only bounded identity metadata and one unique credential file/inherited descriptor source per identity; literal credentials and unknown/duplicate/no-administrator/insecure sources fail startup. Provider mode creates no fallback web-token, browser logs contain neither the identity credentials nor the separate remote API bearer, login ignores a browser-supplied workspace, and bootstrap exposes only the authenticated principal's informational signed-in-as label.

A restart migration begins in exact generated-token local-owner mode, persists a legacy workspace/policy, restarts against the same state with a configured administrator, rejects the old web token, and proves the administrator can list and transfer the retained legacy workspace. Removing the provider remains the explicit compatibility rollback. Existing provider-revalidation tests revoke or role-change a principal with an active cookie/channel; policy tests restart from retained grants/idempotency, fail closed on corrupt/insecure state, and roll memory back on publication failure.

No-existence-leak acceptance compares the complete absent/unauthorized HTTP error shape and the bounded backend work shape, scans inventory through principal/query-bound opaque cursors without unauthorized-only continuation, and denies cross-session workspace, draft, ticket, export and schedule access. Controller tests record release-before-grant order and failed-grant no-restore. Storage, identities, policies, grants, audit, idempotency, browser sessions, connections, queues, frames and responses all retain explicit limits. Fixture, package and browser-source scans reject credential, bearer, prompt and canonical path material; both deployment modes preserve the machine-bearer/browser-identity separation.

Lazy new-session integration acceptance

Parent bd-e9fce1 is complete on main through three independently landed and then jointly validated slices:

The combined focused matrix passed 71/71 Node tests and 61/61 web tests. It proves draft create/get/cancel cause zero factory opens, RPC calls, SDK/model/tool work, controller acquisition, or subprocess creation; concurrent duplicate first sends create one deterministic session and admit one prompt; embedded and remote backends share the same durable ticket/reconciliation semantics; restart resumes only pre-prompt checkpoints; prompt-submitting crashes and cancellation races become non-replayable indeterminate outcomes; and browser refresh restores the draft without duplicating its optimistic first message.

Live rolling acceptance on exact 2c0eb74 authenticated the packaged production New Session flow and opened the polished lazy draft. The daemon session-list response was byte-identical before and after draft creation, proving that the browser performed no eager logical-session/runtime/SDK/model/tool work. The Nix rolling update passed, and the cookie-reuse soak absorbed an intentional restart with zero failures.

Final parent validation on current main passed npm test 356/356 and the full nix flake check, including clean npm pack/import, Pages, Home Manager module, installed binaries, and production web build. No acceptance condition was waived and no eager Session API create path was reused behind the browser.

Post-v1 native transport hardening

Follow-on bd-e89a17 adds native HTTPS/WSS without replacing the recommended loopback reverse-proxy deployment. Focused acceptance covers bounded owner-mode certificate/key files and inherited descriptors, TLS 1.2 minimum, exact SNI, Host and Origin, HSTS, Secure __Host- cookies, plaintext downgrade refusal, content-free remote health, default-rejected and exact loopback proxy headers, default non-loopback plaintext refusal, and live atomic certificate rotation that keeps the listener available. Dedicated pi-daemon web acceptance loads relative instance-YAML secret paths and serves the packaged production SPA over HTTPS while retaining its server-only service bearer. See Dashboard transport security for the full configuration and failure contract. Follow-on bd-6f6ae1 preserves that default refusal while accepting only typed non-loopback plaintext with an exact public origin plus explicit opt-in and a content-free startup advisory.

Wall-clock soak

The initial acceptance harness deliberately performed a fresh credential exchange every minute. After 374 successful logins it reached the configured browser-session capacity and received bounded 503 responses—correct fail-closed product behavior, but not representative of a browser that reuses its HttpOnly cookie. That exploratory receipt is retained owner-privately as dashboard-soak-capacity-finding.jsonl; no credential or session content was recorded.

The cookie-reuse harness then ran from 2026-07-19T09:07:03Z through an external default-tmux server teardown at approximately 13:05Z with zero product failures. The daemon and soak tmux sessions disappeared together without a daemon drain/crash record, so this was operator/process-supervisor interruption, not an availability result. The helper now uses its own named tmux socket so an unrelated default tmux kill-server cannot remove the test service.

The final uninterrupted 24-hour owner-private rolling soak started at 2026-07-19T14:28:50.562Z against the embedded test BFF on dedicated tmux sockets and completed at 2026-07-20T14:28:50.569Z. It reused one cookie like the production SPA, re-authenticated only after intentional atomic exact-main daemon upgrades, and every minute requested the packaged SPA plus bootstrap, real inventory and settings. It recorded only timestamps, bounded status, latency and row counts—never credentials or session content—under ~/.local/state/pi-daemon/test/soak/.

The final summary is pass: 86,400,007 ms uninterrupted wall time, 1,440 checks, zero failures, zero consecutive failures, and 698.95 ms maximum end-to-end check latency including controlled restart/reconcile windows. The last sampled request at 2026-07-20T14:28:23.722Z was healthy; the harness remained alive through the exact deadline and wrote its summary seven milliseconds after 24 hours.

After the soak, the unchanged final 65cef84 candidate passed ambient npm 357/357, web unit 62/62, Playwright 16/16, npm audit with zero findings, and cached exact nix flake check package/Pages/Home Manager gates. A fresh live dedicated pi-daemon web on port 7475 authenticated against the exact embedded API, rendered real non-fixture inventory, painted a scrollable transcript with its footer visible, and exposed both Direct co-opt and Safe fork before shutting down without a listener leak. No gate was waived. Release tagging remains an explicit operator action.