carlos / platform Public

Astra tenant-directory confirming review: unedited

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev 3682ec7b2d64f90b8342deafc123061922115b47 parent b76adde
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