Astra tenant-directory confirming review: unedited
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+34
−0
docs/superpowers/plans/CODEX-REVIEW-REGION-HA-TENANT-DIR-2.md+34 −0
CI passed — run details
CI log
=== gate ===
cd launchctx && go vet ./... && go test ./... -count=1
ok amadan.net/carlos/platform.git/launchctx 0.011s
? 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 330.734s
? github.com/carlosframework/platform/cmd/changelog [no test files]
ok github.com/carlosframework/platform/cmd/console 3.138s
ok github.com/carlosframework/platform/cmd/moveprobe 92.271s
ok github.com/carlosframework/platform/internal/activator 206.003s
ok github.com/carlosframework/platform/internal/agentsock 0.016s
ok github.com/carlosframework/platform/internal/alerting 0.003s
ok github.com/carlosframework/platform/internal/analytics 0.017s
ok github.com/carlosframework/platform/internal/appconfig 2.272s
ok github.com/carlosframework/platform/internal/apperr 0.072s
ok github.com/carlosframework/platform/internal/applog 0.128s
ok github.com/carlosframework/platform/internal/awsinv 0.004s
ok github.com/carlosframework/platform/internal/boxchoice 0.004s
ok github.com/carlosframework/platform/internal/boxid 1.022s
? 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.008s
ok github.com/carlosframework/platform/internal/caps 0.011s
ok github.com/carlosframework/platform/internal/certwarm 0.002s
ok github.com/carlosframework/platform/internal/cgroup 0.197s
ok github.com/carlosframework/platform/internal/changelog 0.273s
ok github.com/carlosframework/platform/internal/clamd 0.054s
? github.com/carlosframework/platform/internal/cliflag [no test files]
ok github.com/carlosframework/platform/internal/console 355.216s
? 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 5.806s
ok github.com/carlosframework/platform/internal/dbdoor/dbdoortest 0.014s
ok github.com/carlosframework/platform/internal/dbverify 0.014s
ok github.com/carlosframework/platform/internal/dnsrec 0.015s
ok github.com/carlosframework/platform/internal/docsite 0.014s
ok github.com/carlosframework/platform/internal/domains 2.026s
ok github.com/carlosframework/platform/internal/doorkey 0.014s
ok github.com/carlosframework/platform/internal/economics 0.016s
ok github.com/carlosframework/platform/internal/edge 25.911s
? github.com/carlosframework/platform/internal/edgeproof [no test files]
ok github.com/carlosframework/platform/internal/edgesfile 0.014s
ok github.com/carlosframework/platform/internal/fleetapi 0.148s
ok github.com/carlosframework/platform/internal/gate 1.659s
ok github.com/carlosframework/platform/internal/genselect 0.018s
ok github.com/carlosframework/platform/internal/geo 0.019s
ok github.com/carlosframework/platform/internal/geoip 0.043s
ok github.com/carlosframework/platform/internal/host 63.305s
ok github.com/carlosframework/platform/internal/hostactors 0.630s
ok github.com/carlosframework/platform/internal/hostbox 1.601s
ok github.com/carlosframework/platform/internal/hostclaim 0.470s
ok github.com/carlosframework/platform/internal/hostevidence 0.005s
ok github.com/carlosframework/platform/internal/hostexec 0.307s
ok github.com/carlosframework/platform/internal/hostfence 0.030s
ok github.com/carlosframework/platform/internal/hostfiles 6.776s
ok github.com/carlosframework/platform/internal/hostfloor 0.008s
ok github.com/carlosframework/platform/internal/hostguard 0.141s
ok github.com/carlosframework/platform/internal/hostops 1.443s
? github.com/carlosframework/platform/internal/hostops/fencerelease [no test files]
ok github.com/carlosframework/platform/internal/hostops/internal/fencerelease 0.003s
ok github.com/carlosframework/platform/internal/hostquarantine 0.002s
ok github.com/carlosframework/platform/internal/hostrelocate 0.465s
ok github.com/carlosframework/platform/internal/hostresolve 0.140s
ok github.com/carlosframework/platform/internal/hostwrite 0.002s
ok github.com/carlosframework/platform/internal/infraview 0.002s
ok github.com/carlosframework/platform/internal/instancectl 1.703s
ok github.com/carlosframework/platform/internal/instanceexec 2.688s
ok github.com/carlosframework/platform/internal/instancefs 0.005s
ok github.com/carlosframework/platform/internal/instancekey 0.002s
ok github.com/carlosframework/platform/internal/instanceupdates 0.009s
ok github.com/carlosframework/platform/internal/layout 1.430s
ok github.com/carlosframework/platform/internal/lease 9.438s
ok github.com/carlosframework/platform/internal/lease/leasetest 0.005s
ok github.com/carlosframework/platform/internal/ledger 0.018s
ok github.com/carlosframework/platform/internal/mail 0.182s
ok github.com/carlosframework/platform/internal/maintenance 0.080s
ok github.com/carlosframework/platform/internal/maintenanceexec 5.509s
ok github.com/carlosframework/platform/internal/maintenanceguard 0.074s
ok github.com/carlosframework/platform/internal/metrics 0.008s
ok github.com/carlosframework/platform/internal/moves 21.084s
ok github.com/carlosframework/platform/internal/moves/archive 0.818s
ok github.com/carlosframework/platform/internal/objstore 0.164s
ok github.com/carlosframework/platform/internal/ops 0.161s
ok github.com/carlosframework/platform/internal/park 0.209s
ok github.com/carlosframework/platform/internal/privatefile 0.003s
ok github.com/carlosframework/platform/internal/provision 3.228s
ok github.com/carlosframework/platform/internal/publicrelease 0.006s
ok github.com/carlosframework/platform/internal/registry 3.750s
ok github.com/carlosframework/platform/internal/relay 7.225s
ok github.com/carlosframework/platform/internal/release 18.548s
ok github.com/carlosframework/platform/internal/rollout 1.527s
ok github.com/carlosframework/platform/internal/rolloutwords 0.004s
ok github.com/carlosframework/platform/internal/rootaws 0.006s
ok github.com/carlosframework/platform/internal/s3compat 0.007s
ok github.com/carlosframework/platform/internal/safefile 0.004s
ok github.com/carlosframework/platform/internal/schedule 2.234s
ok github.com/carlosframework/platform/internal/sim/hostlife 2.626s
ok github.com/carlosframework/platform/internal/sim/litestreamfacts 4.127s
ok github.com/carlosframework/platform/internal/status 0.040s
ok github.com/carlosframework/platform/internal/steering 0.005s
ok github.com/carlosframework/platform/internal/stopevidence 0.129s
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.005s
ok github.com/carlosframework/platform/internal/unixdial 0.003s
ok github.com/carlosframework/platform/internal/updatewords 0.004s
ok github.com/carlosframework/platform/internal/usage 0.005s
ok github.com/carlosframework/platform/internal/version 0.002s
ok github.com/carlosframework/platform/internal/vet 1.555s
=== 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
--- 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/12 10:23:07 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18DDC124074806FD, 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.015s
minio contract: PASS
diff --git a/docs/superpowers/plans/CODEX-REVIEW-REGION-HA-TENANT-DIR-2.md b/docs/superpowers/plans/CODEX-REVIEW-REGION-HA-TENANT-DIR-2.md| new file mode 100644 |
| index 000000000..70d0b49cd |
| --- /dev/null |
| +++ b/docs/superpowers/plans/CODEX-REVIEW-REGION-HA-TENANT-DIR-2.md |
| @@ -0,0 +1,34 @@ |
| +1. **P1 — Restore still traverses an uncapped tenant-controlled tree.** [restore.go:409](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/region-ha-1b-next-build/internal/hostfiles/restore.go:409) |
| + A valid manifest can name the shallow file `x` while the tenant has left a deeply nested directory at `x`. `writeInside` calls `root.RemoveAll(x)`, bypassing `withinTreeCap`. Go’s implementation recurses with an open descriptor per directory and has no context checks. This can exhaust descriptors or prolong installation while its host guard remains locked. This is an inherited risk still within the brief’s scope. Bound the deletion traversal and make it cancellable. |
| + |
| +2. **P1 — The walk’s memory remains unbounded by directory width.** [walk_unix.go:32](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/region-ha-1b-next-build/internal/hostfiles/walk_unix.go:32), [dir_unix.go:74](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/region-ha-1b-next-build/internal/hostfiles/dir_unix.go:74) |
| + `d.names()` calls `Readdirnames(-1)` and sorts every name before any path cap or further cancellation check. A tenant can leave sufficiently many empty files in one shallow directory to exhaust the shared agent’s memory; depth and file-content limits do not constrain this. Ancestor name lists also remain allocated during recursion. This is another inherited gap. Read bounded batches and enforce a total traversal budget. |
| + |
| +3. **P2 — The new manifest restriction is not enforced by every publisher.** [restore.go:271](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/region-ha-1b-next-build/internal/hostfiles/restore.go:271) |
| + `checkManifest` now rejects paths above 256 components, but `publishOne` → `Publisher.Stage` → `Commit` still accepts them. A watcher event for a valid 257-component path can therefore publish a manifest that `Restore`, `CopyManifest`, and `ValidateManifest` refuse. `Run` continues processing events and committing after a failed full scan. Deleting that file leaves a tombstone that also fails validation. Apply the policy across all publishing paths and address existing manifests. |
| + |
| +**Verdict: request changes.** The original FIFO-blocking P1 and vanished-directory P2 are closed by source inspection. The remaining resource risks prevent approval, and the cap introduces a reader/writer mismatch. |
| + |
| +The caps exclude legitimate filesystem trees: 257 one-character components require only 513 bytes. Moves’ archive contract also permits 4096-byte paths without this depth limit. I found no active moves caller of `hostfiles.Publish`, so this is a contract mismatch rather than a demonstrated live moves regression. |
| + |
| +Targeted tests could not start because the read-only sandbox prevented Go from creating its build directory. Findings are based on source inspection. |
| + |
| +--- |
| + |
| +**FIRST PROMPT:** |
| +“Follow the review brief docs/superpowers/plans/CODEX-REVIEW-REGION-HA-TENANT-DIR-BRIEF-2.md. Review the diff 3194d674..f9123572 on branch region-ha-1b-next-build.” |
| + |
| +**WHAT:** |
| +Confirm tenant-directory safety fixes in the requested diff. |
| + |
| +**STATUS:** |
| +Review complete: two remaining P1 risks and one new P2 mismatch; tests blocked. |
| + |
| +**NEEDED:** |
| +Nothing for this review. |
| + |
| +**RECOMMENDED:** |
| +Bound both remaining traversals and align manifest writers with readers before approval. |
| + |
| +**SESSION:** |
| +Safe to close. No files changed or processes left running; the read-only sandbox prevented saving the handoff. |
| \ No newline at end of file |