carlos / platform Public
- P1 — Shared types are introduced after tasks that require them. Plan 1 Task 8 defines
assetPolicy.Forreturningedge.HostAssets, but Task 9 first introduces that type andLocalAssets(plan 1:262, plan 1:290). Likewise, Plan 2 Task 1 definesConfig.FS FS, while Task 2 introducesFS(plan 2:65, plan 2:82). Neither earlier task can reach its required passing build. Smallest fix: move the shared type declarations before their first consumers; leave their implementations in the later tasks.
- P1 — Plan 3 Task 5 calls a method on the wrong interface.
fillFromApptakesa HostAssetsand asks “a’sDeclared” (plan 3:157).HostAssetsis a data struct;Declaredbelongs toLocalAssets(plan 1:290). Smallest fix: specifye.assets.local.Declared(host, answeringBuild, path), using the request hostname.
- P1 — The census instructions prescribe invalid dispositions. Plan 1 Task 11’s inventory calls for an
@legacyrow retaining classauthority, and a new authority row owned solely byJ1(plan 1:45). Plan 3 Task 10 prescribes classcache(plan 3:37). The loader requires@legacyrows to have classlegacy, has nocacheclass, and does not acceptJ1alone as an authority owner (census:420, census:480, census:507). Smallest fix: preserve existing authority rows as ordinary authority entries, assign valid kept-family ownership, and explicitly use the existing legacy format for applicable cache reads.
- P1 — Plan 3 Task 10’s provider test necessarily fails on existing code. It asserts that
go list -depsforinternal/edgecontains no AWS packages, claiming the package already imports none (plan 3:252).route53dns.godirectly imports four AWS packages (route53dns.go:25). Smallest fix: retain the dependency check for the newassetcachepackage and check the new asset implementation files for AWS imports; retain the credential-freeDirStoreintegration test.
- P1 — Plan 1 Task 7’s proposed write-failure fixtures cannot exercise the named branches. The plan keeps a concrete
*registry.Registryparameter but proposes analiasRegFailingwrapper or closing the registry (plan 1:240). A wrapper cannot satisfy that concrete parameter. Closing the handle makesListAliasesfail before the write branches, so the pass returns an error instead of the required nil-with-incomplete result (aliases.go:245, registry.go:2755). Smallest fix: prescribe selective SQLite write-failure triggers on the test database, or introduce a narrow registry interface.
- P2 — Plan 3 Tasks 2, 5 and 6 omit the
Set-Cookietrailer veto. Admission checks headers, and the fill instructions commit after a successful body without a trailer check (plan 3:102, plan 3:157). The spec explicitly prohibitsSet-Cookietrailers (spec:491); the existing shared cache already checks them (edge.go:1875). Smallest fix: require a final trailer veto before committing on both edges, preserving the information through backhaul; test announced and unannounced cookie trailers.
- P2 — Plan 1 Task 6 can confirm records that were never applied. Its completeness predicate checks successful reads and successful attempted writes (plan 1:225). However, an unreadable trash marker sets
declineMint, and the record loop skips the record beforeconvergeOwned, without a failing route write (reconcile.go:1137, reconcile.go:1174). A newly purged generation can therefore remain unapplied while authority time advances. Smallest fix: require positive application or verified equality for every relevant existing route; mark skipped application incomplete and test this case with a changed generation.
- P2 — Plan 2 Tasks 3 and 4 do not bound metadata writes. Reservations allocate 64 KiB for metadata, but the specified write limits cover only identity and gzip bodies;
Commitserializes arbitraryMeta.Headerand key contents (plan 2:103, plan 2:126). This does not implement the spec’s prohibition on writes past the reservation (spec:643). Smallest fix: bound the encoded metadata before writing it, include its bytes in accounting, and test oversized headers and queries.
- P2 — Plan 2 Task 4’s replacement sequence is not crash-safe.
Commitreplaces.body, then.gz, then.meta, including for an existing key (plan 2:126). A crash after replacing the body leaves the previous valid metadata, soOpenindexes new bytes with old headers, sizes or expiry. The proposed missing-meta crash test does not catch this. Smallest fix: invalidate the old metadata before replacing its files, with coordinated readers, or publish versioned body files through the metadata commit. Add a replacement-crash test.
- P2 — Plan 3 Task 5 does not apply conditional or range semantics to the initiating miss. It strips those request headers upstream and tees the resulting body directly to the client (plan 3:157). Task 3 tests those semantics only against an existing entry. The spec requires the edge to answer them itself (spec:400). Smallest fix: specify how an admitted cold fill answers its initiating conditional/range request through
serveAssetEntry, and add cold local and far tests.
- P2 — Plan 3 Tasks 1 and 5 leave acknowledgement key selection undefined during rotation.
verifyAssetFillaccepts either key but returns only a boolean;verifyAssetAckaccepts only the key the far edge used (plan 3:83). The existingsigningKeyprefers.nextimmediately (mesh.go:167). If the home has.nextand the far edge still signs with current, signing the acknowledgement with the home’s preferred key makes both edges skip billing. Smallest fix: return the matched verification key and sign the acknowledgement with it; test asymmetric key availability.
- P2 — Plan 3 Task 6 catches upgrade requests. Its far-edge predicate accepts any matching canonical GET or HEAD, with no upgrade exclusion (plan 3:187). Unlike the local hook, this executes before the existing upgrade branch. A WebSocket GET under an asset prefix can receive a cached body or lose its upgrade headers during filling, contrary to spec:385. Smallest fix: explicitly reject
isUpgradeRequest(r)before far-cache lookup and test intact backhaul of the upgrade.
- P2 — Plan 1 Task 8 lacks a publication trigger for serving-generation changes. It adds the serving build to the path union and a trigger for authority-time advances, but no trigger for a serving build changing while registry fields stay unchanged (plan 1:264). The current loop skips the writer until the registry fingerprint changes or its timer expires (edgesfile.go:888). Thus a retiring build’s prefixes can remain published until the five-minute refresh, contrary to spec:255. Smallest fix: include serving-build changes in the scheduling signal and test a generation switch with an unchanged registry fingerprint.
- P2 — No task implements the fallback ETag. Plan 2 Task 4 stores supplied headers, while Plan 3 Task 3 only preserves or weakens an existing ETag (plan 2:126, plan 3:119). The spec requires a strong body-SHA256 ETag when the app supplies none (spec:560). Smallest fix: assign hashing and fallback-header creation to the fill/commit task, with tests for identical home/far validators and conditional hits.
- P2 — Plan 3’s acceptance tasks omit required production-wired attacks. Tasks 5 and 6 explicitly use fake
LocalAssetsand a fake home; Task 9’s real two-edge tests cover only five scenarios (plan 3:161, plan 3:189, plan 3:239). The spec requires production wiring for the attack matrix, including credential stripping, refused fills, coalescing, deadlines and answering-generation checks (spec:717). Smallest fix: assign those cases explicitly to the real two-edge suite, including the warm/sleep/restart generation lifecycle.
- P2 — Plan 1’s fixed copy inventory omits newly required refusals. Task 0 pins exactly EAC-1 through EAC-19 (plan 1:104), but Task 3 requires a new error for combining
--assetsand--no-assets, and Task 2 requires echo and changed-assets reship refusals, without corresponding rows (plan 1:138, plan 1:161). Smallest fix: inventory these strings before Task 0’s review, update the exact-ID gate, and explicitly identify any existing approved wording reused.
reject