# Packet W1 receipt — durable Project Host + command envelope **Actor:** Helios (Cursor on Icarus, `centaur-macmini-1`) **Composer:** Mitchell Burns **Date:** 2026-09-13 **Work order:** [`ASTRA_WORK_ORDERS.md`](ASTRA_WORK_ORDERS.md) W1 **Contract:** [`ASTRA_INTERFACE_CONTRACT.md`](ASTRA_INTERFACE_CONTRACT.md) §1–2, §7–8 This file is a chip receipt. It does not rewrite [`ASTRA_DESIGN.md`](ASTRA_DESIGN.md) or the freeze JSON zip identity. --- ## Context snapshot | Field | Value | |---|---| | `plan_branch` | `cursor/w1-durable-host-0101` | | `base` / `master_sha` | `4d355a5994467bbe64dc28b9b5817037e25a02ce` (`cursor/astra-gates-0101` W0 freeze tip) | | `tip` | branch `cursor/w1-durable-host-0101` HEAD (Helios handback names the live SHA) | | `sync_method` | bootstrap (isolated worktree from freeze tip; no rebase onto later W5/W6) | | `colliding_prs` | W5 audio (`cursor/w5-audio-import-0101`), W6 export (`cursor/w6-movie-export-0101`) — separate worktrees. This chip did not touch `wav.ts` or `mux-webm-av.ts`. | | `blocking_owner_items` | W2 identity: Better Auth `/login`, fail-closed production, session-minted bindings, session revocation | | `non_claims` | listed below | Worktree: `/Users/icarus/.cursor/worktrees/korgi-w1-durable-host-20260913` Remote: **gdrive only**. No `origin` push. No FF `main`. No Railway. Freeze zip/tgz untouched. --- ## What landed `ProjectHost` is no longer an in-process Map pretending to be a store. 1. **Packed authority.** `ProjectHost.pack()` still writes the `.korgi` document, then embeds `host/authority.json` (hashed binding tokens, grants, actors, invalidated flags, and the `(projectId, operationId)` log) in the same zip. `unpackKorgi` ignores that member; document checksum is unchanged. Opening the pack restores **authority**, not only pixels. 2. **Process cache.** `getAuthoritativeHost()` is a cache. `teardownAuthoritativeHost()` drops it. With `setAuthoritativeHostPackPath`, a later `getAuthoritativeHost()` reopens the same pack (atomic write: tmp + rename). Without a path, tests pass the packed bytes into a new `ProjectHost.openPacked`. 3. **Envelope.** `execute` takes `operationId`, `expectedRevision`, `destination`, `bindingId`. Authenticated `actor` is the **binding actor**; a client-supplied `actor` is ignored. Payloads that already name `destId` still work; envelope `celId` must match when both are present. Wrong `projectId` refuses. 4. **Incomplete ingest.** `korgi.draw.ingestScan` without PNG bytes or complete cel planes refuses *before* `executeAction`. Previous revision intact. Packet B staged ingest injects remain. 5. **Background jobs.** Shop HTTP (`/api/korgi/generate`) still returns bytes only. `executeAction` on a clone does not assign `host.project`. `refuseBackgroundProductionWrite()` is the named refuse for a worker that tries to commit without `host.execute`. 6. **Browser “saved”.** HTTP execute returns `saved`, `revision`, `operationId`, `receiptId`. `studio-host-bridge` sets `saved` only on that durable ack. Inspect/bind do not claim saved. IndexedDB is still a local cache. Studio chrome was not restyled. 7. **Idempotency.** Host log is keyed by `(projectId, operationId)` and packed with the document. Journal still records actor-keyed and `projectId:operationId` entries so reopen without authority metadata can still dedup. `tools/list` for a bound grant with `grant.actions` now lists those actions (Packet A HTTP session lists the two Packet A tools). That is a start. W2 still owns identity, `/login`, and revocation. Bindings are stored as SHA-256 of the presented token. The pack does not replay a raw UUID; a client that still holds the token hashes to the restored record. --- ## How durability was proven (not a singleton) `src/lib/korgi/host/project-host.w1.test.ts`: 1. Mint Packet A binding, `setName` with `operationId`, pack to a temp file, **`teardownAuthoritativeHost()`** (singleton is `null`), `getAuthoritativeHost()` reopens the file. Stale (never packed) binding refuses. The packed binding + expected revision succeeds (`setFollow`). The same bytes also restore via `createProjectHost().openPacked` — a second object, not the previous singleton. 2. Kill-and-restore: same `operationId` + payload after teardown is `deduplicated`; different payload refuses; name stays `Doorway` once. 3. Incomplete ingest fixture: no bytes/cel → `saved: false`, revision unchanged. 4. HTTP `executeStudioHostAction` returns `saved` + `operationId` + `receiptId`. Packet A refusal tests remain green on this tip. --- ## Files changed | Path | Why | |---|---| | `src/lib/korgi/host/project-host.ts` | Hashed bindings, operation log, pack sidecar, destination/actor, ingest gate | | `src/lib/korgi/host/authoritative-host.server.ts` | Teardown + pack-path restore; singleton is a cache | | `src/lib/korgi/host/host-http.server.ts` | Envelope + durable ack JSON | | `src/lib/korgi/host/studio-host-bridge.ts` | `saved` only after host ack; sends `operationId` | | `src/lib/korgi/host/project-host.w1.test.ts` | Kill-restore, stale binding, incomplete ingest, ack | | `src/lib/korgi/actions/types.ts` | `CommandDestination` on the envelope | | `src/lib/korgi/actions/execute.ts` | Destination fill; journal idempotency also keyed `(projectId, operationId)` | | `src/lib/korgi/mcp/from-registry.ts` | `mcpToolsForGrant` | | `src/lib/korgi/mcp/index.ts` | Re-export | | `src/lib/korgi/mcp/server.ts` | Grant-filtered `tools/list`; destination on host execute | | `src/routes/api/korgi/host.ts` | Forwards `destination` | | `src/lib/project-io.test.ts` | Extra `host/authority.json` still unpacks | | `docs/oss/PACKET_W1_RECEIPT.md` | This receipt | Did not edit `wav.ts`, `mux-webm-av.ts`, Studio chrome, Better Auth, freeze JSON, `ASTRA_DESIGN.md`. --- ## Tests (this tip) Commands (worktree tip; not a historical total): ```bash npx tsc --noEmit node --experimental-strip-types --test \ src/lib/korgi/evaluate-frame.test.ts \ src/lib/korgi/mcp/packet-a.test.ts \ src/lib/korgi/mcp/mcp.test.ts \ src/lib/korgi/packet-b.test.ts \ src/lib/project-io.test.ts \ src/lib/korgi/host/project-host.w1.test.ts ``` | Gate | Result | |---|---| | `npx tsc --noEmit` | pass | | `evaluate-frame.test.ts` | pass | | `packet-a.test.ts` | pass | | `mcp.test.ts` | pass | | `packet-b.test.ts` | pass | | `project-io.test.ts` | pass | | `project-host.w1.test.ts` | pass | SHA of the commit that contains these results is the branch tip after this receipt is committed. --- ## non_claims - Not a creator product. Not a release. No `main` land. No KORGI Railway redeploy. - Better Auth is still off. There is still no `/login` route. `dev-user` remains the local no-database convenience. **W2 is not done.** - User-minted bindings from a real session identity are still W2. - Session revocation does not yet invalidate grants (W2). - Destination-render quality gate (accepted-frame2 class) is still W2. - `tools/list` grant filtering is started for a bound `grant.actions` set. Unbound studio catalog is still the full registry. W2 still has to make identity the mint path. - Audio matrix (W5) and VP9/Opus export (W6) were not implemented here. - Studio chrome / canvas-first layout is still W4. - IndexedDB/OPFS remains a local replica. It is not the hosted document. - Paid Higgsfield/OpenAI stills were not run. PixelLab $0. --- ## What W2 still must do - Better Auth on; `/login` as a real route; fail-closed when `DATABASE_URL` is set; no silent `dev-user` in production. - User-minted bindings from the authenticated session id (never client-supplied). - Confirmation + session revocation invalidates grants; subsequent execute refuses. - Destination-render quality gate with an accepted-frame2-class fixture. - Keep Packet A + C recovery green on that commit. --- Helios, Icarus, 2026-09-13.