carlos / platform Public
Reviewed the plan at 7a8cf520 against the working tree and spec. This was a static review; the proposed code and tests were not executed. plan:L below refers to that plan’s line numbers.
- P1 — Task 2, Step 3: missing import prevents compilation.
plan:876introducesstatus.InstanceID(), butinternal/host/edgesfile.go:3–20does not importinternal/status. The import inedgesfile_test.godoes not apply to another file. Fix: explicitly addgithub.com/carlosframework/platform/internal/statustoedgesfile.go.
- P1 — Task 1, Steps 1 and 3: the storage key is not bound to the verified box.
LoadreadsKey(box)but never checksrec.Box == box(plan:378–398). An intact, valid record for A stored undercontrol/boxes/B.jsontherefore passes verification as A (plan:470–471). Review Focus 5’s test changes the record’sBoxfield instead of exercising this substitution (plan:197–203). Fix: reject a storage-key/record mismatch and test loading A’s unchanged record from B’s key.
- P1 — Task 1, Step 4 / Task 3, Step 3: a supported but wrong region is accepted. Verification selects a certificate using the document’s own region, with no expected-region comparison (
plan:453–461). Eligibility then selects by unsigned placement metadata without comparing the verified region (plan:1254–1274). A signed US identity can qualify through an edges file advertising the Irish placement, contrary to spec lines 193–196. Fix: require the signed region to match the expected AWS region; test a mismatch where both regions have certificates.
- P1 — Task 6, Step 3:
readStablecan follow ancestor symlinks or block opening a substituted FIFO.Lstatfollowed by ordinaryos.Open(plan:2551–2579) does not secure the path. Replacing a parent directory with an external symlink before the read lets both inode checks succeed on the external file. Replacing the final file with a FIFO between inspection and opening can block beforef.Stat. Task 7 reaches this through queued paths atplan:3144. Fix: use root-relative traversal that refuses symlink components and a nonblocking, no-follow final open. Add deterministic ancestor and FIFO substitution tests.
- P1 — Task 5, Step 5: restore can write or delete outside its destination.
CleanPathchecks spelling, butfilepath.Joinandos.Removefollow ancestor symlinks (plan:2219–2226), as do the parent-directory operations inwriteAtomic(plan:2271–2274). Withfiles/sub -> outside, entrysub/xmodifiesoutside/x. Fix: constrain all restore operations, including tombstones and temporary files, to an opened destination root. Test both writes and deletes through an external symlink.
- P1 — Task 11, Step 2: the queue policy does not enforce exclusive termination-event provenance. The statement at
plan:4655–4662only grants the EventBridge rule access. A same-account principal with an identity-basedsqs:SendMessagegrant can still submit a forged termination event, whose JSON fields Task 9 accepts. AWS documents that these grants combine unless explicitly denied. SQS policy evaluation. Fix: explicitly denySendMessagewhen the source ARN is missing or differs from the rule. Test both the legitimate rule and an otherwise IAM-authorized sender.
- P2 — Task 5, Step 5: directory-to-file transitions cannot restore. Publish
a/b, then replace directoryawith filea. The resulting manifest has liveaand tombstoneda/b. Restore sorts paths (plan:2216), writesa, then fails removinga/bwithENOTDIR(plan:2222–2226). Restoring over an earlier copy also fails when renaming a file over the existing directory. Fix: handle deletions and file/directory transitions explicitly. Test both transition directions against empty and previously restored destinations.
- P2 — Task 7, Step 9: overflow does not repair missing directory watches.
IN_Q_OVERFLOWrequests a scan without marking coverage degraded (plan:3434–3436), whilerunrepairs watches only when degraded (plan:3093–3098). If overflow loses a directory-creation event, the scan publishes its current files but leaves the directory unwatched; later changes wait ten minutes. Fix: mark coverage uncertain, rebuild recursive watches, and retain polling until repair succeeds. Test a lost directory-creation event followed by another write inside that directory.
- P2 — Task 7, Steps 6 and 9: watcher failure can disable fallback polling. A read error exits the reader and closes its channel (
plan:3403–3411).runignores the receive’sokvalue (plan:3076), producing a busy loop.Repaircan then clear degradation after adding watches even though no reader remains (plan:3332–3336). Fix: detect channel closure and recreate the watcher or stay in polling mode. Test continued publication after the event channel closes.
- P2 — Task 2, Step 3: headroom never refreshes solely on the five-minute tick. The new comparison deliberately removes headroom (
plan:853–871), but the existing timed path still calls the same gated function without forcing a write (internal/host/edgesfile.go:692–695). If nothing else changes, headroom remains stale indefinitely, contrary toplan:642. Fix: distinguish a periodic refresh from a change-triggered pass. Test that headroom-only changes skip ordinary passes but publish on a timed refresh.
- P2 — Task 8, Step 6: importing default replication leaves the destination’s previous class.
ImportWakeskipsSetReplicationwhen the source value is empty (plan:3895–3898). Importing default state onto a destination set todailytherefore retainsdaily. Empty is explicitly valid and supported by the setter (internal/registry/registry.go:415–420, 1259–1278). Fix: apply the empty value too; test an empty source class against a nonempty destination.
- P2 — Task 3, Steps 1 and 3:
chooseBoximplements a different spread rule. Spec lines 266–269 prefer a box with no instance of the app, then use total claimed-host count. The implementation instead minimizes app-instance count before total load (plan:1299–1306). Its test deliberately picks a box with five total hosts over one with two when both already run the app (plan:1204–1206). Fix: compare whether the app count is zero, then total hosts, then box ID; update that test.
- P2 — Task 6, Step 3: directory exclusions can tombstone previously published children. The walk respects
skip("cache", true), but the deletion pass checks onlyskip("cache/x", false)(plan:2627–2630, 2666–2670). With the plan’s callback, an existingcache/xentry becomes a tombstone. Individual-file exclusions are preserved, so the two exclusion forms behave differently. Fix: retain excluded directory prefixes during reconciliation and test exclusion after the child has already been published.
- P2 — Task 7, Step 4: startup scanning masks event and polling test failures.
startRunreturns before its mandatory initial scan finishes (plan:2878–2883, 3070). The deadline, overflow and polling tests immediately create their files (plan:2908–2915, 2936–2965), so the initial scan can satisfy their assertions with the tested mechanism disabled. Fix: synchronize on completion of the initial scan before making changes; assert the publication timing and disable unrelated scan paths.
- P2 — Task 6, Step 1: Review Focus 2 and 3 are only partly tested. The nonregular-file test covers static symlinks, but no FIFO, socket, device or substitution race (
plan:2430–2453). The oversized-file test checks the final skipped result, which would also pass if the implementation read the entire file before rejecting it (plan:2457–2480). Fix: add applicable special-file cases and deterministic races, plus an instrumented read boundary that proves oversized files are rejected without reading their contents.
- P2 — Task 8, Step 1: the all-or-nothing test never reaches the transaction. Its wrong-host row (
plan:3575–3579) is rejected beforeBegin(plan:3620–3625). The test would pass with nontransactional deletion and insertion. Fix: use duplicate names belonging to the correct host so insertion fails after deletion and one successful insert; assert that the original rows survive.
- P2 — Task 9, Step 1: the unverified-identity test passes for the wrong reason.
FromDescribe(..., "", "")returnsFound:falseimmediately (plan:4065–4068, 4193–4196). RemovingVerify’s empty-identity guard would still leave the test passing on absence. Fix: construct aFound:true, terminated, describe observation with matching empty identity coordinates and verify that the identity guard rejects it.
- P2 — Task 4, Step 4: required conflict diagnostics are absent. The plan promises a once-per-refresh diagnostic for equal positive stamps (
plan:1348), and spec lines 322–326 require an alert for conflicting unstamped entries. Neither the fold replacement nordialBeatsimplements reporting (plan:1497–1529). Fix: add refresh-scoped diagnostics and tests that preserve the deterministic winner while checking the warning.
- P3 — Task 5, Step 6: the stated storage protection is deferred elsewhere.
plan:2303says Task 11 enforces create-only content objects, but Task 11 protects onlycontrol/boxes/; the files-prefix policy is explicitly deferred to 1b atplan:4877. Fix: correct the statement to describe the deferred enforcement and its prerequisite before enabling the publisher.
Verdict: not ready.