Instance key provision: rev 3 planner's report
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+54
−0
docs/superpowers/plans/INSTANCE-KEY-PLAN-REPORT-R3.md+54 −0
CI cancelled — superseded by a newer push — run details
diff --git a/docs/superpowers/plans/INSTANCE-KEY-PLAN-REPORT-R3.md b/docs/superpowers/plans/INSTANCE-KEY-PLAN-REPORT-R3.md| new file mode 100644 |
| index 000000000..1eb5718d6 |
| --- /dev/null |
| +++ b/docs/superpowers/plans/INSTANCE-KEY-PLAN-REPORT-R3.md |
| @@ -0,0 +1,54 @@ |
| +# Instance key provision (L21): plan report, rev 3 |
| + |
| +**Status:** rev 3 of the plan is written and committed. It answers Astra's round 2 (`CODEX-PLAN-INSTANCE-KEY-R2.md`) under Paul's rulings R-A to R-F, which are the plan's rulings 19 to 24. Nothing is pushed. |
| +- **Branch:** `instance-key-build`, worktree `/home/paulca/amadan.net/carlos/platform/.claude/worktrees/instance-key-provision` |
| +- **Plan:** `docs/superpowers/plans/2026-10-10-instance-key-provision.md`, rev 3, commit 3947e1d9 |
| +- **Tasks:** 7, then the final verification. Task 5 is now the adoption verb and its publication, and is mounted nowhere on main. Task 7 lost `ConfiguredInstanceKey`. |
| + |
| +## Dispositions (round 2) |
| + |
| +| # | Finding | Disposition | |
| +|---|---|---| |
| +| R2-1 | A configured key still bypasses the refusal (configured A, own B) | Accepted: source (c) dropped; configured keys need an adoption record too | |
| +| R2-2 | Configuration evidence neither identifies nor pins the key | Accepted: the record names the key by digest; the pin carries it; the install verifies it | |
| +| R2-3 | An adoption record outlives its writer | Accepted: the record binds host, incarnation, session and generation from the agent's launch state; every admission starts with none | |
| +| R2-4 | No publication on the running session; O6 not gated | Accepted: `hostfiles.PlatformRelay` onto the session's publisher; O6 a gate in O4 | |
| +| R2-5 | Moves leave the record behind | Accepted: O7 with the exact lists; O6 does not ship before O7 | |
| +| note | The record is tenant-forgeable | Answered by ruling 19 (trusted-helper assertion) | |
| +| R1-6 | The merge option | Closed: withdrawn by Astra | |
| + |
| +**Counts:** 5 accepted, 0 declined. One note answered, one round 1 finding closed. |
| + |
| +## What changed in the code |
| + |
| +- `instancekey`: the record is now version 2 and writer-bound (`Binding`, `ParseAdoption`, `Binds`). New: the sources (`SourcePlatform`, `SourceConfig`, `SourceOf`) and `VerifyDelivered` for the install. |
| +- `ClaimLaunchSnapshot` gains `InstanceKeySHA256` and `InstanceKeySource`, read from the same two files as the env; the identity is unchanged. |
| +- The adoption verb (`MountInstanceKeyAdoption`) takes its writer, key digest and source from an `AdoptionLaunch` that O6 builds per launch. It is no longer mounted on legacy launches. |
| +- New `hostfiles.PlatformRelay` stages a platform item on a running publisher without blocking the caller. |
| +- O2' for stage B is now (a) or (b'), with the pinned key in `PinObject.InstanceKey`. It replaces stage B's own rev 3 `KeyEvidence` reader. |
| + |
| +## How it was checked |
| + |
| +- Every Go block in Tasks 1 to 7 was built in a scratch copy, then rebuilt task by task in a second copy, with `go vet` and `gofmt -l` clean after each task. Both copies ended byte-identical. The plan's blocks were then extracted back out of the document and compared with the scratch files, byte for byte. |
| +- `go build` for windows, darwin and linux/arm64 of activator, host, hostfiles, instancekey and appconfig, and `go vet` on darwin: clean. |
| +- **Tests run**, niced: |
| + - all new tests; |
| + - the activator `Seed`, `Start`, `Prepare`, `Control`, `Schedule`, `Claim` and `LaunchEnvironment` families, with the sandbox off for sockets; |
| + - the host claim and env report tests; |
| + - all of `instancekey`, `hostfiles`, `moves` and `moves/archive`. |
| + |
| + All passed. The full `go test ./internal/host/ -run Claim` also passed, in 1112 seconds. It exceeds go test's default 10-minute timeout on this shared box because of an existing 30,000-delivery test (`TestClaimCompletedProducersBoundStopAndRetry`, 1015 seconds), so the plan's sandbox note now says to pass `-timeout 30m`. |
| +- **O2' was compiled and run against stage B** at 919662d2, in a scratch copy with `internal/instancekey` added. `go build ./internal/...` and `go vet` were clean, and `go test ./internal/hostrelocate/` passed: 17 evidence cases, plus every existing pinner test. |
| +- Scratch copies are deleted. The shared `$TMPDIR/gocache` is untouched. |
| + |
| +## The rastrillo addendum |
| + |
| +The helper reports on every process start (at most once per process), and the body adds `"source": "platform" | "config"`, copied from a new agent-set `$CARLOS_INSTANCE_KEY_SOURCE`. It is in the plan's "Ask for rastrillo #66" section, ready to post. |
| + |
| +## Top concerns |
| + |
| +1. **The helper cannot know the source by itself.** A platform key and a configured key both arrive as `$CARLOS_INSTANCE_KEY`. The plan has the agent deliver `CARLOS_INSTANCE_KEY_SOURCE` beside it (agent-owned, part of O6) for the helper to echo, and the agent checks the echo against its own launch state. If Paul would rather not add a variable, the `source` field could be dropped from the request, because the agent already knows the source. |
| +2. **Nothing writes a record until O6 and O7 land.** The verb is built and tested but mounted nowhere: legacy launches have no writer session to bind to, and claim launches have no control socket. Platform-key and configured-key apps therefore do not relocate until claim Plan 9 Group D (O6) and the moves change (O7) ship, in that order. That is the explicit refusal of ruling 23. |
| +3. **A configured key's digest is published.** A `config` record puts the SHA-256 of a configured secret in the data bucket. That reveals nothing for a random key; a weak, hand-typed key could be guessed against it. It is listed as a follow-up. |
| +4. **Stage B has its own diverging O2' in plan text.** Its rev 3 (919662d2) has the `KeyEvidence` reader, with presence-only config evidence and the `export` parser. Stage B's planner must replace that step with this plan's O2' and rewrite its ruling 55, as O2' says. |
| +5. **One report lost to box loss inside the publisher's bound.** A box lost within that bound (a second by default) after the first adoption loses that report. The pin then refuses until a later session re-reports. That is safe, but worth knowing. |