| 1 | # Census: db region forward, plan 3 (`carlos db pull` and `pull --at` for an instance in another region) |
| 2 | |
| 3 | Status: ACCEPTED in full by the census owner on #280, 2026-10-23, as |
| 4 | `census-ruling-db-region-forward-3`, for every row below and the round 1 fix |
| 5 | rows. Every row now carries `rev3=census-ruling-db-region-forward-3`; the |
| 6 | `@legacy` fingerprints were recomputed and the seal moved to |
| 7 | `79cb56b4c7d3a8e155d1eff1902715d818fcf4c09b1d8a82921c413b116938a9`. |
| 8 | |
| 9 | The census owner's rationale: the box-side reads stay the agent's or the |
| 10 | sandboxed worker's; the CLI reads only its own spool; the `admitDBRead` |
| 11 | re-pin is the same write class; Astra matched every digest. |
| 12 | |
| 13 | The branch is `db-region-forward-3`, cut from amadan `main` at 0d9e81dc. It |
| 14 | builds plan 3 of `docs/superpowers/specs/2026-10-22-db-region-forward-design.md` |
| 15 | (rev 7): the box's worker holds a pull's planned LTX files, verifies their |
| 16 | checksums and sends them back after the agent's check B; the agent seals them |
| 17 | as the `ltx` stream in 1 MiB chunks, with the plan in the summary; the console |
| 18 | forwards and audits the new op; the CLI spools the sealed chunks to a private |
| 19 | directory, checks the file list, the count and the SHA-256, restores locally |
| 20 | with `dbdoor.RestoreLocal` and saves the copy with today's `copyOut`. The |
| 21 | box never restores for a pull. |
| 22 | |
| 23 | It adds one root-read overlay, |
| 24 | `internal/provision/testdata/plan14-root-reads-db-region-forward-3.tsv`, |
| 25 | loaded last in `TestPlan14RootReadCensus`, after `static-redirects` (the |
| 26 | overlay main loads last at 0d9e81dc). Its record-write entry is layered on |
| 27 | `plans3aWriteCensusInventory` in |
| 28 | `internal/provision/db_region_forward_3_census_test.go`. |
| 29 | |
| 30 | ## Root reads |
| 31 | |
| 32 | Executing identities, named once: |
| 33 | |
| 34 | - **the worker**: `carlos system db-worker` under `carlos-dbread@.service`, a |
| 35 | DynamicUser with no network, its own PrivateTmp, `/data` and `/etc/carlos` |
| 36 | hidden. |
| 37 | - **the CLI**: `carlos db pull` on a person's machine, as the person. |
| 38 | |
| 39 | The scanner names no agent, console or host unit: the agent's pull branch in |
| 40 | `attempt`, `NewAgent`'s `MaxPull`, the console's op check and audit detail, |
| 41 | and `CARLOS_DB_PULL_MAX_BYTES` in `dbReadsSettings` make no read it counts |
| 42 | (plan 1's R8 again). |
| 43 | |
| 44 | | unit | change | executing identity | proposed disposition | |
| 45 | |---|---|---|---| |
| 46 | | `internal/dbreads/worker.go` `holdAndSend` | new: opens each planned LTX file it received and verified, in its own private `/var/tmp`, after check B, and copies it back over its socket | the worker | legacy, accepted-legacy, J4 (`root-input`, as `receiveFile`) | |
| 47 | | `internal/dbreads/worker.go` `verifyLTX` | new: opens one received LTX file and decodes it whole to check its checksums, before ready | the worker | legacy, accepted-legacy, J4 | |
| 48 | | `internal/dbreads/worker.go` `ServeWorker` | changed: accepts a pull header and hands it to `holdAndSend` after the same bounded receive; the `Stat` is unchanged | the worker | re-frozen at `census-ruling-db-region-forward-1` with this change appended | |
| 49 | | `dbforward.go` `dbPullForward` | new: the same bounded 64 KiB read of a refused reads-route answer as `dbQueryForward` (`io.ReadAll` over the response body, not a file); creates and removes the pull's private 0700 directory | the CLI | legacy, accepted-legacy, J4 (main's footing for `db.go`'s units) | |
| 50 | | `dbforward.go` `fileSink.chunk` | new: reads back one sealed chunk it spooled itself, 0600 in that directory, admitted by the chunk bound before it was written | the CLI | legacy, accepted-legacy, J4 | |
| 51 | | `dbforward.go` `openDBPull` | new: creates each planned LTX file exclusively (`O_EXCL`, 0600) in that directory, only after the whole file list is checked; then restores, checks and removes them | the CLI | legacy, accepted-legacy, J4 | |
| 52 | | `internal/dbdoor/plan_from.go` `ctxReadCloser.Read` | new (Astra round 1, finding 2): `RestoreLocal` wraps its local replica's reads so each checks the restore's context first; litestream's compaction checks none of its own | the CLI and the worker | legacy, accepted-legacy, J4 (as main's `downloaded.Read`) | |
| 53 | | `dbforward.go` `dbQueryForward` | changed: keeps its chunks in a `memSink` and opens them after `readDBForward` returns the result; the same bounded refusal read | the CLI | re-frozen at `census-ruling-db-region-forward-2` with this change appended | |
| 54 | |
| 55 | Round 1 (Astra on cc77ca95): `ServeWorker` now checks every received file's |
| 56 | LTX header against its plan entry through `verifyLTX`, for a query as well as a |
| 57 | pull, and the plan's end against its target; `holdAndSend` only sends the checked |
| 58 | files back; `openDBPull` compares each rebuilt file's header with its manifest |
| 59 | entry and checks its context per chunk. Their rows carry a round 1 clause; no |
| 60 | read is added to them. |
| 61 | |
| 62 | Envelopes re-pinned: `.`, `internal/console`, `internal/dbdoor`, |
| 63 | `internal/dbreads`, `internal/host`. Frozen declarations are added, so the seal moves: |
| 64 | static-redirects' `65857c29…` is checked first, the proposed seal was |
| 65 | `36ecd2eca043f1d0056f086be47ba1fb887dcdc2eda67427e698c2b6d1b9031b` (79cb56b4… once the markers flipped). |
| 66 | |
| 67 | ## Record writes (9B8) |
| 68 | |
| 69 | `internal/console/apidbforward.go` `Server.admitDBRead` is re-digested and |
| 70 | stays `nonrecord`: it admits a pull beside a query and audits it with its own |
| 71 | detail; its writes are the same conditional creates under `db-reads/` in the |
| 72 | deployment bucket. No write site is added. |
| 73 | |
| 74 | ## Unchanged |
| 75 | |
| 76 | Claim routes (no new route: a pull uses plan 2's reads route), `go.mod`. |
| 77 | |