carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

  1. P1 — Task 5, Step 3: StripAll leaves forged headers in the reserved namespace. Plan:1458 deletes only the five known app headers and the hop header. A client-supplied X-Carlos-Geo-City, for example, survives both ingress and setGeo. Spec §8.1 requires stripping every X-Carlos-Geo-* header. Iterate over header keys using a case-insensitive prefix match, remove the hop header, and test unknown suffixes through the proxies.
  1. P1 — Task 12, Step 3: the prescribed status loader can falsely report “ready.” Plan:3982 explicitly calls systemBoxes, contradicting the task’s prohibition at line 3879. internal/console/apisystemupdate.go:233 and :258 use LoadBoxes, which omits unreadable records; the proposed verdict function also receives no expected-box inventory. Replace this recipe with LoadBoxesComplete for every prefix, reconciled against platform edges records and active fleet boxes. Test missing and unreadable heartbeats. Use Box.GeneratedAt, not the nonexistent Updated named at line 3880.
  1. P1 — Task 7, Step 3: expiry cleanup deletes an in-progress replacement download. Plan:2510 makes cleanLocked remove every .incoming-*, while download writes those files outside genMu at line 2609. If A expires while B downloads, ExpireTick → clearLocked → cleanLocked unlinks B. Its later rename fails, leaving GeoIP unavailable until another poll. Restrict stale-download cleanup to boot, or track active downloads and exclude them. Add a deterministic test that pauses B’s download while A expires.
  1. P1 — Task 7, Step 3: a directory-sync failure leaves current naming a deleted generation. Plan:2495 renames current before returning the directory-sync result. On any returned error, install deletes the newly named generation at line 2667. Restart then encounters a dangling current and cleans away the previous generation too. Distinguish failures before and after the rename; never delete a generation that current may already name. Inject a post-rename sync failure and verify restart recovery.
  1. P1 — Task 7, Step 3: initialization occurs after the edge has been published and after the dev-mode return. Plan:2792 inserts initialization around edge.go:3088, but ready(e) runs at internal/edge/edge.go:3015, and dev mode returns at :3038. Dev edges therefore never initialize or run the mirror. In production, Task 8’s heartbeat callback can read geoMode and geoMirror concurrently with their later assignments. Initialize and boot GeoIP before ready, and start its loop for both serving modes.
  1. P1 — Task 6, Step 3: blob CAS conflicts are accepted without the required size check. Plan:1962 treats every ErrCASConflict as proof that the exact blob exists. Spec §3 requires checking that the existing object’s size matches. A truncated object under that key would be published as current, followed by deletion of the previous good blob. Verify existence and length after a conflict; refuse mismatches without moving the pointer or sweeping. Cover both an existing wrong-size object and a conflict without a readable object.
  1. P1 — Task 7, Step 3: unknown pointer versions retain the active database. Plan:2555 handles every parse error by retaining the current reader. Spec §3, lines 190–191, explicitly treats an unknown v as no pointer: GeoIP must turn off. Distinguish unsupported versions from ordinary read/parse failures, clear the generation, and log once. Test a loaded database followed by a version-2 pointer.
  1. P1 — Task 7, Step 3: rejected-digest suppression survives pointer changes. Plan:2570 returns for the loaded SHA before clearing skipSHA; the missing-pointer branch also leaves it intact. After rejecting B, observing A again—or observing off—and then republishing repaired B, the mirror still refuses to download B. Spec §5.3 permits retry once the pointer changes. Track the observed pointer separately and reset suppression whenever that identity changes, including removal.
  1. P1 — Task 4, Step 3: the streaming DirStore implementation reads the existing blob into memory. Plan:1005 calls os.ReadFile(p) before checking create-only existence. Republishing an existing database therefore allocates its entire contents—potentially 1 GiB—despite introducing this interface to bound memory. Use Stat for create-only checks and streamed hashing when an existing ETag must be compared.
  1. P1 — Task 6, Step 3: ctxReader collides with an existing test type. Plan:2009 declares ctxReader and its Read method in package console. internal/console/apidb_test.go:642 already declares both, with a different shape and behavior. The console test package will not compile. Give the publisher helper a distinct name and update copyCapped.
  1. P1 — Task 7, Steps 1 and 3: the supplied oversize test fails against the supplied implementation. Plan:2317 sets maxBytes = p.Size - 1. The implementation reads limit + 1 bytes, obtaining exactly p.Size, then checks only n != p.Size at line 2630. The blob passes both size and digest checks. Reject n > limit as well, or reject a declared size above the configured cap before downloading.
  1. P1 — Task 11, Step 3: the CLI insertion references an undefined variable. Plan:3827 prescribes printAnalyticsTable(w, "Countries", resp.Countries). The renderer uses res, including the adjacent call at analytics_cmd.go:149. Change the insertion to res.Countries; the literal instruction otherwise breaks the root package build.
  1. P1 — Tasks 9 and 12, Step 5: commit commands omit required implementation changes. Plan:3401 omits backhaul_e2e_test.go, although Task 9’s new test depends on fields added there. The Task 12 command at line 4068 omits geoippublish.go, although its handler depends on the new Stage/Commit split. Following these commands produces commits missing dependencies that local working-tree tests can conceal. Include both files and verify the committed result from a clean checkout.
  1. P2 — Task 12, Step 1: the HTTP expectations contradict the asynchronous contract and existing authorization behavior. Plan:3899 requires successful PUTs to return 200 and invalid databases to return 422, while the same task requires staging followed by a 202 job. Its service-token expectation is also 404, whereas internal/console/authcli.go:438 returns 403 for an empty role set. Update the tests to expect 202 and poll for validation results, and preserve the existing 403 service-credential gate.
  1. P2 — Task 12, Step 3: the reused job API cannot return the promised pointer. Plan:3935 requires the existing job type, and lines 3939 and 4036 require polling to return the publication pointer. systemJob at internal/console/apisystemupdate.go:48 stores only steps, completion, and error; its handler at :587 exposes only those fields. Explicitly add an optional result to the job, locked snapshot, response schema, and CLI polling path. Preserve the result belonging to that job rather than rereading the potentially changed current pointer.
  1. P2 — Task 10, Step 3: Loop drops the TLS configuration required by its new integration test. Plan:3536 introduces DialConfig and updates the handler used by Loop, but does not replace Loop’s existing Dial(ctx, cfg.URL, cfg.Name, cfg.Token) call at internal/tunnelclient/tunnelclient.go:105. That call cannot carry cfg.TLSConfig, so the test server’s certificate pool is lost. Explicitly change Loop to call DialConfig(ctx, cfg) and verify the TLS integration test with certificate verification enabled.
  1. P2 — Tasks 10 and 11, Step 1: tunnel analytics assertions contradict each other and the ingress counting rule. Plan:3475 asks the remote meter to record GB; line 3682 requires zero remote observations, and line 3684 asks to complete the earlier assertion. Line 3682 also expects zero hub countries over plaintext, although the hub still computes its own ingress result. Replace these with one consistent table: zero remote observations for either transport, and hub country counts from the hub’s result. With the stated GB setup, both transports produce two GB pageviews at the hub.
  1. P2 — Tasks 9 and 10, Step 1: required trust-boundary tests are unassigned. Plan:3094 tests forgery through the TCP helper, while Task 10’s scene covers a successful tunnel and plaintext fallback. Neither task assigns the full spec §8.4 matrix: every proxy type with connection nomination and cache replay, the tunnel box’s public listener, a backhauled door, rotation-window backhaul, and transported miss/off states. Assign these cases explicitly to the relevant task, with assertions on backend headers and lookup/counting behavior.
  1. P2 — Task 7, Step 1: the recovery tests do not exercise the promised failure paths. Plan:2227 uses deadbeef as a SHA, so the “missing file” test succeeds through invalid-SHA handling before opening a generation. The expiry test at line 2291 is sequential, and line 2272 tests pointer metadata rather than expired downloaded metadata. Add a valid missing-generation SHA, injected disk/crash failures, pointer-read and deleted-blob failures, and controlled concurrent expiry/install tests, as required by spec §§5.3 and 14.
  1. P2 — Task 6, Step 1: the different-type shrink assertion passes without enforcing its intended property. Plan:1715 force-publishes the Country fixture, resetting the inflated node count from 99,999 to 1,704. The subsequent City fixture has 1,547 nodes, so it passes even if the implementation incorrectly applies the shrink check across types. Reinstate the inflated count before the different-type assertion, or isolate that case. Also assign the spec-required publish/off race and foreign-pointer CAS tests; the sequential sweep/off test at line 1765 covers neither.
  1. P2 — Task 9, Step 1: the WebSocket helper does not expose request headers. Plan:3284 claims upgradeEchoBackend echoes received headers. At internal/edge/edge_test.go:2012, it actually reads a client-supplied line after upgrading and echoes that line with a tag. The named bypass-recording test also does not supply the claimed real-client handshake. Add a backend that records the actual upgrade request headers, and use the real connection pattern from TestMultiUpstreamServesWebSocketUpgrade at :2030.
  1. P2 — Task 1 and the final gate: the required real GeoLite2 measurement has no assigned step. Plan:116 makes Task 1 solely the bucket lifecycle change; the final gate does not restore the measurement requirement. Spec §17 explicitly assigns real DB-IP and GeoLite2 City probe and Verify memory measurements to Plan 1. 2026-10-06-platform-geoip-FACTS.md:30 confirms GeoLite2 was not measured. Add an explicit measurement step and record its results, or mark that requirement outstanding pending access to a real GeoLite2 City file.

Verdict: revise.