carlos / platform Public

docs: cohort-1 runbook: 7a.1 fix-forward, leo version grant applied, PR #46, box records

- 7a.1: the key policy's operator statement gains kms:GetKeyRotationStatus
  (the provider's refresh needs it); records the partial apply, the
  put-key-policy fix, the untaint, and the alias-only plan awaiting Paul.
- Blockers: v0.28.0 rolled on dev (resolved); leo's object-version
  actions applied for the trial; fence-writer role and box-records bucket
  policy planned in platform-infrastructure#46; new blocker: no box
  identity records exist (control/boxes/) because the publisher runs only
  with CARLOS_REGION_HA on, and step 5's enrollment needs them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 4df3d7248c580dacae38baa6a3ca80b2b38220f8 parent 555a317
1 file changed, +16 −6
  • docs/superpowers/plans/2026-10-16-claim-activation-dev-cohort1.md +16 −6

CI passed — run details

CI log
=== gate ===
cd launchctx && go vet ./... && go test ./... -count=1
ok  	amadan.net/carlos/platform.git/launchctx	0.012s
?   	amadan.net/carlos/platform.git/launchctx/controlname	[no test files]
?   	amadan.net/carlos/platform.git/launchctx/wireid	[no test files]
go vet ./...
gofmt -l .: clean
go test ./... -count=1 -timeout 30m
ok  	github.com/carlosframework/platform	312.200s
?   	github.com/carlosframework/platform/cmd/changelog	[no test files]
ok  	github.com/carlosframework/platform/cmd/console	3.061s
ok  	github.com/carlosframework/platform/cmd/moveprobe	92.187s
ok  	github.com/carlosframework/platform/cmd/zddprobe	0.702s
ok  	github.com/carlosframework/platform/internal/activator	249.659s
ok  	github.com/carlosframework/platform/internal/agentsock	0.018s
ok  	github.com/carlosframework/platform/internal/alerting	0.003s
ok  	github.com/carlosframework/platform/internal/analytics	0.020s
ok  	github.com/carlosframework/platform/internal/appconfig	2.497s
ok  	github.com/carlosframework/platform/internal/apperr	0.070s
ok  	github.com/carlosframework/platform/internal/applog	0.120s
ok  	github.com/carlosframework/platform/internal/awsinv	0.005s
ok  	github.com/carlosframework/platform/internal/boxchoice	0.004s
ok  	github.com/carlosframework/platform/internal/boxid	0.787s
?   	github.com/carlosframework/platform/internal/boxid/boxidtest	[no test files]
?   	github.com/carlosframework/platform/internal/boxid/internal/signtest	[no test files]
ok  	github.com/carlosframework/platform/internal/boxvolumes	0.009s
ok  	github.com/carlosframework/platform/internal/caps	0.013s
ok  	github.com/carlosframework/platform/internal/certwarm	0.002s
ok  	github.com/carlosframework/platform/internal/cgroup	0.696s
ok  	github.com/carlosframework/platform/internal/changelog	0.309s
ok  	github.com/carlosframework/platform/internal/claimactivation	0.024s
ok  	github.com/carlosframework/platform/internal/clamd	0.055s
?   	github.com/carlosframework/platform/internal/cliflag	[no test files]
ok  	github.com/carlosframework/platform/internal/console	405.642s
?   	github.com/carlosframework/platform/internal/controlname	[no test files]
?   	github.com/carlosframework/platform/internal/controlsock	[no test files]
ok  	github.com/carlosframework/platform/internal/dbdoor	6.221s
ok  	github.com/carlosframework/platform/internal/dbdoor/dbdoortest	0.009s
ok  	github.com/carlosframework/platform/internal/dbverify	0.004s
ok  	github.com/carlosframework/platform/internal/dnsrec	0.002s
ok  	github.com/carlosframework/platform/internal/docsite	0.005s
ok  	github.com/carlosframework/platform/internal/domains	2.410s
ok  	github.com/carlosframework/platform/internal/doorkey	0.006s
ok  	github.com/carlosframework/platform/internal/economics	0.003s
ok  	github.com/carlosframework/platform/internal/edge	44.900s
?   	github.com/carlosframework/platform/internal/edgeproof	[no test files]
ok  	github.com/carlosframework/platform/internal/edgesfile	0.008s
ok  	github.com/carlosframework/platform/internal/fleetapi	0.134s
ok  	github.com/carlosframework/platform/internal/gate	1.656s
ok  	github.com/carlosframework/platform/internal/genselect	0.016s
ok  	github.com/carlosframework/platform/internal/geo	0.017s
ok  	github.com/carlosframework/platform/internal/geoip	0.031s
ok  	github.com/carlosframework/platform/internal/historyreadback	0.155s
ok  	github.com/carlosframework/platform/internal/host	177.093s
ok  	github.com/carlosframework/platform/internal/hostactors	0.547s
ok  	github.com/carlosframework/platform/internal/hostbox	2.647s
ok  	github.com/carlosframework/platform/internal/hostclaim	0.563s
ok  	github.com/carlosframework/platform/internal/hostevidence	0.017s
ok  	github.com/carlosframework/platform/internal/hostexec	4.766s
ok  	github.com/carlosframework/platform/internal/hostfence	0.033s
ok  	github.com/carlosframework/platform/internal/hostfiles	10.395s
ok  	github.com/carlosframework/platform/internal/hostfloor	0.017s
ok  	github.com/carlosframework/platform/internal/hostguard	1.041s
ok  	github.com/carlosframework/platform/internal/hostops	1.662s
?   	github.com/carlosframework/platform/internal/hostops/fencerelease	[no test files]
ok  	github.com/carlosframework/platform/internal/hostops/internal/fencerelease	0.017s
ok  	github.com/carlosframework/platform/internal/hostquarantine	0.018s
ok  	github.com/carlosframework/platform/internal/hostrelocate	0.477s
ok  	github.com/carlosframework/platform/internal/hostresolve	0.153s
ok  	github.com/carlosframework/platform/internal/hostwrite	0.019s
ok  	github.com/carlosframework/platform/internal/infraview	0.020s
ok  	github.com/carlosframework/platform/internal/instancectl	5.214s
ok  	github.com/carlosframework/platform/internal/instanceexec	2.733s
ok  	github.com/carlosframework/platform/internal/instancefs	0.022s
ok  	github.com/carlosframework/platform/internal/instancekey	0.019s
ok  	github.com/carlosframework/platform/internal/instanceupdates	0.007s
ok  	github.com/carlosframework/platform/internal/layout	1.547s
ok  	github.com/carlosframework/platform/internal/lbhealth	0.003s
ok  	github.com/carlosframework/platform/internal/lease	9.799s
ok  	github.com/carlosframework/platform/internal/lease/leasetest	0.006s
ok  	github.com/carlosframework/platform/internal/ledger	0.017s
ok  	github.com/carlosframework/platform/internal/mail	0.184s
ok  	github.com/carlosframework/platform/internal/maintenance	0.087s
ok  	github.com/carlosframework/platform/internal/maintenanceexec	5.498s
ok  	github.com/carlosframework/platform/internal/maintenanceguard	0.081s
ok  	github.com/carlosframework/platform/internal/metrics	0.005s
ok  	github.com/carlosframework/platform/internal/moves	20.985s
ok  	github.com/carlosframework/platform/internal/moves/archive	0.815s
ok  	github.com/carlosframework/platform/internal/objstore	0.184s
ok  	github.com/carlosframework/platform/internal/ops	0.168s
ok  	github.com/carlosframework/platform/internal/park	0.204s
ok  	github.com/carlosframework/platform/internal/privatefile	0.004s
ok  	github.com/carlosframework/platform/internal/provision	18.050s
ok  	github.com/carlosframework/platform/internal/publicrelease	0.008s
?   	github.com/carlosframework/platform/internal/regionname	[no test files]
ok  	github.com/carlosframework/platform/internal/registry	5.413s
ok  	github.com/carlosframework/platform/internal/relay	7.227s
ok  	github.com/carlosframework/platform/internal/release	21.885s
ok  	github.com/carlosframework/platform/internal/rollout	3.651s
ok  	github.com/carlosframework/platform/internal/rolloutwords	0.004s
ok  	github.com/carlosframework/platform/internal/rootaws	0.006s
ok  	github.com/carlosframework/platform/internal/rootparticipation	0.060s
ok  	github.com/carlosframework/platform/internal/rootstate	0.028s
ok  	github.com/carlosframework/platform/internal/runs	0.582s
ok  	github.com/carlosframework/platform/internal/s3compat	0.005s
ok  	github.com/carlosframework/platform/internal/safefile	0.005s
ok  	github.com/carlosframework/platform/internal/schedule	2.503s
ok  	github.com/carlosframework/platform/internal/seeds	0.011s
ok  	github.com/carlosframework/platform/internal/sim/hostlife	8.809s
ok  	github.com/carlosframework/platform/internal/sim/litestreamfacts	4.166s
ok  	github.com/carlosframework/platform/internal/status	0.039s
ok  	github.com/carlosframework/platform/internal/steering	0.005s
ok  	github.com/carlosframework/platform/internal/stopevidence	0.248s
ok  	github.com/carlosframework/platform/internal/svcrole	0.002s
ok  	github.com/carlosframework/platform/internal/telemetry	0.004s
ok  	github.com/carlosframework/platform/internal/termfence	0.004s
ok  	github.com/carlosframework/platform/internal/tunnelclient	0.003s
ok  	github.com/carlosframework/platform/internal/unixdial	0.002s
ok  	github.com/carlosframework/platform/internal/updatewords	0.004s
ok  	github.com/carlosframework/platform/internal/usage	0.004s
ok  	github.com/carlosframework/platform/internal/version	0.002s
ok  	github.com/carlosframework/platform/internal/vet	1.551s
=== cross ===
--- shard 0 of 5 ---
cross-compiling darwin/arm64
--- shard 1 of 5 ---
cross-compiling darwin/amd64
--- shard 2 of 5 ---
cross-compiling linux/arm64
linux/arm64 carlos binary: 48824482 bytes (ceiling 52000000)
--- shard 3 of 5 ---
cross-compiling windows/amd64
--- shard 4 of 5 ---
cross-compiling windows/arm64
=== minio-contract ===
minio contract: arm64, minio RELEASE.2025-09-07T16-13-09Z, mc RELEASE.2025-08-13T08-35-41Z
  minio: cached, digest verified
  mc: cached, digest verified
  minio healthy on 127.0.0.1:20999
Added `local` successfully.
Bucket created successfully `local/contract-bucket`.
Bucket created successfully `local/denied-bucket`.
Created policy `contract-only` successfully.
Added user `scopeduser` successfully.
Attached Policies: [contract-only]
To User: scopeduser
  buckets and scoped user ready
=== RUN   TestDeliveredContractMinio
=== RUN   TestDeliveredContractMinio/put
=== RUN   TestDeliveredContractMinio/get_round-trips_the_body
=== RUN   TestDeliveredContractMinio/list_shows_the_key
=== RUN   TestDeliveredContractMinio/head_and_list_agree_on_the_version
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_its_own_object
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed
=== RUN   TestDeliveredContractMinio/delete_removes_it
=== RUN   TestDeliveredContractMinio/cross-bucket_denial
--- PASS: TestDeliveredContractMinio (0.02s)
    --- PASS: TestDeliveredContractMinio/put (0.00s)
    --- PASS: TestDeliveredContractMinio/get_round-trips_the_body (0.00s)
    --- PASS: TestDeliveredContractMinio/list_shows_the_key (0.00s)
    --- PASS: TestDeliveredContractMinio/head_and_list_agree_on_the_version (0.00s)
    --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload (0.00s)
    --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route (0.01s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed (0.00s)
    --- PASS: TestDeliveredContractMinio/delete_removes_it (0.00s)
    --- PASS: TestDeliveredContractMinio/cross-bucket_denial (0.00s)
PASS
ok  	github.com/carlosframework/platform/internal/objstore	0.024s
=== RUN   TestT4StorageProbeMinio
2026/10/17 23:50:10 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18DF76153DDEE96F, HostID: 7c420053e0fbcd7f41653fdd92ffa2802c903d05303b1aa15adc2e8bb65d183f, api error SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
--- PASS: TestT4StorageProbeMinio (0.01s)
PASS
ok  	github.com/carlosframework/platform/internal/host	0.022s
minio contract: PASS
diff --git a/docs/superpowers/plans/2026-10-16-claim-activation-dev-cohort1.md b/docs/superpowers/plans/2026-10-16-claim-activation-dev-cohort1.md
index 1d8cf4206..2b7cada44 100644
--- a/docs/superpowers/plans/2026-10-16-claim-activation-dev-cohort1.md
+++ b/docs/superpowers/plans/2026-10-16-claim-activation-dev-cohort1.md
@@ -191,9 +191,10 @@ Pass: all twelve are root-owned regular files in `/etc/systemd/system`; the edge
## Blockers
-1. **Release.** No published release yet contains 26065378 (Plan 14 Parts 2 and 3, the activation tools) or e8e961dd (the empty-app writer fix). v0.28.0 is being cut from 26065378. Step 1.
+1. **Release.** Resolved: v0.28.0, cut from 26065378 (Plan 14 Parts 2 and 3, the activation tools, e8e961dd), is fully rolled on dev (2026-10-18). Step 1.
2. **Empty app segment.** 267 objects under `apps/bab//` (P5). Source: leo's app-less `proof*` routes, removed (2026-10-16). Cleanup waits for the e8e961dd release to reach leo and for Paul's approval. Step 2.
-3. **IAM.** Leo's role lacks the version actions, and dev has neither the deployment bucket policy nor a fence-writer role (P2). Step 3.
+3. **IAM.** Leo's object-version actions were applied on 2026-10-18 (targeted, `0 to add, 1 to change, 0 to destroy`): the claim's data store lists, reads and deletes object versions in `carlos-dev-ie-640012953448` on the seed and cold-wake paths. The fence-writer role and the deployment bucket policy are planned in carlosframework/platform-infrastructure#46 (`5 to add, 0 to change, 0 to destroy`), not applied. Step 3.
+4. **Box identity records.** Step 5's enrollment needs each box's signed AWS identity record at `control/boxes/<box>.json`. None exists, and none has ever been written: the publisher (`internal/host/boxrecord.go`, `boxRecordLoop`) runs only with `CARLOS_REGION_HA` on, which is off on every dev box. Leo's and sophie's records must be published before step 5, by turning region HA on for them or by a reviewed one-off publish. Open question 4.
## Accepted trial gaps
@@ -204,7 +205,7 @@ Paul deferred these for this trial only. They are not blockers here, and they mu
## Owed before production cohorts
-- **Dev module drift.** A whole-root `tofu plan` of `platform-infrastructure/dev` on 2026-10-17 showed 15 adds and 1 change that come from the platform modules (pinned `?ref=main`) moving ahead of dev: termination SQS queues and EventBridge rules for both IE boxes, the deployment bucket's lifecycle rule and its box-records bucket policy, leo's object-version actions (`host_buckets` gains `PullDoorObjectVersions`, `s3:DeleteObjectVersion` and `PullDoorVersionList`), and an SSM parameter scope policy on both IE roles (a deny on parameter reads outside `/carlos/*`). It is owed: its own plan and Paul's approval later, before production cohorts. It is not part of step 7a, whose plan is targeted at its own three resources. Step 3's IAM overlaps it (see open question 3).
+- **Dev module drift.** A whole-root `tofu plan` of `platform-infrastructure/dev` on 2026-10-17 showed 15 adds and 1 change that come from the platform modules (pinned `?ref=main`) moving ahead of dev: termination SQS queues and EventBridge rules for both IE boxes, the deployment bucket's lifecycle rule and its box-records bucket policy, leo's object-version actions (`host_buckets` gains `PullDoorObjectVersions`, `s3:DeleteObjectVersion` and `PullDoorVersionList`; applied for the trial on 2026-10-18), and an SSM parameter scope policy on both IE roles (a deny on parameter reads outside `/carlos/*`). It is owed: its own plan and Paul's approval later, before production cohorts. It is not part of step 7a, whose plan is targeted at its own three resources. Step 3's IAM overlaps it (see open question 3).
## Step 1. Release and roll, claims off
@@ -609,7 +610,15 @@ Paul's go: separate gate, for creating the key, its policy and leo's temporary r
The operator principal in the key policy is `arn:aws:iam::640012953448:user/remote-agent`, the user behind profile `kass`. platform-1e will state this when taking 7a.1 to Paul. It must also be the principal that runs `tofu apply`, or the key policy lockout check refuses the key.
-Dev's infrastructure is OpenTofu in `platform-infrastructure/dev`, so the key is declared there. The file is on branch `claim-cohort1-fence-kms`, PR carlosframework/platform-infrastructure#45 (opened 2026-10-18 on Paul's go for a plan and PR only; not applied). Its content:
+Dev's infrastructure is OpenTofu in `platform-infrastructure/dev`, so the key is declared there. The file is on branch `claim-cohort1-fence-kms`, PR carlosframework/platform-infrastructure#45 (unmerged).
+
+Status on 2026-10-18 (Paul's go to apply):
+- The first apply created `aws_iam_role_policy.cohort1_fence_read` and the key `ef26a257-fc1d-4fe3-ad9e-77a4b7b789f6`, then failed reading the key back: the provider's refresh calls `DescribeKey`, `GetKeyPolicy`, `GetKeyRotationStatus` and `ListResourceTags` (CloudTrail), and the operator statement lacked `kms:GetKeyRotationStatus`. The key was left tainted and the alias was not created.
+- Fix forward, approved: `kms:GetKeyRotationStatus` added to the operator statement (the file below); the live key policy replaced with that exact rendering by `aws kms put-key-policy` without the lockout bypass (equal to the file apart from AWS storing the one-element `Principal` list as a string; the operator keeps `ScheduleKeyDeletion`, `CancelKeyDeletion` and `PutKeyPolicy`); `tofu untaint aws_kms_key.cohort1_fence`.
+- A fresh targeted plan shows `Plan: 1 to add, 0 to change, 0 to destroy.` (the alias only). Not applied; it waits for Paul's go.
+- The alias refresh uses `ListAliases`, an account-level action covered by the operator's IAM policy, not the key policy.
+
+Its content:
```hcl
# platform-infrastructure/dev/cohort1-fence-kms.tf
@@ -650,7 +659,7 @@ resource "aws_kms_key" "cohort1_fence" {
Effect = "Allow"
Principal = { AWS = local.cohort1_operator_arns }
Action = [
- "kms:DescribeKey", "kms:GetKeyPolicy", "kms:PutKeyPolicy",
+ "kms:DescribeKey", "kms:GetKeyPolicy", "kms:GetKeyRotationStatus", "kms:PutKeyPolicy",
"kms:ListResourceTags", "kms:TagResource", "kms:UntagResource",
"kms:EnableKey", "kms:DisableKey", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion",
"kms:CreateAlias", "kms:UpdateAlias", "kms:DeleteAlias", "kms:ListGrants", "kms:RevokeGrant",
@@ -1382,4 +1391,5 @@ Answered: dev-uk is out of this trial; the console is enrolled by the activation
For platform-1e:
1. Should `hostops.Apps` skip an empty app segment instead of refusing, so one stray object cannot stop activation on a whole deployment?
2. For a later teardown out of hold: how do writes made under the claim reach the claims-off restore path?
-3. Step 3 expects leo's object-version actions and the deployment bucket's box-records policy, which are part of the owed module drift. Are they applied for the trial (as part of step 3, with their own plan) or deferred with the rest of the drift?
+3. Answered 2026-10-18: leo's object-version actions are applied for the trial; the box-records bucket policy goes with the fence-writer role in platform-infrastructure#46.
+4. How should leo's and sophie's box identity records (`control/boxes/<box>.json`) be published for step 5, given `CARLOS_REGION_HA` is off on both?