# `carlos db` region forward, plan 1: the box side and the wire, dark Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Build everything a box needs to serve a forwarded `carlos db query` (the wire format, the sealed result, the agent's db-reads loop with its identity bracket and election, the sandboxed `carlos-dbread@` worker and its units, and the `db-read-1` capability), shipped dark: nothing runs unless a console asks, and no console asks until plan 2.

**Architecture:** A new leaf-ish package `internal/dbreads` holds the wire (ids, object keys, the root-signed request envelope, sealing, the result) and the box engine (`Agent`: listing the region's queue, verifying, electing an owner with a create-only `picked`, the identity bracket, admission, chunked sealed output). Everything that decodes tenant bytes runs in `carlos system db-worker` (`dbreads.ServeWorker`), started per connection by a root-bound socket unit `carlos-dbread.socket` as a `DynamicUser` with no network. `internal/dbquery` takes the query runner and guards out of `db.go` so the CLI and the worker run the same code. `internal/dbdoor` gains planning over any replica reader, listed exactly as the console door lists. `internal/host` only wires: units, arming, the capability, the nudge.

**Tech Stack:** Go 1.26, litestream v0.5.14 (`CalcRestorePlan`, the file replica client), superfly/ltx v0.5.1, modernc.org/sqlite v1.55.0, `crypto/ecdh` + `golang.org/x/crypto/hkdf` + AES-256-GCM, ed25519 root envelopes (`internal/release`), systemd socket activation, `golang.org/x/sys/unix`.

**Spec:** `docs/superpowers/specs/2026-10-22-db-region-forward-design.md` (rev 6: rev 5, accepted by Astra in round 5 and approved by Paul for building on 2026-10-22 with the rulings in §16, plus the four clarifications the plan review forced, §5.4, §5.5, §5.7 and §9.3). Read §3, §5, §7, §8, §11.4, §12, §13 and §15 before starting. Every task argues from the spec; where this plan and the spec disagree, the spec wins and the plan is the bug.

**Branch:** `db-region-forward-1-box`, cut from amadan `main`. The worktree is made with the superpowers:using-git-worktrees skill. Plans 2 and 3 branch from `main` after this plan has merged.

## Global Constraints

Every task's requirements include this section.

- **Production-wired acceptance.** Acceptance tests go through real constructors, the real units installed by the real `ensureSystemUnits`, the real store and the real verify and seal code. A stand-in (an in-process worker over a pipe, a fake dialer, a store wrapper) is allowed in unit tests only, and every such test says so in its doc comment with the words "not acceptance". Plan 1's acceptance gates are spec T2, T3, T4, T5, T9, T12, T13 and the parity half of T6.
- **Targeted local runs; CI runs the full suite.** Locally run only the touched packages with `-run`, for example `go test ./internal/dbreads/ -run 'TestEnvelope' -count=1`. Never run `make test`, never a whole `internal/console` or `internal/host` package. Build, `go vet`, `gofmt -l` and the cross-compiles do run locally. A green CI run on the branch tip is the merge gate.
- **Cross-compile gate.** CI builds darwin and windows. Any file using Linux-only syscalls (`SO_PEERCRED`, `Statfs`, `systemctl`) carries `//go:build linux` with a `_other.go` sibling tagged `//go:build !linux` that returns an "unsupported" error. Before every push run `GOOS=darwin GOARCH=arm64 go build ./...` and `GOOS=windows GOARCH=amd64 go build ./...`.
- **Copy needs review before it ships, with no em dashes.** No user-facing string reaches code or docs until Paul approves it in the copy review (the `copy-review` skill). The record is `docs/superpowers/plans/2026-10-22-db-region-forward-copy.md`, gated by `approved_db_forward_copy_test.go`. No em dashes anywhere; a full stop and a new sentence, continuing in lower case. Internal error fragments, log lines and diagnostics are not copy rows (Paul, 2026-10-16).
- **No tenant names.** Examples, fixtures and comments use `shop`, `shop.example.com`, `member@example.com`, regions `ie` and `uk`.
- **Go cache.** Leave `GOCACHE`, `GOMODCACHE` and `GOTMPDIR` at their defaults. If the sandbox makes `~/.cache/go-build` read-only, run the go command with the sandbox off; never invent a cache path. Unix-socket tests fail inside the sandbox ("socket: operation not permitted"); run them with the sandbox off.
- **Census overlays per branch, loaded LAST.** This branch adds `internal/provision/testdata/plan14-root-reads-db-region-forward-1.tsv`, loaded in `TestPlan14RootReadCensus` after every overlay main loads at the time of the merge, with the previous seal checked first. At main `5f341f33` the last overlay is `console-brand-name` (after `plans-2-box-limits`, `email-signin`, `design-fleet-internal-engines`, and earlier `securelisten-337` and `ci-speed-activator`); re-read the test after every merge of main and load this overlay after whatever is last then. Rows carry `rev3=PROPOSED-db-region-forward-1`; the ruling is asked of the census owner on #280.
- **Merge main first.** Before asking for review and again immediately before merging: `git fetch origin && git merge origin/main`, rebuild the census overlay on the merged tree, push, and wait for CI on that tip (`amadan ci status carlos/platform -branch db-region-forward-1-box`). Merge only with `git merge-base --is-ancestor origin/main HEAD && amadan branch merge carlos/platform db-region-forward-1-box -expect <tip> -message "..."`.
- **Test weights.** A new top-level test in `internal/console` or the root package that takes a second or more gets a row in `.amadan/test-weights.tsv` (Task 17 says how, without a full local run).
- **No CI-only scripts under `scripts/`.** CI steps live in `.amadan/ci.d/`.
- **New host tests call `t.Parallel()`** unless they touch env (`t.Setenv`), cwd, umask or package vars.
- **Scratch** goes under `$TMPDIR` or `t.TempDir()`, and is removed by name, never by pattern.
- **Wire shapes are additive.** Nothing this plan writes changes an existing object's shape. The edges file gains one capability string.
- **Spec numbers, verbatim.** Pickup window 60 s from `issued_at` plus 60 s of skew; planning and restore 10 min; query 5 min; owner deadline 20 min from `picked`; restored size 2 GiB (`CARLOS_DB_READ_MAX_BYTES`); output 64 MiB (`runs.MaxOutputBytes`); chunk 256 KiB or 1 s (`runs.ChunkBytes`, `runs.ChunkEvery`); two reads per box plus one probe connection (`MaxConnections=3`); disk floor 5 GiB and 10% free; cancel checked every 5 s; queue listed on every serial move and every 30 s; probe at start, every 5 minutes and after a worker that failed to start; worker exits 5 s after losing its connection.

## Review Focus

The five input classes the spec implies but no gate test names, most likely first. Each has its test in the owning task.

1. **SQL text that JSON escapes or rewrites.** `<`, `>`, `&`, U+2028 and invalid UTF-8 in `sql`. A person expects the box to run exactly the bytes they typed or be told no. `json.Marshal` rewrites invalid UTF-8 to U+FFFD, so the signed SQL would differ from the typed SQL. `Sign` refuses invalid UTF-8; the rest round-trips byte for byte through `Sign` and `Verify`. Test: Task 4, `TestEnvelopeSQLRoundTripsByteForByte`.
2. **The hour boundary.** A request issued at 10:59:50 is listed at 11:00:20 under the previous hour's queue prefix. A person expects it to be picked. Test: Task 12, `TestPassFindsAnEntryFromThePreviousHour`.
3. **A planned file that vanishes or changes size mid-download.** Litestream's compaction removes or rewrites L0 files. A person expects one quiet re-plan (with both identity checks again) and then `changed-twice`, never a half-restored copy and never a chunk. Test: Task 11, `TestReadRePlansOnceThenSaysChangedTwice`.
4. **Output at the cap.** Exactly 64 MiB, one byte over, and one row bigger than a chunk. A person expects the first 64 MiB, `output-cap`, and a summary whose count and hash cover exactly the kept bytes. Test: Task 11, `TestChunkWriterCapIsExact`.
5. **`systemctl` missing or failing.** The unit listing cannot be read. A person expects the box to take no read and skip (not fail) its probe, so a transient listing failure neither admits beside an orphan nor withdraws the capability. Test: Task 9, `TestAdmissionFailsClosedWhenUnitsCannotBeListed`, and Task 12, `TestProbeIsSkippedWhileAdmissionIsBlocked`.

## Plan review, round 1

Astra's findings (`docs/superpowers/specs/CODEX-FINDINGS-DB-REGION-FORWARD-PLANS.md`) for this plan, and where each landed:

- **1** (the installed worker could not pass readiness): `SelfView` reads `/proc/self/net/dev` (`net.Interfaces` needs `AF_NETLINK`, which `RestrictAddressFamilies=AF_UNIX` refuses), reports every observation it could not make in `HelloReply.Errors`, and the probe fails on any. Tests: `TestParseNetDev`, the probe's "an observation that failed" case.
- **2** (`waitFor` collides with `internal/host/housekeeper_test.go:139`): `dbreadWaitFor`.
- **3** (the payload's report parsed with `PASS` after it): the report is one `DBREAD-REPORT ` line the parent scans for.
- **4** (the readiness tests removed the wrong file): `dbreadServiceFile` is `/etc/systemd/system/carlos-dbread@.service`, restored by `mustSystemctl` in cleanup.
- **5** (the census bootstrap could not run): `TestZZDBForwardFingerprints` computes each `@legacy` line from its row; plans 2 and 3 use it.
- **9** (a result could name an unconfirmed chunk): `flushLocked` advances `seq` only once the create is confirmed; spec §5.4 says what the result then names. Test: `TestResultNamesOnlyConfirmedChunks`.
- **10** (a retry reused the reservation): `admission.retry` keeps the first attempt's reservation under its own key and `settle` waits for its unit to stop before the retry dials; spec §5.7 says so. Tests: `TestRetryWaitsForTheFirstWorkerToStop`, `TestAdmissionRetryHoldsTheOldReservation`.
- **11, the box's half**: a box reads `cancel` before it elects; spec §5.5 step 4 and §5.8. Test: `TestPassSkipsACancelledRequest`.
- **14** (draining boxes could win): `AgentConfig.Draining`, from the box's own edges record, checked before admission and again after the jitter. Test: `TestADrainingBoxDoesNotPick`.
- **15** (some start failures asked for no probe): every pre-ready transport failure asks for one. Test: `TestAWorkerThatNeverStartsAsksForAProbe`, and T13's fail-start case through the installed unit.
- **16** (the disk test assumed queue order): the second read is submitted only once the first's unit is running.
- **17** (T3 could not see `PrivateNetwork` go): the witness reports the interfaces the unit sees, and fails on any but loopback; ATTACH targets a real SQLite file.
- **21, the box's half**: the agent logs its planning-and-restore time and its confirmed output, for plan 3's measurement.

None declined.

## Plan review, round 2

From `CODEX-FINDINGS-DB-REGION-FORWARD-PLANS-R2.md`:

- **27** (the mask could not take): T13 swaps `/etc/systemd/system/carlos-dbread@.service` for a `/dev/null` symlink, proves `LoadState=masked`, then removes the symlink before restoring the file; cleanup removes before it writes.
- **29** (an owed probe could be lost): `Probe` answers whether it ran, `Run` retries a skipped one every `probeRetry`, and a failed worker's connection is closed before the probe is asked for (`closeThenProbe`), so admission sees the lingering unit. Test: `TestAProbeSkippedWhileTheUnitLingersRunsOnceItIsGone`, through `Run`.
- **26, plan 1's side**: plan 3 now keeps the two timing lines this plan writes.
- Every new top-level identifier in the three plans was checked against `origin/main` for a declaration of the same name in the same package (functions, types, variables, constants and methods on existing types); `dbStream` (plan 2) was the only collision.

None declined.

## Census impact

- **Plan 14 root-read census:** one overlay, `plan14-root-reads-db-region-forward-1.tsv`, `rev3=PROPOSED-db-region-forward-1`:
  - `db.go` `runQueryContext` keeps its name as a one-line wrapper that reads nothing, so main's legacy row is retired by an `@remove` plus an `@removed ... H3 census-ruling-db-region-forward-1 (PROPOSED, awaiting the census owner on #280): ...` row, the form the carlos-run and email-signin overlays used.
  - New legacy rows (class `legacy`, task `accepted-legacy`): `internal/dbquery` `RunContext` (the moved body plus the `Immutable` open option; both callers named), every flagged unit in `internal/dbreads` (agent units at J1 for record reads and J4 for object input; worker units at J4), `internal/dbdoor` `ListLevel` and `PlanFrom` and `RestoreLocal`, the host units that list `carlos-dbread@` units and `Statfs` `/var/tmp` (J4), and the two unit files `internal/host/units/carlos-dbread.socket` and `carlos-dbread@.service` as `external` units (the form `carlos-instance-cmd@.service` took).
  - One `diagnostic` row: the agent's readiness probe.
  - Envelopes re-pinned: `.`, `internal/dbquery` (new), `internal/dbreads` (new), `internal/dbdoor`, `internal/host`, `internal/host/units`, `internal/console`. Frozen declarations are added, so the seal moves; main's seal is checked first.
- **9B8 record-write census:** new `nonrecord` entries for the `Put` sites in `internal/dbreads` (`picked`, chunks, `result.json`), all conditional creates. No `Delete` site. No record writer.
- **go.mod:** unchanged, so no root-envelope overlay for it.

## Copy strings

Plan 1 creates the whole deck from spec §10 (every row `pending`) so its gate pins the full inventory, and builds one row:

| id | file | text |
|---|---|---|
| DBF-31 | docs/site/cli.md | carlos system db-worker runs on platform boxes only. systemd starts it for each forwarded database query. you never run it yourself. |

Rows DBF-1 to DBF-16, DBF-21, DBF-22, DBF-30 and DBF-32 are plan 2's to review and build.

## File structure

| File | Responsibility |
|---|---|
| `internal/dbquery/dbquery.go` (create) | The read-only query runner, its guards and its cell format, moved from `db.go`. |
| `internal/dbquery/dbquery_test.go` (create) | Guard table, immutable open, output format. |
| `db.go` (modify) | Thin wrappers onto `internal/dbquery`. |
| `internal/dbreads/limits.go` (create) | Every number from spec §5.7, named once. |
| `internal/dbreads/ids.go` (create) | `dbr_` ids and every `db-reads/` key, with parsers. |
| `internal/dbreads/envelope.go` (create) | The request envelope: `Request`, `Sign`, `Verify`, `QueueMatches`. |
| `internal/dbreads/seal.go` (create) | Reply keys, chunk and summary sealing. |
| `internal/dbreads/result.go` (create) | `Result`, `Picked`, `Summary`, states and codes. |
| `internal/dbreads/class.go` (create) | `ClassRefusal`, moved from the console. |
| `internal/dbreads/protocol.go` (create) | Worker framing and message types, shared by agent and worker. |
| `internal/dbreads/worker.go` (create) | `ServeWorker`: the worker's whole job, portable. |
| `internal/dbreads/worker_linux.go`, `worker_other.go` (create) | `RunWorker`: stdin socket and peer checks, the process exit. |
| `internal/dbreads/admission.go` (create) | Reservations, the read and connection counts, the orphan rule. |
| `internal/dbreads/agent.go` (create) | `Agent`: config, `Run`, `Pass`, `Probe`, `Capable`, election. |
| `internal/dbreads/read.go` (create) | One owned read: the identity bracket, planning, streaming, check B, output, result. |
| `internal/dbreads/chunks.go` (create) | `chunkWriter` and the create-only put with read-back. |
| `internal/dbdoor/plan_from.go` (create) | `ReplicaReader`, `ListLevel`, `PlanFrom`, `RestoreLocal`. |
| `internal/dbdoor/plan.go` (modify) | `RestorePlan` gains `Planned` and `At`; shared tail with `PlanFrom`. |
| `internal/console/apidb.go` (modify) | `listReplicaLevel` and `dbClassRefusal` delegate to the moved code. |
| `internal/host/units/carlos-dbread.socket`, `carlos-dbread@.service` (create) | The worker's units. |
| `internal/host/systemunits.go` (modify) | Installs and arms the two units. |
| `internal/host/dbreads.go` (create) | Arming, the env gate, the capability, the nudge. |
| `internal/host/dbreads_linux.go`, `dbreads_other.go` (create) | Dialing the socket, listing units, `Statfs`. |
| `internal/host/edgesfile.go`, `agent.go` (modify) | Publish `db-read-1`; arm the loop; nudge on serial moves. |
| `system.go` (modify) | `carlos system db-worker`. |
| `approved_db_forward_copy_test.go` (create) | The copy gate. |
| `docs/superpowers/plans/2026-10-22-db-region-forward-copy.md` (create) | The copy record. |
| `internal/console/dbreads_parity_test.go` (create) | The parity half of T6. |
| `internal/host/dbreads_rootrunner_linux_test.go` (create) | T2, T3, T12, T13 on the root runner. |
| `internal/provision/testdata/plan14-root-reads-db-region-forward-1.tsv` (create), `plan14_root_reads_test.go`, `db_region_forward_census_test.go` (create) | Census. |
| `docs/superpowers/notes/census-proposal-db-region-forward-1.md` (create) | The census proposal for #280. |

---

### Task 1: The copy record and its gate

**Files:**
- Create: `docs/superpowers/plans/2026-10-22-db-region-forward-copy.md`
- Create: `approved_db_forward_copy_test.go`

**Interfaces:**
- Consumes: `parseCopyTable`, `checkMovesInventory`, `checkMovesNoEmDash`, `checkRunBuilt`, `builtRows`, `checkRunApplied`, `reportAll`, `copyRow` (root package test helpers in `approved_moves_copy_test.go` and `approved_run_copy_test.go`).
- Produces: `dbForwardCopyIDs` (the pinned inventory) and `dbForwardCopyBuilt` (empty here; Task 16 and plans 2 and 3 append to it).

- [ ] **Step 1: Write the record**

Create `docs/superpowers/plans/2026-10-22-db-region-forward-copy.md`:

```markdown
# `carlos db` region forward: copy record

Every user-facing string the db region forward plans write (spec
`2026-10-22-db-region-forward-design.md` §10): console refusals, the CLI's
sentences, the audit details and the docs prose. The gate is
`approved_db_forward_copy_test.go` at the repo root. It reuses the moves
gate's parser, so the format is the moves record's: one table per heading,
columns id, file, text, status.

The rules:

- A row is `pending` until Paul approves it in the copy review (the
  `copy-review` skill). His edits are applied to the text here verbatim and
  the row becomes `approved`.
- No pending string reaches code or docs. The task that writes a row's
  text adds its id to `dbForwardCopyBuilt` in the gate in the same commit,
  and from then on the gate fails unless the row is `approved` and its
  text is in the file it names.
- In a Go file the text is one string literal, or one `fmt.Sprintf`,
  `fmt.Errorf` or `errors.New` format, equal to the row with a format verb
  where the row has a `<placeholder>`. No trailing newline inside the
  literal.
- A table cell holds one line, so a row's text writes a paragraph break as
  `\n\n`. In `docs/site/cli.md` each paragraph of a row is one line.
- No em dashes. A full stop and a new sentence instead, continuing in lower
  case. Docs prose keeps the CLI page's sentence case.
- Ids are not renumbered. DBF-17 to DBF-20 and DBF-23 to DBF-29 are kept
  for plan 3's pull rows.

Placeholders: `<host>` the instance's hostname; `<region>` a placement code
such as uk; `<size>` and `<cap>` byte sizes as the CLI prints them; `<n>` a
count of bytes; `<sha>` the first 16 hex digits of a SHA-256; `<time>` an
RFC 3339 time.

## Console (plan 2)

| id | file | text | status |
|---|---|---|---|
| DBF-1 | internal/console/apidbforward.go | <host> keeps its data in region <region>. no server in that region can read databases yet, so carlos db cannot read it for now. | pending |
| DBF-2 | internal/console/apidbforward.go | <host> keeps its data in region <region>. no server in that region is answering right now. try again in a few minutes. | pending |
| DBF-9 | internal/console/apidbforward.go | too many database reads are open. wait a minute and try again. | pending |
| DBF-10 | internal/console/apidbforward.go | <host> is moving between regions. read its database once the move has finished. | pending |
| DBF-14 | internal/console/apidbforward.go | <host> keeps its data in region <region>. this version of carlos cannot read it from there. run carlos update, then try again. | pending |
| DBF-21 | internal/console/apidbforward.go | forwarded a database query to region <region>. the query was <n> bytes, sha256 <sha> (cli) | pending |
| DBF-22 | internal/console/apidbforward.go | forwarded a database query to region <region>, as of <time>. the query was <n> bytes, sha256 <sha> (cli) | pending |

## CLI (plan 2)

| id | file | text | status |
|---|---|---|---|
| DBF-3 | dbforward.go | no server in region <region> picked up the read within 60 seconds. try again in a few minutes. | pending |
| DBF-4 | dbforward.go | <host>'s database is <size> once restored. carlos db can query at most <cap> in region <region>. | pending |
| DBF-5 | dbforward.go | the server in region <region> does not have room to restore <host>'s database right now. try again later. | pending |
| DBF-6 | dbforward.go | the result was cut off at 64 MB. narrow the query with WHERE or LIMIT and run it again. | pending |
| DBF-7 | dbforward.go | the query ran for 5 minutes and was stopped. narrow it and run it again. | pending |
| DBF-8 | dbforward.go | <host> keeps its data in region <region>. carlos db pull cannot fetch a copy from there yet. carlos db query can read it. | pending |
| DBF-11 | dbforward.go | reading a copy of <host>'s database in region <region>. | pending |
| DBF-12 | dbforward.go | the read of <host>'s database in region <region> did not finish, so nothing was printed. try again. | pending |
| DBF-13 | dbforward.go | the answer from region <region> did not check out, so carlos db showed none of it. try again. | pending |
| DBF-15 | dbforward.go | <host> changed while the read was waiting. try again. | pending |
| DBF-16 | dbforward.go | <host> is moving between regions. read its database once the move has finished. | pending |
| DBF-32 | dbforward.go | this query cannot be sent to region <region>, because it holds bytes that are not UTF-8 text or the character U+FFFD. fix the query and run it again. | pending |

## Docs

| id | file | text | status |
|---|---|---|---|
| DBF-30 | docs/site/cli.md | If the app has more than one instance, name one with `--instance`. Only instances that sleep have a replica. An instance on your own fleet or in a pool cannot be read this way, and the command says which.\n\nWhen an instance keeps its data in another region than the console's, `carlos db query` runs in that region. A server there restores the copy, runs your query and sends back only the rows. The rows are encrypted for your terminal on the way, so nothing in between can read them, and nothing is printed until all of them have arrived and checked out. There, the copy can be at most 2 GB once restored, the query runs for at most 5 minutes, and the rows can come to at most 64 MB. `carlos db pull` cannot fetch a copy from another region yet. | pending |
| DBF-31 | docs/site/cli.md | carlos system db-worker runs on platform boxes only. systemd starts it for each forwarded database query. you never run it yourself. | pending |
```

- [ ] **Step 2: Write the gate**

Create `approved_db_forward_copy_test.go`:

```go
// approved_db_forward_copy_test.go
package main

import (
	"os"
	"regexp"
	"strconv"
	"strings"
	"testing"
)

// The copy gate of the db region forward plans (spec 2026-10-22 §10), the
// region HA 2b gate over this record:
//
//   - TestDBForwardCopyRecordIsComplete: the record names exactly
//     dbForwardCopyIDs;
//   - TestDBForwardCopyHasNoEmDash;
//   - TestDBForwardBuiltCopyIsApproved: an id in dbForwardCopyBuilt is an
//     approved row. No pending string reaches code or docs;
//   - TestDBForwardBuiltCopyIsApplied: a built row's text is in the file it
//     names.
const dbForwardCopyRecordPath = "docs/superpowers/plans/2026-10-22-db-region-forward-copy.md"

var dbForwardCopyIDPattern = regexp.MustCompile(`^DBF-[0-9]+$`)

// dbForwardCopyIDs is the record's inventory, pinned: DBF-1 to DBF-16,
// DBF-21, DBF-22, DBF-30, DBF-31 and DBF-32. Plan 3 adds its pull rows here.
var dbForwardCopyIDs = func() []string {
	ids := make([]string, 0, 21)
	for i := 1; i <= 16; i++ {
		ids = append(ids, "DBF-"+strconv.Itoa(i))
	}
	return append(ids, "DBF-21", "DBF-22", "DBF-30", "DBF-31", "DBF-32")
}()

// dbForwardCopyBuilt is every id whose text the code or docs carry. The task
// that writes a row's text adds its id here in the same commit, once Paul has
// approved the row.
var dbForwardCopyBuilt = []string{}

func mustParseDBForwardRecord(t *testing.T) []copyRow {
	t.Helper()
	raw, err := os.ReadFile(dbForwardCopyRecordPath)
	if err != nil {
		t.Fatal(err)
	}
	rows, err := parseCopyTable(string(raw), dbForwardCopyRecordPath, dbForwardCopyIDPattern, "a DBF-<n>")
	if err != nil {
		t.Fatal(err)
	}
	return rows
}

func TestDBForwardCopyRecordIsComplete(t *testing.T) {
	reportAll(t, checkMovesInventory(mustParseDBForwardRecord(t), dbForwardCopyIDs))
}

func TestDBForwardCopyHasNoEmDash(t *testing.T) {
	reportAll(t, checkMovesNoEmDash(mustParseDBForwardRecord(t)))
}

func TestDBForwardBuiltCopyIsApproved(t *testing.T) {
	reportAll(t, checkRunBuilt(mustParseDBForwardRecord(t), dbForwardCopyBuilt))
}

func TestDBForwardBuiltCopyIsApplied(t *testing.T) {
	rows := builtRows(mustParseDBForwardRecord(t), dbForwardCopyBuilt)
	for i := range rows {
		rows[i].Text = strings.ReplaceAll(rows[i].Text, `\n`, "\n")
	}
	reportAll(t, checkRunApplied(rows, "."))
}
```

- [ ] **Step 3: Run the gate**

Run: `go test . -run 'TestDBForward' -count=1`
Expected: PASS (four tests). A FAIL from `TestDBForwardCopyRecordIsComplete` means a row id is missing or extra; fix the record, not the inventory.

- [ ] **Step 4: Commit**

```bash
git add docs/superpowers/plans/2026-10-22-db-region-forward-copy.md approved_db_forward_copy_test.go
git commit -m "db forward: copy record (all rows pending) and its gate"
```

- [ ] **Step 5: Ask for DBF-31's review**

Invoke the `copy-review` skill with DBF-31 only (its context: the `carlos system` section of the CLI page; nobody runs the verb by hand). Apply Paul's text verbatim to the record, set the row to `approved`, and commit the record alone: `git commit -m "db forward: DBF-31 approved"`. Task 16 waits for this; every other task does not.

---

### Task 2: `internal/dbquery`, the query runner both callers share

**Files:**
- Create: `internal/dbquery/dbquery.go`
- Create: `internal/dbquery/dbquery_test.go`
- Modify: `db.go:384-684` (the runner, the guard and the tokenizer move out; thin wrappers stay)

**Interfaces:**
- Produces: `dbquery.RunContext(ctx context.Context, w io.Writer, path, sqlText string, opt dbquery.Options) error`; `dbquery.Options{Immutable bool}`; `dbquery.CheckSQL(q string) error`; `dbquery.Cell(v any) string`; `dbquery.ErrOneStatement`, `dbquery.ErrPragmaChange`.
- Keeps (in `db.go`, for its callers and tests): `runQuery`, `runQueryContext`, `checkQuerySQL`, `dbQueryCell`, `errOneStatement`, `errPragmaChange` as one-line wrappers.

- [ ] **Step 1: Write the failing test**

Create `internal/dbquery/dbquery_test.go`:

```go
package dbquery

import (
	"bytes"
	"context"
	"database/sql"
	"errors"
	"path/filepath"
	"strings"
	"testing"

	_ "modernc.org/sqlite"
)

func fixtureDB(t *testing.T) string {
	t.Helper()
	path := filepath.Join(t.TempDir(), "shop.db")
	db, err := sql.Open("sqlite", path)
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	for _, q := range []string{
		`CREATE TABLE orders (id INTEGER PRIMARY KEY, note TEXT, data BLOB)`,
		`INSERT INTO orders (note, data) VALUES ('a	tab', x'00ff'), (NULL, NULL), ('two
lines', 'x')`,
	} {
		if _, err := db.Exec(q); err != nil {
			t.Fatal(err)
		}
	}
	return path
}

func TestRunContextFormatsLikeTheCLI(t *testing.T) {
	t.Parallel()
	path := fixtureDB(t)
	for _, opt := range []Options{{}, {Immutable: true}} {
		var out bytes.Buffer
		if err := RunContext(context.Background(), &out, path, "SELECT id, note FROM orders ORDER BY id", opt); err != nil {
			t.Fatalf("%+v: %v", opt, err)
		}
		want := "id\tnote\n1\ta\\ttab\n2\tNULL\n3\ttwo\\nlines\n"
		if out.String() != want {
			t.Fatalf("%+v: got %q, want %q", opt, out.String(), want)
		}
	}
}

func TestRunContextRefusesWritesAndAttach(t *testing.T) {
	t.Parallel()
	path := fixtureDB(t)
	for _, opt := range []Options{{}, {Immutable: true}} {
		for _, q := range []string{
			"DELETE FROM orders",
			"ATTACH DATABASE 'x.db' AS x",
			"VACUUM INTO 'copy.db'",
		} {
			if err := RunContext(context.Background(), &bytes.Buffer{}, path, q, opt); err == nil {
				t.Fatalf("%+v: %q ran", opt, q)
			}
		}
	}
}

func TestCheckSQLTable(t *testing.T) {
	t.Parallel()
	for _, c := range []struct {
		q    string
		want error
	}{
		{"SELECT 1", nil},
		{"SELECT 1; SELECT 2", ErrOneStatement},
		{"SELECT ';' AS x", nil},
		{"PRAGMA table_info(orders)", nil},
		{"PRAGMA query_only = 0", ErrPragmaChange},
		{"EXPLAIN QUERY PLAN PRAGMA writable_schema=1", ErrPragmaChange},
		{"SELECT pragma FROM t", nil},
	} {
		if got := CheckSQL(c.q); !errors.Is(got, c.want) && !(got == nil && c.want == nil) {
			t.Errorf("CheckSQL(%q) = %v, want %v", c.q, got, c.want)
		}
	}
}

func TestImmutableOpenAddsTheFlagOnly(t *testing.T) {
	t.Parallel()
	if got := dsn("/x/copy.db", Options{}); strings.Contains(got, "immutable") {
		t.Fatalf("the CLI's open changed: %s", got)
	}
	if got := dsn("/x/copy.db", Options{Immutable: true}); !strings.Contains(got, "mode=ro&immutable=1&") {
		t.Fatalf("the worker's open lacks immutable=1: %s", got)
	}
}
```

- [ ] **Step 2: Run it to verify it fails**

Run: `go test ./internal/dbquery/ -count=1`
Expected: FAIL, the package does not exist.

- [ ] **Step 3: Move the code**

Create `internal/dbquery/dbquery.go`. Move, unchanged except for names and the `dsn` helper, the bodies of `runQueryContext`, `dbQueryCell`, `errOneStatement`, `errPragmaChange`, `dbReadPragmas`, `checkQuerySQL`, `sqlTokenKind` and its constants, `sqlToken`, `utf8BOM`, `sqlTokens`, `isSQLIdentByte`, `splitFirstStatement` and `skipQuoted` from `db.go` (lines 384 to 684 at main `5f341f33`). The renamed exported surface and the one new helper:

```go
// Package dbquery is the one read-only query runner `carlos db query` uses:
// on a member's machine (the CLI, db.go) and inside the db-read worker on a
// box (internal/dbreads, spec 2026-10-22 §8.3). It moved out of db.go so the
// guards, the open flags and the output format cannot drift between the two.
package dbquery

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"io"
	"strings"
	"time"

	"modernc.org/sqlite"
	sqlitelib "modernc.org/sqlite/lib"
)

// Options are the only difference between the two callers. Immutable adds
// immutable=1 to the open: the worker's copy is a file nothing else ever
// writes (spec §8.3).
type Options struct {
	Immutable bool
}

// ErrOneStatement and ErrPragmaChange are the two refusals before SQLite sees
// anything. Their text is the CLI's, unchanged.
var (
	ErrOneStatement = errors.New("carlos db query runs one statement at a time. Run each statement on its own")
	ErrPragmaChange = errors.New("this pragma changes how the copy is read, so carlos db query does not run it. Reading a pragma's value is fine")
)

// dsn is the open string. temp_store(2) keeps sorts and temp b-trees in
// memory, so a large query cannot spill plaintext pages to a file outside the
// private directory.
func dsn(path string, opt Options) string {
	mode := "mode=ro"
	if opt.Immutable {
		mode = "mode=ro&immutable=1"
	}
	return "file:" + path + "?" + mode + "&_pragma=query_only(1)&_pragma=busy_timeout(5000)&_pragma=temp_store(2)"
}

// RunContext opens path read-only, both ways (mode=ro and query_only), runs
// sqlText, and writes a header row then one tab-separated line per row. It
// is db.go's runQueryContext with the open string from dsn.
func RunContext(ctx context.Context, w io.Writer, path, sqlText string, opt Options) error {
	if err := CheckSQL(sqlText); err != nil {
		return err
	}
	db, err := sql.Open("sqlite", dsn(path, opt))
	if err != nil {
		return err
	}
	defer db.Close()
	conn, err := db.Conn(ctx)
	if err != nil {
		return err
	}
	defer conn.Close()
	// mode=ro covers only main, and query_only is a pragma the statement
	// list itself can switch off. ATTACH opens with the connection's
	// read-write flags, so it is the way around both. VACUUM INTO attaches
	// internally. No attached databases at all closes every one of those.
	if _, err := sqlite.Limit(conn, sqlitelib.SQLITE_LIMIT_ATTACHED, 0); err != nil {
		return err
	}
	rows, err := conn.QueryContext(ctx, sqlText)
	if err != nil {
		return err
	}
	defer rows.Close()
	cols, err := rows.Columns()
	if err != nil {
		return err
	}
	if len(cols) > 0 {
		if _, err := fmt.Fprintln(w, strings.Join(cols, "\t")); err != nil {
			return err
		}
	}
	vals := make([]any, len(cols))
	ptrs := make([]any, len(cols))
	for i := range vals {
		ptrs[i] = &vals[i]
	}
	line := make([]string, len(cols))
	for rows.Next() {
		if err := rows.Scan(ptrs...); err != nil {
			return err
		}
		for i, v := range vals {
			line[i] = Cell(v)
		}
		if _, err := fmt.Fprintln(w, strings.Join(line, "\t")); err != nil {
			return err
		}
	}
	return rows.Err()
}

// Cell renders one value: NULL spelled out, tabs and newlines escaped.
func Cell(v any) string {
	var s string
	switch x := v.(type) {
	case nil:
		return "NULL"
	case []byte:
		s = string(x)
	case time.Time:
		s = x.UTC().Format(time.RFC3339Nano)
	default:
		s = fmt.Sprint(x)
	}
	return strings.NewReplacer("\\", `\\`, "\t", `\t`, "\n", `\n`, "\r", `\r`).Replace(s)
}
```

`CheckSQL` is `checkQuerySQL`'s body verbatim, returning `ErrOneStatement` and `ErrPragmaChange`; keep every doc comment that travels with the moved code.

In `db.go`, delete the moved declarations and the now unused imports (`database/sql`, `modernc.org/sqlite`, `sqlitelib`), and add:

```go
// The query runner and its guards live in internal/dbquery (spec 2026-10-22
// §8.3), so the CLI and the db-read worker run one copy of them. These
// names stay for db.go's callers and tests.
var (
	errOneStatement = dbquery.ErrOneStatement
	errPragmaChange = dbquery.ErrPragmaChange
)

func checkQuerySQL(q string) error { return dbquery.CheckSQL(q) }

func dbQueryCell(v any) string { return dbquery.Cell(v) }

func runQuery(w io.Writer, path, sqlText string) error {
	return runQueryContext(context.Background(), w, path, sqlText)
}

// runQueryContext reads nothing itself: the open and the query are
// dbquery.RunContext's.
func runQueryContext(ctx context.Context, w io.Writer, path, sqlText string) error {
	return dbquery.RunContext(ctx, w, path, sqlText, dbquery.Options{})
}
```

- [ ] **Step 4: Run the tests**

Run: `go test ./internal/dbquery/ -count=1 && go test . -run 'TestQuery|TestCheckQuerySQL|TestDBQuery|TestRunQuery' -count=1`
Expected: PASS. The root package's existing `db_test.go` tests run unchanged through the wrappers; if a name in that `-run` matches nothing, list the tests with `grep -n '^func Test' db_test.go` and run those names.

- [ ] **Step 5: Commit**

```bash
gofmt -l db.go internal/dbquery
git add internal/dbquery db.go
git commit -m "dbquery: the carlos db query runner and guards, shared by the CLI and the worker"
```

---

### Task 3: `internal/dbreads` ids, keys and limits

**Files:**
- Create: `internal/dbreads/limits.go`
- Create: `internal/dbreads/ids.go`
- Create: `internal/dbreads/ids_test.go`

**Interfaces:**
- Produces: the constants below; `NewID(r io.Reader) (string, error)`, `MintID() (string, error)`, `ValidID(string) bool`, `ValidRegion(string) bool`; `RequestKey`, `PickedKey`, `OutPrefix`, `ResultKey`, `CancelKey` (each `func(id string) string`); `ChunkKey(id string, seq int64) string`; `ParseChunkKey(key, outPrefix string) (int64, bool)`; `QueueRegionPrefix(region string) string`; `QueueHourPrefix(region string, t time.Time) string`; `QueueKey(region string, issued time.Time, id string) string`; `type QueueEntry struct{ Region, Hour, ID string; Issued time.Time }`; `ParseQueueKey(key string) (QueueEntry, bool)`; `InWindow(issued, now time.Time) bool`.

- [ ] **Step 1: Write the failing test**

Create `internal/dbreads/ids_test.go`:

```go
package dbreads

import (
	"bytes"
	"strings"
	"testing"
	"time"
)

func TestIDsAreDbrAnd26Base32(t *testing.T) {
	t.Parallel()
	id, err := NewID(bytes.NewReader(make([]byte, 16)))
	if err != nil || id != "dbr_aaaaaaaaaaaaaaaaaaaaaaaaaa" || !ValidID(id) {
		t.Fatalf("NewID = %q, %v", id, err)
	}
	minted, err := MintID()
	if err != nil || !ValidID(minted) {
		t.Fatalf("MintID = %q, %v", minted, err)
	}
	for _, bad := range []string{"", "run_aaaaaaaaaaaaaaaaaaaaaaaaaa", "dbr_AAAAAAAAAAAAAAAAAAAAAAAAAA", "dbr_aaaa", "queue", "dbr_aaaaaaaaaaaaaaaaaaaaaaaaa/"} {
		if ValidID(bad) {
			t.Errorf("ValidID(%q) = true", bad)
		}
	}
}

func TestKeysLiveUnderOnePrefix(t *testing.T) {
	t.Parallel()
	id := "dbr_aaaaaaaaaaaaaaaaaaaaaaaaaa"
	for _, k := range []string{RequestKey(id), PickedKey(id), ChunkKey(id, 1), ResultKey(id), CancelKey(id),
		QueueKey("uk", time.Date(2026, 10, 22, 9, 0, 5, 0, time.UTC), id)} {
		if !strings.HasPrefix(k, "db-reads/") {
			t.Errorf("%s is outside db-reads/", k)
		}
	}
	if got := ChunkKey(id, 12); got != "db-reads/"+id+"/out/00000012" {
		t.Fatalf("ChunkKey = %s", got)
	}
	if seq, ok := ParseChunkKey(ChunkKey(id, 12), OutPrefix(id)); !ok || seq != 12 {
		t.Fatalf("ParseChunkKey = %d %v", seq, ok)
	}
	for _, bad := range []string{OutPrefix(id) + "0000001", OutPrefix(id) + "-0000001", OutPrefix(id) + "00000000", OutPrefix(id) + "0000001x"} {
		if _, ok := ParseChunkKey(bad, OutPrefix(id)); ok {
			t.Errorf("ParseChunkKey(%q) accepted", bad)
		}
	}
}

func TestQueueKeyRoundTrips(t *testing.T) {
	t.Parallel()
	id := "dbr_bbbbbbbbbbbbbbbbbbbbbbbbbb"
	issued := time.Date(2026, 10, 22, 10, 59, 50, 0, time.UTC)
	key := QueueKey("uk", issued, id)
	if key != "db-reads/queue/uk/2026102210/1792666790-"+id {
		t.Fatalf("QueueKey = %s", key)
	}
	e, ok := ParseQueueKey(key)
	if !ok || e.Region != "uk" || e.Hour != "2026102210" || !e.Issued.Equal(issued) || e.ID != id {
		t.Fatalf("ParseQueueKey = %+v %v", e, ok)
	}
	for _, bad := range []string{
		"db-reads/queue/uk/2026102210/x-" + id,
		"db-reads/queue/uk/20261022/1792666790-" + id,
		"db-reads/queue/../2026102210/1792666790-" + id,
		"db-reads/queue/uk/2026102210/01792666790-" + id,
		"db-reads/queue/uk/2026102210/1792666790-run_bbbbbbbbbbbbbbbbbbbbbbbbbb",
	} {
		if _, ok := ParseQueueKey(bad); ok {
			t.Errorf("ParseQueueKey(%q) accepted", bad)
		}
	}
}

func TestInWindowIs60sPlus60sOfSkew(t *testing.T) {
	t.Parallel()
	now := time.Date(2026, 10, 22, 9, 0, 0, 0, time.UTC)
	for _, c := range []struct {
		issued time.Time
		want   bool
	}{
		{now, true},
		{now.Add(-120 * time.Second), true},
		{now.Add(-121 * time.Second), false},
		{now.Add(60 * time.Second), true},
		{now.Add(61 * time.Second), false},
	} {
		if got := InWindow(c.issued, now); got != c.want {
			t.Errorf("InWindow(%s) = %v", c.issued.Sub(now), got)
		}
	}
}
```

- [ ] **Step 2: Run it to verify it fails**

Run: `go test ./internal/dbreads/ -count=1`
Expected: FAIL, the package does not exist.

- [ ] **Step 3: Write `limits.go` and `ids.go`**

Create `internal/dbreads/limits.go`:

```go
// Package dbreads is a forwarded `carlos db` read (spec
// docs/superpowers/specs/2026-10-22-db-region-forward-design.md): the wire
// the console, the box and the CLI share, and the box's half of the work.
// Every object lives under db-reads/ in the deployment bucket and is a
// conditional create; the store's lifecycle rule is the only deletion (J2,
// J4).
package dbreads

import (
	"time"

	"github.com/carlosframework/platform/internal/runs"
)

// Capability is what a box publishes in its edges file while its armed
// db-reads loop's last readiness probe passed (spec §7.1).
const Capability = "db-read-1"

// Purpose is the envelope's fixed purpose and the sealing's HKDF info: one
// string, so nothing else signed by the root or sealed by this package can be
// mistaken for a db read.
const Purpose = "carlos-db-read-v1"

// Prefix is the one prefix every db read object lives under.
const Prefix = "db-reads/"

const (
	OpQuery = "query"
	OpPull  = "pull" // plan 3

	PickupWindow   = 60 * time.Second // from issued_at (§5.7)
	Skew           = 60 * time.Second
	ConsoleWaitsPicked = 2 * time.Minute
	PlanBudget     = 10 * time.Minute
	QueryTimeout   = 5 * time.Minute
	OwnerDeadline  = 20 * time.Minute
	OwnerGrace     = time.Minute
	RequestBound   = 22 * time.Minute
	CLIBound       = 23 * time.Minute
	CancelEvery    = 5 * time.Second
	ListEvery      = 30 * time.Second
	ProbeEvery     = 5 * time.Minute
	WorkerExitGrace = 5 * time.Second
	MaxJitter      = 500 * time.Millisecond

	DefaultMaxRestored int64 = 2 << 30 // CARLOS_DB_READ_MAX_BYTES
	MaxOutputBytes           = runs.MaxOutputBytes
	ChunkBytes               = runs.ChunkBytes
	ChunkEvery               = runs.ChunkEvery

	ReadsPerBox    = 2
	MaxConnections = 3 // two reads and one probe (carlos-dbread.socket)
	OpenPerPerson  = 2
	OpenPerConsole = 16

	DiskFloor       int64 = 5 << 30
	DiskFreePercent       = 10

	// MaxSQLBytes keeps a request well inside the root envelope's payload
	// bound (release.MaxRootEnvelopeBytes/2).
	MaxSQLBytes = 256 << 10
)
```

Run `gofmt -w internal/dbreads/limits.go` after writing it; the alignment above is not gofmt's.

Create `internal/dbreads/ids.go`:

```go
package dbreads

import (
	"crypto/rand"
	"encoding/base32"
	"fmt"
	"io"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var idEnc = base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567").WithPadding(base32.NoPadding)

var (
	idShape     = regexp.MustCompile(`^dbr_[a-z2-7]{26}$`)
	regionShape = regexp.MustCompile(`^[a-z][a-z0-9-]{0,31}$`)
	hourShape   = regexp.MustCompile(`^[0-9]{10}$`)
)

// NewID mints an id from r: "dbr_" and 26 lowercase base32 characters, 128
// random bits, the way runs.NewID mints run ids. Production mints with MintID.
func NewID(r io.Reader) (string, error) {
	var b [16]byte
	if _, err := io.ReadFull(r, b[:]); err != nil {
		return "", err
	}
	return "dbr_" + idEnc.EncodeToString(b[:]), nil
}

func MintID() (string, error) { return NewID(rand.Reader) }

// ValidID reports a db read id: 30 bytes of [a-z2-7_], one clean path
// element, and never "queue".
func ValidID(id string) bool { return idShape.MatchString(id) }

// ValidRegion reports a placement code that can be one key segment. A fleet
// placement ("fleet/x") is not one: fleet instances never forward.
func ValidRegion(r string) bool { return regionShape.MatchString(r) }

func RequestKey(id string) string { return Prefix + id + "/request.json" }
func PickedKey(id string) string  { return Prefix + id + "/picked" }
func OutPrefix(id string) string  { return Prefix + id + "/out/" }
func ResultKey(id string) string  { return Prefix + id + "/result.json" }
func CancelKey(id string) string  { return Prefix + id + "/cancel" }

// ChunkKey is out/<seq>, zero-padded to 8 digits so keys sort in order.
func ChunkKey(id string, seq int64) string { return OutPrefix(id) + fmt.Sprintf("%08d", seq) }

// ParseChunkKey reads a key ChunkKey made under outPrefix.
func ParseChunkKey(key, outPrefix string) (int64, bool) {
	name, ok := strings.CutPrefix(key, outPrefix)
	if !ok || len(name) != 8 {
		return 0, false
	}
	for i := 0; i < 8; i++ {
		if name[i] < '0' || name[i] > '9' {
			return 0, false
		}
	}
	seq, err := strconv.ParseInt(name, 10, 64)
	if err != nil || seq < 1 {
		return 0, false
	}
	return seq, true
}

const hourLayout = "2006010215"

func QueueRegionPrefix(region string) string { return Prefix + "queue/" + region + "/" }

func QueueHourPrefix(region string, t time.Time) string {
	return QueueRegionPrefix(region) + t.UTC().Format(hourLayout) + "/"
}

// QueueKey is the empty pointer the console writes after the request:
// db-reads/queue/<region>/<YYYYMMDDHH>/<unix>-<id>. A box can skip an
// out-of-window entry from its key alone (spec §5.4).
func QueueKey(region string, issued time.Time, id string) string {
	return QueueHourPrefix(region, issued) + strconv.FormatInt(issued.Unix(), 10) + "-" + id
}

// QueueEntry is a parsed queue key.
type QueueEntry struct {
	Region, Hour, ID string
	Issued           time.Time
}

func ParseQueueKey(key string) (QueueEntry, bool) {
	rest, ok := strings.CutPrefix(key, Prefix+"queue/")
	if !ok {
		return QueueEntry{}, false
	}
	parts := strings.Split(rest, "/")
	if len(parts) != 3 || !ValidRegion(parts[0]) || !hourShape.MatchString(parts[1]) {
		return QueueEntry{}, false
	}
	unixRaw, id, ok := strings.Cut(parts[2], "-")
	if !ok || !ValidID(id) {
		return QueueEntry{}, false
	}
	unix, err := strconv.ParseInt(unixRaw, 10, 64)
	if err != nil || unix <= 0 || strconv.FormatInt(unix, 10) != unixRaw {
		return QueueEntry{}, false
	}
	return QueueEntry{Region: parts[0], Hour: parts[1], ID: id, Issued: time.Unix(unix, 0).UTC()}, true
}

// InWindow is the box's pickup window: no more than PickupWindow plus Skew
// old, and no more than Skew in the future (spec §5.5, §5.7).
func InWindow(issued, now time.Time) bool {
	return !issued.Before(now.Add(-PickupWindow-Skew)) && !issued.After(now.Add(Skew))
}
```

- [ ] **Step 4: Run the tests**

Run: `gofmt -l internal/dbreads; go test ./internal/dbreads/ -count=1`
Expected: no gofmt output; PASS.

- [ ] **Step 5: Commit**

```bash
git add internal/dbreads/limits.go internal/dbreads/ids.go internal/dbreads/ids_test.go
git commit -m "dbreads: ids, db-reads/ keys and the spec's limits"
```

---

### Task 4: The request envelope

**Files:**
- Create: `internal/dbreads/envelope.go`
- Create: `internal/dbreads/envelope_test.go`

**Interfaces:**
- Consumes: `release.Signer`, `release.RootSigner`, `release.SignRootEnvelope`, `release.VerifyRootEnvelope`, `release.ValidAccount`, `release.ValidApp`, `provision.ValidHostShape`; `ParseReplyKey` (Task 5; write Task 5's `seal.go` reply-key functions first if you take Task 4 alone, or do Tasks 4 and 5 in one sitting).
- Produces: `type Request struct` (fields below, JSON exactly spec §5.5); `Sign(sg release.Signer, req Request) ([]byte, error)`; `Verify(pub ed25519.PublicKey, wire []byte, id, region string, now time.Time) (Request, error)`; `QueueMatches(e QueueEntry, req Request) bool`; `(Request) AtTime() (time.Time, error)`; `(Request) Issued() (time.Time, error)`; `ErrEnvelope`.

- [ ] **Step 1: Write the failing test**

Create `internal/dbreads/envelope_test.go`:

```go
package dbreads

import (
	"crypto/ed25519"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"errors"
	"strconv"
	"strings"
	"testing"
	"time"

	"github.com/carlosframework/platform/internal/release"
)

var testNow = time.Date(2026, 10, 22, 9, 0, 0, 0, time.UTC)

func testRequest(t *testing.T) Request {
	t.Helper()
	priv, err := NewReplyKey()
	if err != nil {
		t.Fatal(err)
	}
	return Request{
		ID: "dbr_aaaaaaaaaaaaaaaaaaaaaaaaaa", Account: "bab", App: "shop", Host: "shop.example.com",
		Incarnation: "inc", Region: "uk", Op: OpQuery, SQL: "SELECT count(*) FROM orders",
		ReplyKey: EncodeReplyKey(priv.PublicKey()), By: "member@example.com",
		IssuedAt: testNow.Format(time.RFC3339),
	}
}

func rootKeys(t *testing.T) (ed25519.PublicKey, ed25519.PrivateKey) {
	t.Helper()
	pub, priv, err := ed25519.GenerateKey(rand.Reader)
	if err != nil {
		t.Fatal(err)
	}
	return pub, priv
}

func TestEnvelopeVerifiesWhatTheRootSigned(t *testing.T) {
	t.Parallel()
	pub, priv := rootKeys(t)
	req := testRequest(t)
	wire, err := Sign(release.RootSigner(priv), req)
	if err != nil {
		t.Fatal(err)
	}
	got, err := Verify(pub, wire, req.ID, "uk", testNow.Add(30*time.Second))
	if err != nil {
		t.Fatal(err)
	}
	req.Purpose, req.V = Purpose, 1
	if got != req {
		t.Fatalf("got %+v, want %+v", got, req)
	}
}

// T4 (spec §11.4), the envelope half: every forgery and replay the envelope
// alone must stop.
func TestEnvelopeRefusesForgeryAndReplay(t *testing.T) {
	t.Parallel()
	pub, priv := rootKeys(t)
	_, otherPriv := rootKeys(t)
	req := testRequest(t)
	good, err := Sign(release.RootSigner(priv), req)
	if err != nil {
		t.Fatal(err)
	}
	unsigned, _ := json.Marshal(map[string]string{"payload": base64.StdEncoding.EncodeToString([]byte(`{}`)), "sig": ""})
	wrongKey, err := Sign(release.RootSigner(otherPriv), req)
	if err != nil {
		t.Fatal(err)
	}
	cases := []struct {
		name   string
		wire   []byte
		id     string
		region string
		now    time.Time
	}{
		{"unsigned", unsigned, req.ID, "uk", testNow},
		{"wrong key", wrongKey, req.ID, "uk", testNow},
		{"moved to another id", good, "dbr_bbbbbbbbbbbbbbbbbbbbbbbbbb", "uk", testNow},
		{"moved to another region", good, req.ID, "ie", testNow},
		{"older than the window", good, req.ID, "uk", testNow.Add(61 * time.Second)},
		{"from the future", good, req.ID, "uk", testNow.Add(-61 * time.Second)},
	}
	for _, c := range cases {
		if _, err := Verify(pub, c.wire, c.id, c.region, c.now); !errors.Is(err, ErrEnvelope) && !errors.Is(err, release.ErrRootEnvelope) {
			t.Errorf("%s: Verify = %v, want a refusal", c.name, err)
		}
	}
}

// A scoped release key cannot sign: the console that holds only one cannot
// forward (spec §5.5).
func TestEnvelopeScopedKeyCannotSign(t *testing.T) {
	t.Parallel()
	rootPub, rootPriv := rootKeys(t)
	seed, grant, err := release.MintKeyGrant(rootPriv, "ci", []string{"canary"}, time.Hour)
	if err != nil {
		t.Fatal(err)
	}
	key, err := release.ParseSigningKey(seed, "scoped")
	if err != nil {
		t.Fatal(err)
	}
	sg, err := release.ScopedSigner(key, grant, rootPub)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := Sign(sg, testRequest(t)); !errors.Is(err, release.ErrRootEnvelope) {
		t.Fatalf("a scoped key signed: %v", err)
	}
}

func TestEnvelopeRefusesWhatItCannotCarry(t *testing.T) {
	t.Parallel()
	_, priv := rootKeys(t)
	for name, mut := range map[string]func(*Request){
		"bad id":         func(r *Request) { r.ID = "run_aaaaaaaaaaaaaaaaaaaaaaaaaa" },
		"fleet region":   func(r *Request) { r.Region = "fleet/acme" },
		"bad host":       func(r *Request) { r.Host = "../../etc" },
		"bad op":         func(r *Request) { r.Op = "shell" },
		"empty sql":      func(r *Request) { r.SQL = "" },
		"huge sql":       func(r *Request) { r.SQL = strings.Repeat("x", MaxSQLBytes+1) },
		"invalid utf-8":  func(r *Request) { r.SQL = "SELECT '\xff'" },
		"bad at":         func(r *Request) { r.At = "yesterday" },
		"bad reply key":  func(r *Request) { r.ReplyKey = "AAAA" },
		"bad issued_at":  func(r *Request) { r.IssuedAt = "now" },
	} {
		req := testRequest(t)
		mut(&req)
		if _, err := Sign(release.RootSigner(priv), req); !errors.Is(err, ErrEnvelope) {
			t.Errorf("%s: Sign = %v", name, err)
		}
	}
}

// Review Focus 1: the SQL a person typed is the SQL the box runs.
func TestEnvelopeSQLRoundTripsByteForByte(t *testing.T) {
	t.Parallel()
	pub, priv := rootKeys(t)
	req := testRequest(t)
	req.SQL = "SELECT '<a href=\"x\">&amp;</a>' || char(10) || '     é' WHERE 1 < 2 AND 3 > 2"
	wire, err := Sign(release.RootSigner(priv), req)
	if err != nil {
		t.Fatal(err)
	}
	got, err := Verify(pub, wire, req.ID, "uk", testNow)
	if err != nil || got.SQL != req.SQL {
		t.Fatalf("Verify = %q, %v", got.SQL, err)
	}
}

func TestQueueMatchesNeedsEveryPart(t *testing.T) {
	t.Parallel()
	req := testRequest(t)
	issued, _ := req.Issued()
	good, _ := ParseQueueKey(QueueKey("uk", issued, req.ID))
	if !QueueMatches(good, req) {
		t.Fatal("the console's own entry does not match")
	}
	for name, key := range map[string]string{
		"other region": QueueKey("ie", issued, req.ID),
		"other time":   QueueKey("uk", issued.Add(time.Second), req.ID),
		"other hour":   QueueHourPrefix("uk", issued.Add(time.Hour)) + strconv.FormatInt(issued.Unix(), 10) + "-" + req.ID,
		"other id":     QueueKey("uk", issued, "dbr_bbbbbbbbbbbbbbbbbbbbbbbbbb"),
	} {
		e, ok := ParseQueueKey(key)
		if ok && QueueMatches(e, req) {
			t.Errorf("%s matched", name)
		}
	}
}
```

- [ ] **Step 2: Run it to verify it fails**

Run: `go test ./internal/dbreads/ -run 'TestEnvelope|TestQueueMatches' -count=1`
Expected: FAIL, `Request`, `Sign` and `Verify` are undefined.

- [ ] **Step 3: Write `envelope.go`**

```go
package dbreads

import (
	"crypto/ed25519"
	"errors"
	"time"
	"unicode/utf8"

	"github.com/carlosframework/platform/internal/provision"
	"github.com/carlosframework/platform/internal/release"
)

// ErrEnvelope is a request this package will not sign or a box will not
// accept: well signed, perhaps, but not for this id, region or moment.
var ErrEnvelope = errors.New("dbreads: request refused")

// Request is db-reads/<id>/request.json's payload (spec §5.5). The box
// decodes it with release.VerifyRootEnvelope, which requires canonical JSON
// for this exact type, so the field order here is the wire's.
type Request struct {
	Purpose     string `json:"purpose"`
	V           int    `json:"v"`
	ID          string `json:"id"`
	Account     string `json:"account"`
	App         string `json:"app"`
	Host        string `json:"host"`
	Incarnation string `json:"incarnation"`
	Region      string `json:"region"`
	Op          string `json:"op"`
	SQL         string `json:"sql"`
	At          string `json:"at"`
	ReplyKey    string `json:"reply_key"`
	By          string `json:"by"`
	IssuedAt    string `json:"issued_at"`
}

// Issued is IssuedAt as a time.
func (r Request) Issued() (time.Time, error) { return time.Parse(time.RFC3339, r.IssuedAt) }

// AtTime is At as a time; zero for the newest copy.
func (r Request) AtTime() (time.Time, error) {
	if r.At == "" {
		return time.Time{}, nil
	}
	return time.Parse(time.RFC3339, r.At)
}

// ops are the operations this build serves. Plan 3 adds OpPull.
var ops = map[string]bool{OpQuery: true}

func (r Request) valid() bool {
	if r.Purpose != Purpose || r.V != 1 || !ValidID(r.ID) || !ValidRegion(r.Region) ||
		!release.ValidAccount(r.Account) || !release.ValidApp(r.App) || !provision.ValidHostShape(r.Host) ||
		r.Incarnation == "" || !ops[r.Op] || r.By == "" {
		return false
	}
	if r.Op == OpQuery && (r.SQL == "" || len(r.SQL) > MaxSQLBytes || !utf8.ValidString(r.SQL)) {
		return false
	}
	if _, err := r.AtTime(); err != nil {
		return false
	}
	if _, err := r.Issued(); err != nil {
		return false
	}
	_, err := ParseReplyKey(r.ReplyKey)
	return err == nil
}

// Sign is the console's half: it fills Purpose and V, refuses a request it
// could not carry intact (invalid UTF-8 would be rewritten by encoding/json,
// so the box would run SQL nobody typed), and signs with the root.
// release.SignRootEnvelope refuses a scoped key.
func Sign(sg release.Signer, req Request) ([]byte, error) {
	req.Purpose, req.V = Purpose, 1
	if !req.valid() {
		return nil, ErrEnvelope
	}
	return release.SignRootEnvelope(sg, req)
}

// Verify is the box's half (spec §5.5): the root signature over canonical
// JSON, this package's purpose, the id the object was read under, this box's
// own region, and an issue time no more than PickupWindow old and Skew in the
// future. The age bound is PickupWindow, not PickupWindow+Skew: InWindow
// already widened the listing by Skew, and the envelope is checked against
// this box's own clock.
func Verify(pub ed25519.PublicKey, wire []byte, id, region string, now time.Time) (Request, error) {
	var req Request
	if err := release.VerifyRootEnvelope(pub, wire, &req); err != nil {
		return Request{}, err
	}
	if !req.valid() || req.ID != id || req.Region != region {
		return Request{}, ErrEnvelope
	}
	issued, _ := req.Issued()
	if issued.Before(now.Add(-PickupWindow)) || issued.After(now.Add(Skew)) {
		return Request{}, ErrEnvelope
	}
	return req, nil
}

// QueueMatches is the queue entry check (spec §5.9): the entry's region,
// hour, time and id are all the envelope's, so a box's forged entry for a
// real request names nothing the request does not.
func QueueMatches(e QueueEntry, req Request) bool {
	issued, err := req.Issued()
	return err == nil && e.Region == req.Region && e.ID == req.ID && e.Issued.Equal(issued) &&
		e.Hour == issued.UTC().Format(hourLayout)
}
```

Note the spec's window: "issued_at is no more than 60 s old and no more than 60 s in the future". `Verify` enforces exactly that; the test's "older than the window" case uses 61 s.

- [ ] **Step 4: Run the tests**

Run: `go test ./internal/dbreads/ -run 'TestEnvelope|TestQueueMatches' -count=1`
Expected: PASS.

- [ ] **Step 5: Commit**

```bash
git add internal/dbreads/envelope.go internal/dbreads/envelope_test.go
git commit -m "dbreads: the root-signed request envelope and the queue entry check"
```

---

### Task 5: Sealing and the result

**Files:**
- Create: `internal/dbreads/seal.go`
- Create: `internal/dbreads/result.go`
- Create: `internal/dbreads/seal_test.go`

**Interfaces:**
- Produces: `NewReplyKey() (*ecdh.PrivateKey, error)`, `EncodeReplyKey(*ecdh.PublicKey) string`, `ParseReplyKey(string) (*ecdh.PublicKey, error)`; `SealChunk(pub *ecdh.PublicKey, id string, seq int64, stream string, last bool, plain []byte) ([]byte, error)`; `OpenChunk(priv *ecdh.PrivateKey, id string, seq int64, stream string, last bool, sealed []byte) ([]byte, error)`; `SealSummary(pub *ecdh.PublicKey, id string, s Summary) (string, error)`; `OpenSummary(priv *ecdh.PrivateKey, id, sealed string) (Summary, error)`; `SealOverhead`; `StreamRows`, `StreamLTX`; `ErrSeal`; `type Summary`, `type Result`, `type Picked`; the `State*` and `Code*` constants; `(Result) Valid() error`.

- [ ] **Step 1: Write the failing test**

Create `internal/dbreads/seal_test.go`:

```go
package dbreads

import (
	"bytes"
	"errors"
	"testing"
	"time"
)

const sealID = "dbr_aaaaaaaaaaaaaaaaaaaaaaaaaa"

func TestChunkSealRoundTripsAndBindsEverything(t *testing.T) {
	t.Parallel()
	priv, err := NewReplyKey()
	if err != nil {
		t.Fatal(err)
	}
	plain := bytes.Repeat([]byte("row\n"), 1000)
	sealed, err := SealChunk(priv.PublicKey(), sealID, 3, StreamRows, false, plain)
	if err != nil {
		t.Fatal(err)
	}
	if len(sealed)-len(plain) >= 100 || len(sealed)-len(plain) != SealOverhead {
		t.Fatalf("overhead %d, spec §5.7 says under 100 bytes", len(sealed)-len(plain))
	}
	got, err := OpenChunk(priv, sealID, 3, StreamRows, false, sealed)
	if err != nil || !bytes.Equal(got, plain) {
		t.Fatalf("OpenChunk = %v", err)
	}
	other, _ := NewReplyKey()
	for name, open := range map[string]func() ([]byte, error){
		"moved to another read": func() ([]byte, error) {
			return OpenChunk(priv, "dbr_bbbbbbbbbbbbbbbbbbbbbbbbbb", 3, StreamRows, false, sealed)
		},
		"reordered":          func() ([]byte, error) { return OpenChunk(priv, sealID, 4, StreamRows, false, sealed) },
		"relabelled as last": func() ([]byte, error) { return OpenChunk(priv, sealID, 3, StreamRows, true, sealed) },
		"another stream":     func() ([]byte, error) { return OpenChunk(priv, sealID, 3, StreamLTX, false, sealed) },
		"another key":        func() ([]byte, error) { return OpenChunk(other, sealID, 3, StreamRows, false, sealed) },
		"truncated":          func() ([]byte, error) { return OpenChunk(priv, sealID, 3, StreamRows, false, sealed[:len(sealed)-1]) },
	} {
		if _, err := open(); !errors.Is(err, ErrSeal) {
			t.Errorf("%s: %v", name, err)
		}
	}
}

func TestSummarySealRoundTrips(t *testing.T) {
	t.Parallel()
	priv, _ := NewReplyKey()
	want := Summary{TXID: 42, At: time.Date(2026, 10, 7, 14, 0, 0, 0, time.UTC), Bytes: 10, SHA256: "ab"}
	sealed, err := SealSummary(priv.PublicKey(), sealID, want)
	if err != nil {
		t.Fatal(err)
	}
	got, err := OpenSummary(priv, sealID, sealed)
	if err != nil || got.TXID != want.TXID || !got.At.Equal(want.At) || got.SHA256 != want.SHA256 {
		t.Fatalf("OpenSummary = %+v, %v", got, err)
	}
	if _, err := OpenSummary(priv, "dbr_bbbbbbbbbbbbbbbbbbbbbbbbbb", sealed); !errors.Is(err, ErrSeal) {
		t.Fatalf("a summary moved to another read opened: %v", err)
	}
}

func TestReplyKeyRefusesWhatIsNotAnUncompressedPoint(t *testing.T) {
	t.Parallel()
	for _, bad := range []string{"", "AAAA", "!!!!"} {
		if _, err := ParseReplyKey(bad); err == nil {
			t.Errorf("ParseReplyKey(%q) accepted", bad)
		}
	}
}

func TestResultValidKnowsTheVocabulary(t *testing.T) {
	t.Parallel()
	ok := []Result{
		{State: StateDone, LastSeq: 1},
		{State: StateDone, Code: CodeOutputCap, LastSeq: 3},
		{State: StateFailed, Code: CodeSQLError},
		{State: StateRefused, Code: CodeRecordChanged},
		{State: StateCancelled},
	}
	for _, r := range ok {
		if err := r.Valid(); err != nil {
			t.Errorf("%+v: %v", r, err)
		}
	}
	bad := []Result{
		{State: StateDone, LastSeq: 0},
		{State: "maybe"},
		{State: StateFailed, Code: "nope"},
		{State: StateDone, LastSeq: -1},
	}
	for _, r := range bad {
		if err := r.Valid(); err == nil {
			t.Errorf("%+v accepted", r)
		}
	}
}
```

- [ ] **Step 2: Run it to verify it fails**

Run: `go test ./internal/dbreads/ -run 'TestChunkSeal|TestSummarySeal|TestReplyKey|TestResultValid' -count=1`
Expected: FAIL, undefined names.

- [ ] **Step 3: Write `seal.go`**

```go
package dbreads

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/ecdh"
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"encoding/binary"
	"encoding/json"
	"errors"
	"io"
	"strconv"

	"golang.org/x/crypto/hkdf"
)

// Sealing is the appconfig v2 construction (spec §5.6): ECDH P-256 with a
// fresh sender key per seal, HKDF-SHA256 with this package's own info string,
// AES-256-GCM with bound associated data. The wire is raw bytes, never
// base64, in the bucket: "DBR1" || sender key (65) || nonce (12) || ciphertext.
const (
	sealPrefix   = "DBR1"
	sealEphLen   = 65
	sealNonceLen = 12
	// SealOverhead is what sealing adds: under 100 bytes (spec §5.7).
	SealOverhead = len(sealPrefix) + sealEphLen + sealNonceLen + 16
)

// The streams a chunk can carry, bound into its associated data.
const (
	StreamRows = "rows" // a query's output
	StreamLTX  = "ltx"  // a pull's planned files (plan 3)
)

// ErrSeal is any sealed object that does not open: wrong key, moved,
// reordered, relabelled, truncated or corrupt.
var ErrSeal = errors.New("dbreads: the sealed bytes do not open")

var errBadReplyKey = errors.New("dbreads: reply_key is not an uncompressed P-256 point")

// randReader is a var so a test can make sealing deterministic.
var randReader io.Reader = rand.Reader

// NewReplyKey is the CLI's ephemeral key pair for one read. The private half
// never leaves the CLI's memory.
func NewReplyKey() (*ecdh.PrivateKey, error) { return ecdh.P256().GenerateKey(randReader) }

func EncodeReplyKey(pub *ecdh.PublicKey) string { return base64.StdEncoding.EncodeToString(pub.Bytes()) }

func ParseReplyKey(s string) (*ecdh.PublicKey, error) {
	raw, err := base64.StdEncoding.Strict().DecodeString(s)
	if err != nil || len(raw) != sealEphLen {
		return nil, errBadReplyKey
	}
	pub, err := ecdh.P256().NewPublicKey(raw)
	if err != nil {
		return nil, errBadReplyKey
	}
	return pub, nil
}

// lengthPrefixed encodes fields so no choice of values makes two lists
// encode the same.
func lengthPrefixed(fields ...string) []byte {
	var out []byte
	for _, f := range fields {
		out = binary.BigEndian.AppendUint32(out, uint32(len(f)))
		out = append(out, f...)
	}
	return out
}

func chunkAAD(id string, seq int64, stream string, last bool) []byte {
	l := "0"
	if last {
		l = "1"
	}
	return lengthPrefixed(Purpose, "chunk", id, strconv.FormatInt(seq, 10), stream, l)
}

func summaryAAD(id string) []byte { return lengthPrefixed(Purpose, "summary", id) }

func gcmFor(shared []byte) (cipher.AEAD, error) {
	key := make([]byte, 32)
	if _, err := io.ReadFull(hkdf.New(sha256.New, shared, nil, []byte(Purpose)), key); err != nil {
		return nil, err
	}
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	return cipher.NewGCM(block)
}

func seal(pub *ecdh.PublicKey, aad, plain []byte) ([]byte, error) {
	eph, err := ecdh.P256().GenerateKey(randReader)
	if err != nil {
		return nil, err
	}
	nonce := make([]byte, sealNonceLen)
	if _, err := io.ReadFull(randReader, nonce); err != nil {
		return nil, err
	}
	shared, err := eph.ECDH(pub)
	if err != nil {
		return nil, err
	}
	gcm, err := gcmFor(shared)
	if err != nil {
		return nil, err
	}
	out := make([]byte, 0, SealOverhead+len(plain))
	out = append(out, sealPrefix...)
	out = append(out, eph.PublicKey().Bytes()...)
	out = append(out, nonce...)
	return gcm.Seal(out, nonce, plain, aad), nil
}

func open(priv *ecdh.PrivateKey, aad, sealed []byte) ([]byte, error) {
	if len(sealed) < SealOverhead || string(sealed[:len(sealPrefix)]) != sealPrefix {
		return nil, ErrSeal
	}
	body := sealed[len(sealPrefix):]
	ephPub, err := ecdh.P256().NewPublicKey(body[:sealEphLen])
	if err != nil {
		return nil, ErrSeal
	}
	shared, err := priv.ECDH(ephPub)
	if err != nil {
		return nil, ErrSeal
	}
	gcm, err := gcmFor(shared)
	if err != nil {
		return nil, ErrSeal
	}
	plain, err := gcm.Open(nil, body[sealEphLen:sealEphLen+sealNonceLen], body[sealEphLen+sealNonceLen:], aad)
	if err != nil {
		return nil, ErrSeal
	}
	return plain, nil
}

// SealChunk seals one chunk of a read's output: bound to the read, its
// sequence number, its stream and whether it is the last.
func SealChunk(pub *ecdh.PublicKey, id string, seq int64, stream string, last bool, plain []byte) ([]byte, error) {
	return seal(pub, chunkAAD(id, seq, stream, last), plain)
}

func OpenChunk(priv *ecdh.PrivateKey, id string, seq int64, stream string, last bool, sealed []byte) ([]byte, error) {
	return open(priv, chunkAAD(id, seq, stream, last), sealed)
}

// SealSummary seals the result's summary (base64, it rides in result.json).
func SealSummary(pub *ecdh.PublicKey, id string, s Summary) (string, error) {
	raw, err := json.Marshal(s)
	if err != nil {
		return "", err
	}
	sealed, err := seal(pub, summaryAAD(id), raw)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(sealed), nil
}

func OpenSummary(priv *ecdh.PrivateKey, id, sealed string) (Summary, error) {
	raw, err := base64.StdEncoding.Strict().DecodeString(sealed)
	if err != nil {
		return Summary{}, ErrSeal
	}
	plain, err := open(priv, summaryAAD(id), raw)
	if err != nil {
		return Summary{}, err
	}
	var s Summary
	if err := json.Unmarshal(plain, &s); err != nil {
		return Summary{}, ErrSeal
	}
	return s, nil
}
```

- [ ] **Step 4: Write `result.go`**

```go
package dbreads

import (
	"fmt"
	"time"

	"github.com/carlosframework/platform/internal/dbdoor"
)

// How a read ended (result.json's state, spec §5.6).
const (
	StateDone      = "done"
	StateFailed    = "failed"
	StateRefused   = "refused"
	StateCancelled = "cancelled"
)

// The fixed code vocabulary the console may read.
const (
	CodeNothingReplicated = "nothing-replicated"
	CodeHistoryGone       = "history-gone"
	CodeCheckFailed       = "check-failed"
	CodeChangedTwice      = "changed-twice"
	CodeTooLarge          = "too-large"
	CodeNoRoom            = "no-room"
	CodeSQLError          = "sql-error"
	CodeTimeout           = "timeout"
	CodeOutputCap         = "output-cap"
	CodeRecordChanged     = "record-changed"
	CodeMoving            = "moving"
	CodeInterrupted       = "interrupted"
)

var codesByState = map[string]map[string]bool{
	StateDone:      {"": true, CodeOutputCap: true},
	StateFailed:    {CodeNothingReplicated: true, CodeHistoryGone: true, CodeCheckFailed: true, CodeChangedTwice: true, CodeTooLarge: true, CodeNoRoom: true, CodeSQLError: true, CodeTimeout: true, CodeInterrupted: true},
	StateRefused:   {CodeRecordChanged: true, CodeMoving: true},
	StateCancelled: {"": true},
}

// Result is db-reads/<id>/result.json, written only after every chunk is
// confirmed. LastSeq is the last chunk's sequence number; a done read has at
// least one chunk, the last of which is sealed as last.
type Result struct {
	State   string    `json:"state"`
	Code    string    `json:"code"`
	Box     string    `json:"box"`
	LastSeq int64     `json:"last_seq"`
	Started time.Time `json:"started"`
	Ended   time.Time `json:"ended"`
	Sealed  string    `json:"sealed"`
}

// Valid is the shape the console checks before it relays a result.
func (r Result) Valid() error {
	codes, ok := codesByState[r.State]
	switch {
	case !ok:
		return fmt.Errorf("dbreads: unknown state %q", r.State)
	case !codes[r.Code]:
		return fmt.Errorf("dbreads: code %q is not one of state %s's", r.Code, r.State)
	case r.LastSeq < 0, r.State == StateDone && r.LastSeq < 1:
		return fmt.Errorf("dbreads: last_seq %d for state %s", r.LastSeq, r.State)
	}
	return nil
}

// Picked is db-reads/<id>/picked: the owner (J3).
type Picked struct {
	Box      string    `json:"box"`
	Boot     string    `json:"boot"`
	Nonce    string    `json:"nonce"`
	Deadline time.Time `json:"deadline"`
}

// Summary is the result's sealed half, which only the CLI can open (§5.6).
type Summary struct {
	TXID     uint64    `json:"txid"`     // the copy's newest transaction
	At       time.Time `json:"at"`       // that transaction's time, from its LTX header
	Oldest   time.Time `json:"oldest"`   // history-gone: the earliest --at that works
	Restored int64     `json:"restored"` // too-large: the restored size
	Cap      int64     `json:"cap"`      // too-large: the box's cap
	Error    string    `json:"error"`    // sql-error: SQLite's text; check-failed: the detail
	Bytes    int64     `json:"bytes"`    // the output's plaintext byte count
	SHA256   string    `json:"sha256"`   // the output's plaintext SHA-256, hex
	// Files is a pull's planned files in order (plan 3); empty for a query.
	Files []dbdoor.LTXFile `json:"files,omitempty"`
}
```

- [ ] **Step 5: Run the tests**

Run: `go test ./internal/dbreads/ -count=1`
Expected: PASS, including Task 4's tests.

- [ ] **Step 6: Commit**

```bash
git add internal/dbreads/seal.go internal/dbreads/result.go internal/dbreads/seal_test.go
git commit -m "dbreads: reply keys, bound chunk and summary sealing, the result"
```

---

### Task 6: `dbdoor` planning over any replica reader, listed as the door lists

**Files:**
- Create: `internal/dbdoor/plan_from.go`
- Create: `internal/dbdoor/plan_from_test.go`
- Modify: `internal/dbdoor/plan.go` (shared tail; two new `RestorePlan` fields)
- Modify: `internal/console/apidb.go:316-342` (`listReplicaLevel` delegates)

**Interfaces:**
- Consumes: `litestream.CalcRestorePlan`, `fileIterator`, `restoreOnce`, `removeCopy`, `checkDB`, `errReadOnly`, `EarliestAsOf`, `BeforeHistoryError` (all existing in `dbdoor`).
- Produces: `dbdoor.ReplicaReader` (interface: `LTXFiles`, `OpenLTXFile`); `dbdoor.ListLevel(ctx context.Context, rd ReplicaReader, level int) (ListResponse, error)`; `dbdoor.PlanFrom(ctx context.Context, rd ReplicaReader, at time.Time) (RestorePlan, error)`; `dbdoor.RestoreLocal(ctx context.Context, c litestream.ReplicaClient, out string, target uint64) error`; `RestorePlan.Planned []LTXFile` and `RestorePlan.At time.Time`.

- [ ] **Step 1: Write the failing test**

Create `internal/dbdoor/plan_from_test.go`:

```go
package dbdoor

import (
	"context"
	"errors"
	"io"
	"os"
	"path/filepath"
	"testing"
	"time"

	"github.com/benbjohnson/litestream"
	lsfile "github.com/benbjohnson/litestream/file"
	"github.com/superfly/ltx"

	"github.com/carlosframework/platform/internal/dbdoor/dbdoortest"
)

// metaSpy records every useMetadata the listing passes down: the box must
// list LastModified as CreatedAt, exactly as the console's door does
// (listReplicaLevel), never S3 metadata timestamps (spec §6, T6).
type metaSpy struct {
	ReplicaReader
	sawMetadata bool
}

func (m *metaSpy) LTXFiles(ctx context.Context, level int, seek ltx.TXID, useMetadata bool) (ltx.FileIterator, error) {
	if useMetadata {
		m.sawMetadata = true
	}
	return m.ReplicaReader.LTXFiles(ctx, level, seek, useMetadata)
}

func TestListLevelIsTheDoorsListing(t *testing.T) {
	t.Parallel()
	dir := t.TempDir()
	dbdoortest.Replicate(t, dir, 3)
	spy := &metaSpy{ReplicaReader: lsfile.NewReplicaClient(dir)}
	got, err := ListLevel(context.Background(), spy, 0)
	if err != nil {
		t.Fatal(err)
	}
	want := collect(t, NewClient(newTestDoor(t, dir).do), 0, 0)
	if len(got.Files) != len(want) || spy.sawMetadata {
		t.Fatalf("ListLevel = %d files (metadata %v), the door lists %d", len(got.Files), spy.sawMetadata, len(want))
	}
	for i := range want {
		f := got.Files[i]
		if f.MinTXID != uint64(want[i].MinTXID) || f.MaxTXID != uint64(want[i].MaxTXID) || f.Size != want[i].Size || !f.CreatedAt.Equal(want[i].CreatedAt) {
			t.Fatalf("file %d: %+v, the door lists %+v", i, f, want[i])
		}
	}
	empty, err := ListLevel(context.Background(), spy, 5)
	if err != nil || empty.Files == nil || len(empty.Files) != 0 {
		t.Fatalf("an empty level = %+v, %v; want an empty list", empty, err)
	}
}

// PlanFrom plans what RestoreAsOf through the door restores: the same
// transaction, the same time, the same size, for the newest copy and as of
// a time.
func TestPlanFromMatchesTheDoorsRestore(t *testing.T) {
	dir := t.TempDir()
	src := dbdoortest.Replicate(t, dir, 2)
	at := pause()
	addBatch(t, src, dir, 2)
	for _, when := range []time.Time{{}, at} {
		plan, err := PlanFrom(context.Background(), lsfile.NewReplicaClient(dir), when)
		if err != nil {
			t.Fatal(err)
		}
		got, err := RestoreAsOf(context.Background(), NewClient(newTestDoor(t, dir).do), t.TempDir(), when)
		if err != nil {
			t.Fatal(err)
		}
		st, err := os.Stat(got.Path)
		if err != nil {
			t.Fatal(err)
		}
		os.RemoveAll(got.Dir)
		if plan.TXID != got.TXID || !plan.At.Equal(got.At) || plan.RestoredBytes != st.Size() || len(plan.Planned) != plan.Files || plan.Files == 0 {
			t.Fatalf("as of %v: plan %+v; the door restored txid %d at %v, %d bytes", when, plan, got.TXID, got.At, st.Size())
		}
	}
}

func TestPlanFromBeforeHistoryNamesTheOldestPoint(t *testing.T) {
	t.Parallel()
	before := time.Now().Add(-time.Hour)
	dir := t.TempDir()
	dbdoortest.Replicate(t, dir, 2)
	_, err := PlanFrom(context.Background(), lsfile.NewReplicaClient(dir), before)
	var bh *BeforeHistoryError
	if !errors.As(err, &bh) {
		t.Fatalf("PlanFrom before history = %v", err)
	}
	_, derr := RestoreAsOf(context.Background(), NewClient(newTestDoor(t, dir).do), t.TempDir(), before)
	var dbh *BeforeHistoryError
	if !errors.As(derr, &dbh) || !dbh.Oldest.Equal(bh.Oldest) {
		t.Fatalf("the door says %v, the plan says %v", derr, bh.Oldest)
	}
}

func TestPlanFromAnEmptyReplica(t *testing.T) {
	t.Parallel()
	_, err := PlanFrom(context.Background(), lsfile.NewReplicaClient(t.TempDir()), time.Time{})
	if !errors.Is(err, ErrNothingReplicated) {
		t.Fatalf("PlanFrom on nothing = %v", err)
	}
}

// RestoreLocal restores exactly the planned files, copied into a fresh file
// replica the way the worker writes them, to the plan's transaction.
func TestRestoreLocalRestoresThePlan(t *testing.T) {
	t.Parallel()
	dir := t.TempDir()
	dbdoortest.Replicate(t, dir, 4)
	src := lsfile.NewReplicaClient(dir)
	plan, err := PlanFrom(context.Background(), src, time.Time{})
	if err != nil {
		t.Fatal(err)
	}
	root := t.TempDir()
	for _, f := range plan.Planned {
		rc, err := src.OpenLTXFile(context.Background(), f.Level, ltx.TXID(f.MinTXID), ltx.TXID(f.MaxTXID), 0, 0)
		if err != nil {
			t.Fatal(err)
		}
		path := litestream.LTXFilePath(root, f.Level, ltx.TXID(f.MinTXID), ltx.TXID(f.MaxTXID))
		if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
			t.Fatal(err)
		}
		out, err := os.Create(path)
		if err != nil {
			t.Fatal(err)
		}
		if _, err := io.Copy(out, rc); err != nil {
			t.Fatal(err)
		}
		rc.Close()
		out.Close()
	}
	db := filepath.Join(t.TempDir(), "copy.db")
	if err := RestoreLocal(context.Background(), lsfile.NewReplicaClient(root), db, plan.TXID); err != nil {
		t.Fatal(err)
	}
	if rows := countRows(t, db); rows != 4*dbdoortest.Rows {
		t.Fatalf("restored %d rows", rows)
	}
	st, _ := os.Stat(db)
	if st.Size() != plan.RestoredBytes {
		t.Fatalf("restored %d bytes, planned %d", st.Size(), plan.RestoredBytes)
	}
}
```

- [ ] **Step 2: Run it to verify it fails**

Run: `go test ./internal/dbdoor/ -run 'TestListLevel|TestPlanFrom|TestRestoreLocal' -count=1`
Expected: FAIL, undefined `ListLevel`, `PlanFrom`, `RestoreLocal`, `ReplicaReader`.

- [ ] **Step 3: Refactor `plan.go` around a shared tail**

In `internal/dbdoor/plan.go`, add the two fields to `RestorePlan`:

```go
	// Planned is the plan's files in restore order (box side: what the
	// worker is sent, spec §8.2).
	Planned []LTXFile
	// At is the last planned file's header time: the time of the copy's
	// newest transaction, as RestoreAsOf's Restored.At reports it.
	At time.Time
```

and replace everything in `PlanRestore` after the `switch` with a call to a new shared tail, so both planners read and check the last file's header the same way:

```go
	return finishPlan(ctx, c, infos, target)
}

// finishPlan sums the plan, records its files, and reads and bounds the
// last planned file's header: the size check's one decode (spec §8.1).
func finishPlan(ctx context.Context, c litestream.ReplicaClient, infos []*ltx.FileInfo, target uint64) (RestorePlan, error) {
	p := RestorePlan{Target: target, Files: len(infos)}
	for _, f := range infos {
		p.LTXBytes += f.Size
		p.Planned = append(p.Planned, LTXFile{Level: f.Level, MinTXID: uint64(f.MinTXID), MaxTXID: uint64(f.MaxTXID), Size: f.Size, CreatedAt: f.CreatedAt})
	}
	last := infos[len(infos)-1]
	p.TXID = uint64(last.MaxTXID)
	rc, err := c.OpenLTXFile(ctx, last.Level, last.MinTXID, last.MaxTXID, 0, ltx.HeaderSize)
	if err != nil {
		return RestorePlan{}, fmt.Errorf("dbdoor: read the last planned file's header: %w", err)
	}
	defer rc.Close()
	buf := make([]byte, ltx.HeaderSize)
	if _, err := io.ReadFull(rc, buf); err != nil {
		return RestorePlan{}, fmt.Errorf("dbdoor: read the last planned file's header: %w", err)
	}
	var h ltx.Header
	if err := h.UnmarshalBinary(buf); err != nil {
		return RestorePlan{}, fmt.Errorf("dbdoor: the last planned file's header: %w", err)
	}
	if !ltx.IsValidPageSize(h.PageSize) || h.Commit == 0 || h.MinTXID != last.MinTXID || h.MaxTXID != last.MaxTXID {
		return RestorePlan{}, fmt.Errorf("dbdoor: the last planned file's header does not describe it (level %d %s: page size %d, commit %d, txids %s)",
			last.Level, Span(uint64(last.MinTXID), uint64(last.MaxTXID)), h.PageSize, h.Commit, Span(uint64(h.MinTXID), uint64(h.MaxTXID)))
	}
	p.RestoredBytes = int64(h.Commit) * int64(h.PageSize)
	p.At = time.UnixMilli(h.Timestamp).UTC()
	return p, nil
}
```

Keep the comment block above the bounds check that explains why the header is untrusted. `PlanRestore`'s existing tests must still pass unchanged.

- [ ] **Step 4: Write `plan_from.go`**

```go
package dbdoor

import (
	"context"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"sort"
	"sync"
	"time"

	"github.com/benbjohnson/litestream"
	"github.com/superfly/ltx"
)

// ReplicaReader is the read half of a litestream replica client: the two
// methods a door or a planner may hold. A *lss3.ReplicaClient from
// lease.ReadReplicaClient is one; so is a file replica client.
type ReplicaReader interface {
	LTXFiles(ctx context.Context, level int, seek ltx.TXID, useMetadata bool) (ltx.FileIterator, error)
	OpenLTXFile(ctx context.Context, level int, minTXID, maxTXID ltx.TXID, offset, size int64) (io.ReadCloser, error)
}

// ListLevel lists one level of rd in the door's wire shape, ordered by
// MinTXID, with an empty level as an empty list, and with S3's LastModified
// as CreatedAt (useMetadata false). The console's door and the box's planner
// both list through it, so a forwarded --at stops at the transaction an
// in-region one does (spec §6, T6).
func ListLevel(ctx context.Context, rd ReplicaReader, level int) (ListResponse, error) {
	itr, err := rd.LTXFiles(ctx, level, 0, false)
	if err != nil {
		return ListResponse{}, err
	}
	out := ListResponse{Files: []LTXFile{}}
	for itr.Next() {
		f := itr.Item()
		out.Files = append(out.Files, LTXFile{
			Level: level, MinTXID: uint64(f.MinTXID), MaxTXID: uint64(f.MaxTXID),
			Size: f.Size, CreatedAt: f.CreatedAt,
		})
	}
	err = itr.Err()
	if cerr := itr.Close(); err == nil {
		err = cerr
	}
	if err != nil {
		return ListResponse{}, err
	}
	sort.Slice(out.Files, func(i, j int) bool { return out.Files[i].MinTXID < out.Files[j].MinTXID })
	return out, nil
}

// listing is a read-only litestream.ReplicaClient over rd that lists through
// ListLevel. For an as-of plan it also does what the CLI's recorder does
// over the door's listings: refuse a listing with no times (ErrNoTimes) and
// remember the earliest file a restore could start from.
type listing struct {
	rd     ReplicaReader
	asOf   bool
	mu     sync.Mutex
	oldest time.Time
}

func (l *listing) Type() string               { return "carlos-db-listing" }
func (l *listing) Init(context.Context) error { return nil }
func (l *listing) SetLogger(*slog.Logger)     {}

func (l *listing) LTXFiles(ctx context.Context, level int, seek ltx.TXID, _ bool) (ltx.FileIterator, error) {
	out, err := ListLevel(ctx, l.rd, level)
	if err != nil {
		return nil, err
	}
	if l.asOf {
		l.mu.Lock()
		defer l.mu.Unlock()
		for _, f := range out.Files {
			if f.CreatedAt.IsZero() {
				return nil, ErrNoTimes
			}
			if level == litestream.SnapshotLevel || f.MinTXID == 1 {
				if l.oldest.IsZero() || f.CreatedAt.Before(l.oldest) {
					l.oldest = f.CreatedAt
				}
			}
		}
	}
	return fileIterator(out.Files, level, seek), nil
}

func (l *listing) OpenLTXFile(ctx context.Context, level int, minTXID, maxTXID ltx.TXID, offset, size int64) (io.ReadCloser, error) {
	return l.rd.OpenLTXFile(ctx, level, minTXID, maxTXID, offset, size)
}

func (l *listing) WriteLTXFile(context.Context, int, ltx.TXID, ltx.TXID, io.Reader) (*ltx.FileInfo, error) {
	return nil, errReadOnly
}

func (l *listing) DeleteLTXFiles(context.Context, []*ltx.FileInfo) error { return errReadOnly }

func (l *listing) DeleteAll(context.Context) error { return errReadOnly }

var _ litestream.ReplicaClient = (*listing)(nil)

// PlanFrom plans the restore RestoreAsOf would make through the door, from
// rd directly: the newest copy when at is zero, else the copy holding every
// file listed before at rounded down to its second. Its errors are
// RestoreAsOf's: ErrNothingReplicated, a *BeforeHistoryError naming the
// oldest point kept, ErrNoTimes.
func PlanFrom(ctx context.Context, rd ReplicaReader, at time.Time) (RestorePlan, error) {
	l := &listing{rd: rd, asOf: !at.IsZero()}
	var ts time.Time
	if !at.IsZero() {
		if at.Truncate(time.Second).Before(EarliestAsOf) {
			at = EarliestAsOf
		}
		ts = at.Truncate(time.Second)
	}
	infos, err := litestream.CalcRestorePlan(ctx, l, 0, ts, slog.Default())
	switch {
	case errors.Is(err, ErrNoTimes):
		return RestorePlan{}, ErrNoTimes
	case errors.Is(err, litestream.ErrTxNotAvailable) || errors.Is(err, litestream.ErrNoSnapshots):
		l.mu.Lock()
		oldest := l.oldest
		l.mu.Unlock()
		if !ts.IsZero() && !oldest.IsZero() {
			if !oldest.Before(ts) {
				return RestorePlan{}, &BeforeHistoryError{Oldest: oldest.Truncate(time.Second).Add(time.Second)}
			}
			return RestorePlan{}, err
		}
		return RestorePlan{}, ErrNothingReplicated
	case err != nil:
		return RestorePlan{}, err
	case len(infos) == 0:
		return RestorePlan{}, ErrNothingReplicated
	}
	return finishPlan(ctx, l, infos, 0)
}

// RestoreLocal restores the replica c holds, a litestream file replica in a
// private directory (the db-read worker's, or the CLI's for a forwarded
// pull), exactly to target, at out, and proves it with lease.CheckDBContext.
// On failure nothing is left at out.
func RestoreLocal(ctx context.Context, c litestream.ReplicaClient, out string, target uint64) error {
	if err := restoreOnce(ctx, c, out, target, time.Time{}); err != nil {
		removeCopy(out)
		if cerr := ctx.Err(); cerr != nil {
			return cerr
		}
		return err
	}
	if err := checkDB(ctx, out); err != nil {
		removeCopy(out)
		if cerr := ctx.Err(); cerr != nil {
			return cerr
		}
		return fmt.Errorf("%w: %v", ErrCheckFailed, err)
	}
	if err := ctx.Err(); err != nil {
		removeCopy(out)
		return err
	}
	return nil
}
```

In `internal/console/apidb.go`, replace `listReplicaLevel`'s body with `return dbdoor.ListLevel(ctx, rd, level)` and keep its doc comment, adding one line: "The body moved to dbdoor.ListLevel so the box's planner lists through it too (db region forward spec §6)." Drop the now unused `sort` import if nothing else in the file uses it.

- [ ] **Step 5: Run the tests**

Run: `go test ./internal/dbdoor/ -count=1 && go test ./internal/console/ -run 'TestAPIDB|TestDBDoor|TestSeed' -count=1`
Expected: PASS. The `dbdoor` package is small enough to run whole; for the console, only the db door's and the seed door's tests (list them with `grep -ln 'listReplicaLevel\|handleAPIDBList' internal/console/*_test.go` and `-run` their names if the pattern above matches none).

- [ ] **Step 6: Commit**

```bash
git add internal/dbdoor internal/console/apidb.go
git commit -m "dbdoor: ListLevel, PlanFrom and RestoreLocal; the console door lists through ListLevel"
```

---

### Task 7: The worker protocol and `ServeWorker`

**Files:**
- Create: `internal/dbreads/protocol.go`
- Create: `internal/dbreads/worker.go`
- Create: `internal/dbreads/worker_test.go`

**Interfaces:**
- Consumes: `dbdoor.LTXFile`, `dbdoor.RestoreLocal`, `dbdoor.ErrCheckFailed`, `dbquery.RunContext`, `dbquery.Options`, `litestream.LTXFilePath`, `lsfile.NewReplicaClient`.
- Produces: `ProtocolVersion`; frame bytes `frameHello`, `frameHelloReply`, `frameHeader`, `frameFile`, `frameReady`, `frameRun`, `frameStop`, `frameOutput`, `frameEnd`; `writeFrame(w io.Writer, typ byte, p []byte) error`, `writeJSONFrame(w io.Writer, typ byte, v any) error`, `readFrame(r io.Reader) (byte, []byte, error)`; message types `hello`, `HelloReply`, `planHeader`, `readyMsg`, `runMsg`, `endMsg`; `type WorkerOptions struct { Scratch string; QueryTimeout, Grace time.Duration; Exit func(int); Self func() HelloReply; Restore func(ctx context.Context, c litestream.ReplicaClient, out string, target uint64) error }`; `ServeWorker(conn io.ReadWriter, opt WorkerOptions) error`; `SelfView() HelloReply`.

- [ ] **Step 1: Write the failing test**

Create `internal/dbreads/worker_test.go`. These tests drive the real worker code over `net.Pipe`: not acceptance (Task 15 is); they pin the protocol.

```go
package dbreads

import (
	"bytes"
	"context"
	"encoding/json"
	"io"
	"net"
	"strings"
	"sync/atomic"
	"testing"
	"time"

	"github.com/benbjohnson/litestream"
	lsfile "github.com/benbjohnson/litestream/file"
	"github.com/superfly/ltx"

	"github.com/carlosframework/platform/internal/dbdoor"
	"github.com/carlosframework/platform/internal/dbdoor/dbdoortest"
	"github.com/carlosframework/platform/internal/dbquery"
)

// workerPipe starts ServeWorker on one end of a pipe and returns the other.
// Not acceptance: the units are Task 15's.
func workerPipe(t *testing.T, opt WorkerOptions) (net.Conn, <-chan error) {
	t.Helper()
	agent, worker := net.Pipe()
	if opt.Scratch == "" {
		opt.Scratch = t.TempDir()
	}
	if opt.Exit == nil {
		opt.Exit = func(int) { t.Error("the worker asked to exit the process") }
	}
	done := make(chan error, 1)
	go func() {
		err := ServeWorker(worker, opt)
		worker.Close()
		done <- err
	}()
	t.Cleanup(func() { agent.Close() })
	return agent, done
}

// sendPlan sends a header and the planned files of dir's replica.
func sendPlan(t *testing.T, conn net.Conn, dir string) dbdoor.RestorePlan {
	t.Helper()
	rd := lsfile.NewReplicaClient(dir)
	plan, err := dbdoor.PlanFrom(context.Background(), rd, time.Time{})
	if err != nil {
		t.Fatal(err)
	}
	if err := writeJSONFrame(conn, frameHeader, planHeader{V: ProtocolVersion, Op: OpQuery, Files: plan.Planned, Target: plan.TXID, MaxRestored: DefaultMaxRestored}); err != nil {
		t.Fatal(err)
	}
	for _, f := range plan.Planned {
		rc, err := rd.OpenLTXFile(context.Background(), f.Level, ltx.TXID(f.MinTXID), ltx.TXID(f.MaxTXID), 0, 0)
		if err != nil {
			t.Fatal(err)
		}
		body, _ := io.ReadAll(rc)
		rc.Close()
		if err := writeFrame(conn, frameFile, body); err != nil {
			t.Fatal(err)
		}
	}
	return plan
}

func readTyped(t *testing.T, conn net.Conn, want byte, v any) {
	t.Helper()
	typ, p, err := readFrame(conn)
	if err != nil || typ != want {
		t.Fatalf("frame %q (%s), want %q: %v", typ, p, want, err)
	}
	if v != nil {
		if err := json.Unmarshal(p, v); err != nil {
			t.Fatal(err)
		}
	}
}

func TestWorkerAnswersHelloWithItsSelfView(t *testing.T) {
	t.Parallel()
	conn, done := workerPipe(t, WorkerOptions{Self: func() HelloReply {
		return HelloReply{V: ProtocolVersion, Interfaces: []string{"lo"}}
	}})
	if err := writeJSONFrame(conn, frameHello, hello{V: ProtocolVersion}); err != nil {
		t.Fatal(err)
	}
	var h HelloReply
	readTyped(t, conn, frameHelloReply, &h)
	if h.V != ProtocolVersion || len(h.Interfaces) != 1 {
		t.Fatalf("hello = %+v", h)
	}
	if err := <-done; err != nil {
		t.Fatal(err)
	}
}

// The default self-view reads /proc/self/net/dev, which needs no socket
// (plan review finding 1). Mutation: SelfView back on net.Interfaces makes
// TestRootDBReadReadiness's baseline red inside the installed unit.
func TestParseNetDev(t *testing.T) {
	t.Parallel()
	only := "Inter-|   Receive\n face |bytes\n    lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
	if got := parseNetDev(only); len(got) != 1 || got[0] != "lo" {
		t.Fatalf("%q", got)
	}
	two := only + "  eth0: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16\n"
	if got := parseNetDev(two); len(got) != 2 || got[1] != "eth0" {
		t.Fatalf("%q", got)
	}
	if got := SelfView(); len(got.Errors) != 0 && !strings.Contains(strings.Join(got.Errors, " "), "/proc") {
		t.Fatalf("SelfView on this machine: %+v", got)
	}
}

func TestWorkerRestoresThenRunsOnlyWhenTold(t *testing.T) {
	t.Parallel()
	dir := t.TempDir()
	dbdoortest.Replicate(t, dir, 3)
	conn, done := workerPipe(t, WorkerOptions{})
	plan := sendPlan(t, conn, dir)
	var ready readyMsg
	readTyped(t, conn, frameReady, &ready)
	if ready.TXID != plan.TXID {
		t.Fatalf("ready at %d, planned %d", ready.TXID, plan.TXID)
	}
	if err := writeJSONFrame(conn, frameRun, runMsg{SQL: "SELECT count(*) AS n FROM t"}); err != nil {
		t.Fatal(err)
	}
	var out bytes.Buffer
	for {
		typ, p, err := readFrame(conn)
		if err != nil {
			t.Fatal(err)
		}
		if typ == frameOutput {
			out.Write(p)
			continue
		}
		var end endMsg
		if typ != frameEnd || json.Unmarshal(p, &end) != nil || end.Code != "" {
			t.Fatalf("end %q %s", typ, p)
		}
		break
	}
	if out.String() != "n\n30\n" {
		t.Fatalf("output %q", out.String())
	}
	if err := <-done; err != nil {
		t.Fatal(err)
	}
}

func TestWorkerStopRunsNothing(t *testing.T) {
	t.Parallel()
	dir := t.TempDir()
	dbdoortest.Replicate(t, dir, 1)
	conn, done := workerPipe(t, WorkerOptions{})
	sendPlan(t, conn, dir)
	readTyped(t, conn, frameReady, nil)
	if err := writeFrame(conn, frameStop, nil); err != nil {
		t.Fatal(err)
	}
	if err := <-done; err != nil {
		t.Fatal(err)
	}
}

// The worker refuses a file larger than its header said (spec §8.3).
func TestWorkerRefusesAFileLargerThanItsHeader(t *testing.T) {
	t.Parallel()
	conn, done := workerPipe(t, WorkerOptions{})
	files := []dbdoor.LTXFile{{Level: 0, MinTXID: 1, MaxTXID: 1, Size: 4}}
	if err := writeJSONFrame(conn, frameHeader, planHeader{V: ProtocolVersion, Op: OpQuery, Files: files, Target: 1, MaxRestored: DefaultMaxRestored}); err != nil {
		t.Fatal(err)
	}
	go writeFrame(conn, frameFile, []byte("12345"))
	var end endMsg
	readTyped(t, conn, frameEnd, &end)
	if end.Code != CodeCheckFailed {
		t.Fatalf("end = %+v", end)
	}
	<-done
}

func TestWorkerSQLErrorIsSQLitesText(t *testing.T) {
	t.Parallel()
	dir := t.TempDir()
	dbdoortest.Replicate(t, dir, 1)
	conn, done := workerPipe(t, WorkerOptions{})
	sendPlan(t, conn, dir)
	readTyped(t, conn, frameReady, nil)
	writeJSONFrame(conn, frameRun, runMsg{SQL: "SELECT * FROM nope"})
	var end endMsg
	readTyped(t, conn, frameEnd, &end)
	if end.Code != CodeSQLError || end.Error == "" {
		t.Fatalf("end = %+v", end)
	}
	if err := dbquery.CheckSQL("SELECT * FROM nope"); err != nil {
		t.Fatal(err)
	}
	<-done
}

func TestWorkerQueryTimeout(t *testing.T) {
	t.Parallel()
	dir := t.TempDir()
	dbdoortest.Replicate(t, dir, 1)
	conn, done := workerPipe(t, WorkerOptions{QueryTimeout: 50 * time.Millisecond})
	sendPlan(t, conn, dir)
	readTyped(t, conn, frameReady, nil)
	writeJSONFrame(conn, frameRun, runMsg{SQL: "WITH RECURSIVE c(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM c) SELECT count(*) FROM c"})
	for {
		typ, p, err := readFrame(conn)
		if err != nil {
			t.Fatal(err)
		}
		if typ == frameEnd {
			var end endMsg
			json.Unmarshal(p, &end)
			if end.Code != CodeTimeout {
				t.Fatalf("end = %+v", end)
			}
			break
		}
	}
	<-done
}

// The worker stops when its agent goes (spec §8.3, codex 8): EOF cancels the
// context, and a step that ignores the context is ended by the exit after
// the grace.
func TestWorkerExitsWhenTheAgentGoesMidRestore(t *testing.T) {
	t.Parallel()
	dir := t.TempDir()
	dbdoortest.Replicate(t, dir, 1)
	var exited atomic.Int32
	hang := make(chan struct{})
	t.Cleanup(func() { close(hang) })
	conn, _ := workerPipe(t, WorkerOptions{
		Grace: 50 * time.Millisecond,
		Exit:  func(code int) { exited.Store(int32(code)) },
		Restore: func(context.Context, litestream.ReplicaClient, string, uint64) error {
			<-hang // a compaction that ignores its context
			return nil
		},
	})
	sendPlan(t, conn, dir)
	conn.Close()
	deadline := time.Now().Add(5 * time.Second)
	for exited.Load() == 0 && time.Now().Before(deadline) {
		time.Sleep(10 * time.Millisecond)
	}
	if exited.Load() == 0 {
		t.Fatal("the worker outlived its agent past the grace")
	}
}

func TestWorkerCheckFailsAMissingFile(t *testing.T) {
	t.Parallel()
	conn, done := workerPipe(t, WorkerOptions{})
	if err := writeJSONFrame(conn, frameHeader, planHeader{V: ProtocolVersion, Op: OpQuery, Files: nil, Target: 9, MaxRestored: DefaultMaxRestored}); err != nil {
		t.Fatal(err)
	}
	var end endMsg
	readTyped(t, conn, frameEnd, &end)
	if end.Code != CodeCheckFailed {
		t.Fatalf("an empty plan = %+v", end)
	}
	<-done
}
```

- [ ] **Step 2: Run it to verify it fails**

Run: `go test ./internal/dbreads/ -run 'TestWorker' -count=1`
Expected: FAIL, undefined names.

- [ ] **Step 3: Write `protocol.go`**

```go
package dbreads

import (
	"encoding/binary"
	"encoding/json"
	"errors"
	"io"

	"github.com/carlosframework/platform/internal/dbdoor"
)

// ProtocolVersion is the worker protocol's version, answered in hello. A
// worker that speaks another one never advertises anything (spec §7.1).
const ProtocolVersion = 1

// Frames are one type byte, a four-byte big-endian length and the payload,
// at most maxFrame bytes (spec §8.3: length-framed with a fixed maximum).
const (
	maxFrame         = 1 << 20
	fileFrameBytes   = 256 << 10
	outputFrameBytes = 64 << 10
)

const (
	frameHello      byte = 'H' // agent: the readiness probe
	frameHelloReply byte = 'h' // worker: its version and its view of its sandbox
	frameHeader     byte = 'P' // agent: the plan
	frameFile       byte = 'F' // agent: file bytes, in the header's order
	frameReady      byte = 'R' // worker: restored and checked; runs nothing yet
	frameRun        byte = 'X' // agent: check B passed; the statement
	frameStop       byte = 'S' // agent: end without running
	frameOutput     byte = 'O' // worker: output bytes
	frameEnd        byte = 'E' // worker: how it ended
)

var (
	errFrameTooLarge = errors.New("dbreads: frame over the protocol's maximum")
	errProtocol      = errors.New("dbreads: unexpected frame")
)

type hello struct {
	V int `json:"v"`
}

// HelloReply is the worker's answer to the probe: its protocol version and
// what it can see of the box (spec §7.1). A sandboxed worker sees only the
// loopback interface, an empty /data and no /etc/carlos.
type HelloReply struct {
	V           int      `json:"v"`
	Interfaces  []string `json:"interfaces"`
	DataEntries int      `json:"data_entries"`
	EtcReadable bool     `json:"etc_readable"`
	// Errors names every observation the worker could not make. A probe
	// fails on any: an unobserved sandbox is not a sandbox.
	Errors []string `json:"errors,omitempty"`
}

type planHeader struct {
	V           int              `json:"v"`
	Op          string           `json:"op"`
	Files       []dbdoor.LTXFile `json:"files"`
	Target      uint64           `json:"target"`
	MaxRestored int64            `json:"max_restored"`
}

type readyMsg struct {
	TXID uint64 `json:"txid"`
}

type runMsg struct {
	SQL string `json:"sql"`
}

type endMsg struct {
	Code  string `json:"code"`
	Error string `json:"error"`
}

// writeFrame writes one frame in a single Write.
func writeFrame(w io.Writer, typ byte, p []byte) error {
	if len(p) > maxFrame {
		return errFrameTooLarge
	}
	buf := make([]byte, 5, 5+len(p))
	buf[0] = typ
	binary.BigEndian.PutUint32(buf[1:], uint32(len(p)))
	_, err := w.Write(append(buf, p...))
	return err
}

func writeJSONFrame(w io.Writer, typ byte, v any) error {
	p, err := json.Marshal(v)
	if err != nil {
		return err
	}
	return writeFrame(w, typ, p)
}

func readFrame(r io.Reader) (byte, []byte, error) {
	var hdr [5]byte
	if _, err := io.ReadFull(r, hdr[:]); err != nil {
		return 0, nil, err
	}
	n := binary.BigEndian.Uint32(hdr[1:])
	if n > maxFrame {
		return 0, nil, errFrameTooLarge
	}
	p := make([]byte, n)
	if _, err := io.ReadFull(r, p); err != nil {
		return 0, nil, err
	}
	return hdr[0], p, nil
}
```

- [ ] **Step 4: Write `worker.go`**

```go
package dbreads

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/benbjohnson/litestream"
	lsfile "github.com/benbjohnson/litestream/file"
	"github.com/superfly/ltx"

	"github.com/carlosframework/platform/internal/dbdoor"
	"github.com/carlosframework/platform/internal/dbquery"
)

// WorkerOptions are ServeWorker's settings. Production (RunWorker) sets
// Scratch and leaves the rest zero.
type WorkerOptions struct {
	// Scratch is where the read's private directory goes: /var/tmp, the
	// unit's own PrivateTmp, which systemd removes at stop.
	Scratch string
	// QueryTimeout is QueryTimeout when zero; Grace is WorkerExitGrace.
	QueryTimeout time.Duration
	Grace        time.Duration
	// Exit ends the process (os.Exit when nil): the 5 s backstop for a step
	// that ignores its context (spec §8.3, codex 8).
	Exit func(code int)
	// Self is the hello's view of the sandbox (SelfView when nil).
	Self func() HelloReply
	// Restore is dbdoor.RestoreLocal when nil. Tests replace it.
	Restore func(ctx context.Context, c litestream.ReplicaClient, out string, target uint64) error
}

type frame struct {
	typ byte
	p   []byte
}

var errAgentGone = errors.New("dbreads: the agent closed the connection")

// ServeWorker is the worker's whole job on one connection (spec §8.3): a
// hello, or a plan, its files, a restore, ready, then run or stop. One
// goroutine reads the connection from the start; EOF or an error cancels
// the one context everything runs under, and if the work has not returned
// Grace later, the process exits.
func ServeWorker(conn io.ReadWriter, opt WorkerOptions) error {
	if opt.QueryTimeout == 0 {
		opt.QueryTimeout = QueryTimeout
	}
	if opt.Grace == 0 {
		opt.Grace = WorkerExitGrace
	}
	if opt.Exit == nil {
		opt.Exit = os.Exit
	}
	if opt.Self == nil {
		opt.Self = SelfView
	}
	if opt.Restore == nil {
		opt.Restore = dbdoor.RestoreLocal
	}
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	frames := make(chan frame)
	done := make(chan struct{})
	defer close(done)
	go func() {
		defer close(frames)
		for {
			typ, p, err := readFrame(conn)
			if err != nil {
				cancel()
				select {
				case <-done:
				case <-time.After(opt.Grace):
					opt.Exit(3)
				}
				return
			}
			select {
			case frames <- frame{typ, p}:
			case <-done:
				return
			}
		}
	}()
	next := func() (frame, error) {
		select {
		case f, ok := <-frames:
			if !ok {
				return frame{}, errAgentGone
			}
			return f, nil
		case <-ctx.Done():
			return frame{}, errAgentGone
		}
	}
	end := func(code string, err error) error {
		msg := endMsg{Code: code}
		if err != nil {
			msg.Error = err.Error()
		}
		return writeJSONFrame(conn, frameEnd, msg)
	}

	f, err := next()
	if err != nil {
		return err
	}
	switch f.typ {
	case frameHello:
		var h hello
		if json.Unmarshal(f.p, &h) != nil {
			return errProtocol
		}
		return writeJSONFrame(conn, frameHelloReply, opt.Self())
	case frameHeader:
	default:
		return errProtocol
	}
	var h planHeader
	if err := json.Unmarshal(f.p, &h); err != nil || h.V != ProtocolVersion || h.Op != OpQuery {
		return errProtocol
	}
	dir, err := os.MkdirTemp(opt.Scratch, "dbread-")
	if err != nil {
		return err
	}
	defer os.RemoveAll(dir)
	root := filepath.Join(dir, "replica")
	for _, lf := range h.Files {
		path := litestream.LTXFilePath(root, lf.Level, ltx.TXID(lf.MinTXID), ltx.TXID(lf.MaxTXID))
		if err := receiveFile(next, path, lf.Size); err != nil {
			if errors.Is(err, errAgentGone) {
				return err
			}
			return end(CodeCheckFailed, err)
		}
	}
	db := filepath.Join(dir, "copy.db")
	if err := opt.Restore(ctx, lsfile.NewReplicaClient(root), db, h.Target); err != nil {
		if ctx.Err() != nil {
			return errAgentGone
		}
		return end(CodeCheckFailed, err)
	}
	if st, err := os.Stat(db); err != nil || st.Size() > h.MaxRestored {
		return end(CodeTooLarge, err)
	}
	if err := writeJSONFrame(conn, frameReady, readyMsg{TXID: h.Target}); err != nil {
		return err
	}
	f, err = next()
	if err != nil {
		return err
	}
	switch f.typ {
	case frameStop:
		return nil
	case frameRun:
	default:
		return errProtocol
	}
	var run runMsg
	if err := json.Unmarshal(f.p, &run); err != nil {
		return errProtocol
	}
	qctx, qcancel := context.WithTimeout(ctx, opt.QueryTimeout)
	defer qcancel()
	out := &frameWriter{w: conn}
	qerr := dbquery.RunContext(qctx, out, db, run.SQL, dbquery.Options{Immutable: true})
	if ferr := out.flush(); ferr != nil {
		return ferr
	}
	switch {
	case qerr == nil:
		return end("", nil)
	case errors.Is(qctx.Err(), context.DeadlineExceeded):
		return end(CodeTimeout, nil)
	case ctx.Err() != nil:
		return errAgentGone
	}
	return end(CodeSQLError, qerr)
}

// receiveFile writes exactly size bytes of file frames to path, refusing a
// file larger than its header said (spec §8.3).
func receiveFile(next func() (frame, error), path string, size int64) error {
	if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
		return err
	}
	out, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o600)
	if err != nil {
		return err
	}
	defer out.Close()
	var got int64
	for got < size {
		f, err := next()
		if err != nil {
			return err
		}
		if f.typ != frameFile {
			return errProtocol
		}
		if got+int64(len(f.p)) > size {
			return fmt.Errorf("dbreads: %s is larger than its header said (%d bytes)", filepath.Base(path), size)
		}
		if _, err := out.Write(f.p); err != nil {
			return err
		}
		got += int64(len(f.p))
	}
	return out.Close()
}

// frameWriter frames the query's output in outputFrameBytes pieces.
type frameWriter struct {
	w   io.Writer
	buf []byte
}

func (f *frameWriter) Write(p []byte) (int, error) {
	f.buf = append(f.buf, p...)
	for len(f.buf) >= outputFrameBytes {
		if err := writeFrame(f.w, frameOutput, f.buf[:outputFrameBytes]); err != nil {
			return 0, err
		}
		f.buf = f.buf[outputFrameBytes:]
	}
	return len(p), nil
}

func (f *frameWriter) flush() error {
	if len(f.buf) == 0 {
		return nil
	}
	err := writeFrame(f.w, frameOutput, f.buf)
	f.buf = nil
	return err
}

// SelfView is what the worker can see of the box: in the unit, the loopback
// interface alone, an empty /data and no readable /etc/carlos.
//
// Interfaces come from /proc/self/net/dev, this process's own network
// namespace. net.Interfaces cannot be used: on Linux it opens an AF_NETLINK
// socket, which the unit's RestrictAddressFamilies=AF_UNIX refuses, and an
// empty list would read as "no network" (plan review finding 1). Every
// observation that fails is reported in Errors, and a probe fails on any.
func SelfView() HelloReply {
	h := HelloReply{V: ProtocolVersion}
	if raw, err := os.ReadFile("/proc/self/net/dev"); err != nil {
		h.Errors = append(h.Errors, "interfaces: "+err.Error())
	} else {
		h.Interfaces = parseNetDev(string(raw))
	}
	switch ents, err := os.ReadDir("/data"); {
	case err == nil:
		h.DataEntries = len(ents)
	case !errors.Is(err, os.ErrNotExist):
		h.Errors = append(h.Errors, "/data: "+err.Error())
	}
	if f, err := os.Open("/etc/carlos/host.env"); err == nil {
		f.Close()
		h.EtcReadable = true
	}
	return h
}

// parseNetDev reads /proc/net/dev's interface names: two header lines, then
// one "<name>: <counters>" line per interface.
func parseNetDev(s string) []string {
	var out []string
	for i, line := range strings.Split(s, "\n") {
		if i < 2 {
			continue
		}
		name, _, ok := strings.Cut(line, ":")
		if name = strings.TrimSpace(name); ok && name != "" {
			out = append(out, name)
		}
	}
	return out
}
```

- [ ] **Step 5: Run the tests**

Run (sandbox off: `net.Pipe` is fine inside, but the replicas need the Go cache): `go test ./internal/dbreads/ -run 'TestWorker' -count=1 -race`
Expected: PASS.

- [ ] **Step 6: Commit**

```bash
git add internal/dbreads/protocol.go internal/dbreads/worker.go internal/dbreads/worker_test.go
git commit -m "dbreads: the worker protocol and ServeWorker, with the 5 s exit"
```

---

### Task 8: `carlos system db-worker`

**Files:**
- Create: `internal/dbreads/worker_linux.go`
- Create: `internal/dbreads/worker_other.go`
- Create: `internal/dbreads/worker_linux_test.go`
- Modify: `system.go:52` (verb list) and `system.go:59-110` (dispatch)

**Interfaces:**
- Consumes: `ServeWorker`, `WorkerOptions` (Task 7).
- Produces: `RunWorker(args []string)`; `RunWorkerWith(opt WorkerOptions)`; `StdinConn(f *os.File, wantUID func() (uint32, error)) (net.Conn, error)`; `CarlosUID() (uint32, error)`.

- [ ] **Step 1: Write the failing test**

Create `internal/dbreads/worker_linux_test.go`:

```go
//go:build linux

package dbreads

import (
	"os"
	"path/filepath"
	"testing"

	"golang.org/x/sys/unix"
)

func me() (uint32, error) { return uint32(os.Getuid()), nil }

func other() (uint32, error) { return uint32(os.Getuid()) + 1, nil }

func socketpairFile(t *testing.T, typ int) (*os.File, *os.File) {
	t.Helper()
	fds, err := unix.Socketpair(unix.AF_UNIX, typ, 0)
	if err != nil {
		t.Fatal(err)
	}
	a, b := os.NewFile(uintptr(fds[0]), "a"), os.NewFile(uintptr(fds[1]), "b")
	t.Cleanup(func() { a.Close(); b.Close() })
	return a, b
}

// The worker runs only on a connected unix stream socket whose peer is the
// agent's user (spec §8.3): it cannot be started by hand or pointed at a
// file.
func TestStdinConnRefusesWhatIsNotTheAgentsSocket(t *testing.T) {
	t.Parallel()
	file, err := os.Create(filepath.Join(t.TempDir(), "f"))
	if err != nil {
		t.Fatal(err)
	}
	defer file.Close()
	r, w, err := os.Pipe()
	if err != nil {
		t.Fatal(err)
	}
	defer r.Close()
	defer w.Close()
	dgram, _ := socketpairFile(t, unix.SOCK_DGRAM)
	stream, _ := socketpairFile(t, unix.SOCK_STREAM)
	for name, f := range map[string]*os.File{"a file": file, "a pipe": r, "a datagram socket": dgram} {
		if _, err := StdinConn(f, me); err == nil {
			t.Errorf("%s accepted", name)
		}
	}
	if _, err := StdinConn(stream, other); err == nil {
		t.Fatal("a peer that is not the agent's user accepted")
	}
	c, err := StdinConn(stream, me)
	if err != nil {
		t.Fatal(err)
	}
	c.Close()
}
```

- [ ] **Step 2: Run it to verify it fails**

Run (sandbox off): `go test ./internal/dbreads/ -run 'TestStdinConn' -count=1`
Expected: FAIL, `StdinConn` undefined.

- [ ] **Step 3: Write the Linux and other files**

Create `internal/dbreads/worker_linux.go`:

```go
//go:build linux

package dbreads

import (
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"os/user"
	"strconv"

	"golang.org/x/sys/unix"
)

var errNotSocket = errors.New("stdin is not a connected unix stream socket")

// RunWorker is `carlos system db-worker`, which carlos-dbread@.service runs
// once per connection to carlos-dbread.socket (spec §8.3).
func RunWorker(args []string) {
	if len(args) != 0 {
		fmt.Fprintln(os.Stderr, "db-worker: takes no arguments")
		os.Exit(2)
	}
	RunWorkerWith(WorkerOptions{Scratch: "/var/tmp"})
}

// RunWorkerWith is RunWorker with its options supplied: the seam the root
// runner's acceptance tests use to make a restore slow (Task 15).
func RunWorkerWith(opt WorkerOptions) {
	conn, err := StdinConn(os.Stdin, CarlosUID)
	if err != nil {
		fmt.Fprintf(os.Stderr, "db-worker: %v\n", err)
		os.Exit(2)
	}
	if err := ServeWorker(conn, opt); err != nil {
		log.Printf("db-worker: %v", err)
		os.Exit(1)
	}
}

// CarlosUID is the agent's user, the only peer the worker serves.
func CarlosUID() (uint32, error) {
	u, err := user.Lookup("carlos")
	if err != nil {
		return 0, err
	}
	uid, err := strconv.ParseUint(u.Uid, 10, 32)
	return uint32(uid), err
}

// StdinConn checks f is a connected unix stream socket (SO_TYPE, the socket
// name's family, SO_PEERCRED) whose peer is wantUID, and returns it as a
// connection.
func StdinConn(f *os.File, wantUID func() (uint32, error)) (net.Conn, error) {
	fd := int(f.Fd())
	typ, err := unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_TYPE)
	if err != nil || typ != unix.SOCK_STREAM {
		return nil, errNotSocket
	}
	if sa, err := unix.Getsockname(fd); err != nil {
		return nil, errNotSocket
	} else if _, ok := sa.(*unix.SockaddrUnix); !ok {
		return nil, errNotSocket
	}
	cred, err := unix.GetsockoptUcred(fd, unix.SOL_SOCKET, unix.SO_PEERCRED)
	if err != nil || cred.Pid == 0 {
		return nil, errNotSocket
	}
	want, err := wantUID()
	if err != nil {
		return nil, err
	}
	if cred.Uid != want {
		return nil, fmt.Errorf("the peer is uid %d, not the agent's uid %d", cred.Uid, want)
	}
	c, err := net.FileConn(f)
	if err != nil {
		return nil, errNotSocket
	}
	return c, nil
}
```

Create `internal/dbreads/worker_other.go`:

```go
//go:build !linux

package dbreads

import (
	"errors"
	"fmt"
	"net"
	"os"
)

var errUnsupported = errors.New("db-worker runs only on Linux")

func RunWorker([]string) {
	fmt.Fprintln(os.Stderr, "db-worker:", errUnsupported)
	os.Exit(2)
}

func RunWorkerWith(WorkerOptions) { RunWorker(nil) }

func CarlosUID() (uint32, error) { return 0, errUnsupported }

func StdinConn(*os.File, func() (uint32, error)) (net.Conn, error) { return nil, errUnsupported }
```

In `system.go`, add `"db-worker"` to the `case` list in `systemVerb` (line 52), and to `runSystem`'s switch:

```go
	case "db-worker":
		// The db-read worker (db region forward spec §8.3): systemd starts
		// it per connection to carlos-dbread.socket. Never run by hand.
		dbreads.RunWorker(rest)
```

with the import `"github.com/carlosframework/platform/internal/dbreads"`. Do not add it to `systemUsage`: nobody runs it.

- [ ] **Step 4: Run the tests and the cross-compiles**

Run (sandbox off):
```bash
go test ./internal/dbreads/ -run 'TestStdinConn' -count=1
go build ./... && GOOS=darwin GOARCH=arm64 go build ./... && GOOS=windows GOARCH=amd64 go build ./...
```
Expected: PASS and three clean builds.

- [ ] **Step 5: Commit**

```bash
git add internal/dbreads/worker_linux.go internal/dbreads/worker_other.go internal/dbreads/worker_linux_test.go system.go
git commit -m "carlos system db-worker: the stdin socket and peer checks, Linux only"
```

---

### Task 9: Admission: reservations, read slots and the orphan rule

**Files:**
- Create: `internal/dbreads/admission.go`
- Create: `internal/dbreads/admission_test.go`

**Interfaces:**
- Produces: `newAdmission(units func(context.Context) (int, error), free func() (avail, total uint64, err error)) *admission`; methods `admitRead(ctx, id) error`, `grow(id string, need int64) error`, `finish(id string)`, `abandon(id string)`, `admitProbe(ctx) bool`, `probeDone()`, `opened() bool`, `closed()`; errors `errBusy`, `errOrphans`, `errNoRoom`.

- [ ] **Step 1: Write the failing test**

Create `internal/dbreads/admission_test.go`:

```go
package dbreads

import (
	"context"
	"errors"
	"testing"
	"time"
)

type unitsSeam struct {
	n   int
	err error
}

func (u *unitsSeam) count(context.Context) (int, error) { return u.n, u.err }

func gib(n uint64) uint64 { return n << 30 }

func TestAdmissionTwoReadsThenBusy(t *testing.T) {
	t.Parallel()
	u := &unitsSeam{}
	a := newAdmission(u.count, func() (uint64, uint64, error) { return gib(100), gib(200), nil })
	ctx := context.Background()
	for _, id := range []string{"r1", "r2"} {
		if err := a.admitRead(ctx, id); err != nil {
			t.Fatalf("%s: %v", id, err)
		}
	}
	if err := a.admitRead(ctx, "r3"); !errors.Is(err, errBusy) {
		t.Fatalf("a third read: %v", err)
	}
	// The probe still has its connection (spec §7.1, codex 9).
	if !a.opened() || !a.opened() || !a.admitProbe(ctx) || !a.opened() {
		t.Fatal("two reads and a probe do not fit three connections")
	}
	if a.opened() {
		t.Fatal("a fourth connection was allowed")
	}
}

// T12, unit half: free space that fits one read admits one.
func TestAdmissionDiskFitsOneOfTwo(t *testing.T) {
	t.Parallel()
	a := newAdmission((&unitsSeam{}).count, func() (uint64, uint64, error) { return gib(12), gib(20), nil })
	ctx := context.Background()
	if err := a.admitRead(ctx, "r1"); err != nil {
		t.Fatal(err)
	}
	if err := a.admitRead(ctx, "r2"); !errors.Is(err, errNoRoom) {
		t.Fatalf("a second read on a box with room for one: %v", err)
	}
	if err := a.grow("r1", int64(gib(8))); !errors.Is(err, errNoRoom) {
		t.Fatalf("growing past the floor and 10%%: %v", err)
	}
	if err := a.grow("r1", int64(gib(6))); err != nil {
		t.Fatalf("growing within room: %v", err)
	}
}

// An orphan (a unit this agent is not running) blocks every admission until
// it is gone, and no size is guessed for it (spec §5.7, codex 8).
func TestAdmissionRefusesBesideAnOrphan(t *testing.T) {
	t.Parallel()
	u := &unitsSeam{n: 1}
	a := newAdmission(u.count, func() (uint64, uint64, error) { return gib(100), gib(200), nil })
	ctx := context.Background()
	if err := a.admitRead(ctx, "r1"); !errors.Is(err, errOrphans) {
		t.Fatalf("beside an orphan: %v", err)
	}
	if a.admitProbe(ctx) {
		t.Fatal("a probe beside an orphan")
	}
	u.n = 0
	if err := a.admitRead(ctx, "r1"); err != nil {
		t.Fatalf("once the orphan is gone: %v", err)
	}
}

// A finished read's reservation is held until no db-read unit is left, since
// systemd removes the scratch only at unit stop.
func TestAdmissionHoldsAReservationUntilItsUnitIsGone(t *testing.T) {
	t.Parallel()
	u := &unitsSeam{}
	// 12 GiB free of 20: r1 grown to 6 leaves room for r2's floor only once
	// r1's reservation is released.
	a := newAdmission(u.count, func() (uint64, uint64, error) { return gib(12), gib(20), nil })
	ctx := context.Background()
	if err := a.admitRead(ctx, "r1"); err != nil {
		t.Fatal(err)
	}
	a.opened()
	if err := a.grow("r1", int64(gib(6))); err != nil {
		t.Fatal(err)
	}
	u.n = 1
	a.closed()
	a.finish("r1")
	// The unit is still deactivating: one unit, no connection. Refused.
	if err := a.admitRead(ctx, "r2"); !errors.Is(err, errOrphans) {
		t.Fatalf("while the unit deactivates: %v", err)
	}
	u.n = 0
	if err := a.admitRead(ctx, "r2"); err != nil {
		t.Fatalf("after the unit is gone the reservation is free: %v", err)
	}
}

// Review Focus 5: a unit listing that fails admits nothing and skips the
// probe rather than guessing.
func TestAdmissionFailsClosedWhenUnitsCannotBeListed(t *testing.T) {
	t.Parallel()
	u := &unitsSeam{err: errors.New("systemctl: not found")}
	a := newAdmission(u.count, func() (uint64, uint64, error) { return gib(100), gib(200), nil })
	if err := a.admitRead(context.Background(), "r1"); err == nil {
		t.Fatal("admitted with no unit listing")
	}
	if a.admitProbe(context.Background()) {
		t.Fatal("probed with no unit listing")
	}
}

// A read admitted and then lost in the election started no worker: its
// floor goes at once, even while another read's unit is running.
func TestAdmissionAbandonFreesAtOnce(t *testing.T) {
	t.Parallel()
	u := &unitsSeam{}
	// 17 GiB of 20: room for two floors (17-10 = 7), not three.
	a := newAdmission(u.count, func() (uint64, uint64, error) { return gib(17), gib(20), nil })
	ctx := context.Background()
	if err := a.admitRead(ctx, "running"); err != nil {
		t.Fatal(err)
	}
	a.opened()
	u.n = 1 // its worker unit is up, so finished reservations stay held
	if err := a.admitRead(ctx, "lost"); err != nil {
		t.Fatal(err)
	}
	a.abandon("lost") // it lost the election; no worker started
	if err := a.admitRead(ctx, "next"); err != nil {
		t.Fatalf("the lost read's floor is still held: %v", err)
	}
}

// Plan review finding 10: a retried read keeps its first attempt's
// reservation while that worker's unit is still stopping, and settle waits
// for the unit. Mutation: retry leaves held[id] in place instead of moving
// it to a retired key; the grow below then fits and this test is red.
func TestAdmissionRetryHoldsTheOldReservation(t *testing.T) {
	t.Parallel()
	u := &unitsSeam{}
	a := newAdmission(u.count, func() (uint64, uint64, error) { return gib(12), gib(20), nil })
	ctx := context.Background()
	if err := a.admitRead(ctx, "r1"); err != nil {
		t.Fatal(err)
	}
	if err := a.grow("r1", int64(gib(6))); err != nil {
		t.Fatal(err)
	}
	u.n = 1 // the first worker's connection is closed; its unit is stopping
	a.retry("r1", 1)
	if err := a.grow("r1", int64(gib(5))); !errors.Is(err, errNoRoom) {
		t.Fatalf("the stopping worker's scratch was not held: %v", err)
	}
	short, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
	defer cancel()
	if err := a.settle(short, 10*time.Millisecond); !errors.Is(err, context.DeadlineExceeded) {
		t.Fatalf("settle returned beside a live unit: %v", err)
	}
	u.n = 0
	if err := a.settle(ctx, 10*time.Millisecond); err != nil {
		t.Fatal(err)
	}
	if err := a.grow("r1", int64(gib(5))); err != nil {
		t.Fatalf("after the unit stopped: %v", err)
	}
}

func TestAdmissionFailsClosedWhenTheDiskCannotBeRead(t *testing.T) {
	t.Parallel()
	a := newAdmission((&unitsSeam{}).count, func() (uint64, uint64, error) { return 0, 0, errors.New("statfs") })
	if err := a.admitRead(context.Background(), "r1"); !errors.Is(err, errNoRoom) {
		t.Fatalf("admitted with no disk reading: %v", err)
	}
}
```

- [ ] **Step 2: Run it to verify it fails**

Run: `go test ./internal/dbreads/ -run 'TestAdmission' -count=1`
Expected: FAIL, `newAdmission` undefined.

- [ ] **Step 3: Write `admission.go`**

```go
package dbreads

import (
	"context"
	"errors"
	"fmt"
	"sync"
	"time"
)

var (
	errBusy    = errors.New("dbreads: this box is running its two reads")
	errOrphans = errors.New("dbreads: a carlos-dbread@ unit this agent is not running is still active")
	errNoRoom  = errors.New("dbreads: not enough disk for the read")
)

// admission is the agent's one table (spec §5.7, J5): how many worker
// connections it holds, which reads it is running, and every disk
// reservation. The agent is the only process that starts workers, so one
// mutex covers it all.
type admission struct {
	units func(context.Context) (int, error)
	free  func() (avail, total uint64, err error)

	mu      sync.Mutex
	conns   int
	running map[string]bool
	held    map[string]int64
	probing bool
}

func newAdmission(units func(context.Context) (int, error), free func() (uint64, uint64, error)) *admission {
	return &admission{units: units, free: free, running: map[string]bool{}, held: map[string]int64{}}
}

// reconcileLocked is the refusal-based reconciliation (spec §5.7): while any
// carlos-dbread@ unit is active, activating or deactivating beyond the
// connections this agent holds, nothing is admitted. A finished read's
// reservation is released only when no unit is left at all: then every
// stopped unit's scratch has been removed by systemd.
func (a *admission) reconcileLocked(ctx context.Context) error {
	n, err := a.units(ctx)
	if err != nil {
		return fmt.Errorf("dbreads: list carlos-dbread@ units: %w", err)
	}
	if n > a.conns {
		return errOrphans
	}
	if n == 0 {
		for id := range a.held {
			if !a.running[id] {
				delete(a.held, id)
			}
		}
	}
	return nil
}

// fitsLocked: after subtracting every other reservation and need, the
// filesystem holding /var/tmp keeps DiskFloor and DiskFreePercent free.
func (a *admission) fitsLocked(id string, need int64) bool {
	avail, total, err := a.free()
	if err != nil {
		return false
	}
	left := int64(avail) - need
	for k, v := range a.held {
		if k != id {
			left -= v
		}
	}
	return left >= DiskFloor && left >= int64(total)*DiskFreePercent/100
}

// admitRead admits a read before it enters the election: a free read slot,
// no orphan, and room for the floor reservation.
func (a *admission) admitRead(ctx context.Context, id string) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	if err := a.reconcileLocked(ctx); err != nil {
		return err
	}
	if len(a.running) >= ReadsPerBox {
		return errBusy
	}
	if !a.fitsLocked(id, DiskFloor) {
		return errNoRoom
	}
	a.running[id] = true
	a.held[id] = DiskFloor
	return nil
}

// grow raises a running read's reservation to need (never below the floor)
// once its plan is known.
func (a *admission) grow(id string, need int64) error {
	a.mu.Lock()
	defer a.mu.Unlock()
	need = max(need, DiskFloor)
	if !a.fitsLocked(id, need) {
		return errNoRoom
	}
	a.held[id] = need
	return nil
}

// finish ends a read's slot. Its reservation stays until reconcileLocked
// sees no unit left.
func (a *admission) finish(id string) {
	a.mu.Lock()
	defer a.mu.Unlock()
	delete(a.running, id)
}

// abandon gives back a read this agent admitted and then did not run (it
// lost the election, or stopped before it): no worker was started for it,
// so its reservation goes at once rather than waiting for the units to drain.
func (a *admission) abandon(id string) {
	a.mu.Lock()
	defer a.mu.Unlock()
	delete(a.running, id)
	delete(a.held, id)
}

// retry is a read starting a fresh plan after a planned file vanished (spec
// §8.2). Its previous worker may still hold scratch until its unit stops, so
// that reservation moves to a retired key, held until no unit is left (J5),
// and the read starts again from the floor (plan review finding 10).
func (a *admission) retry(id string, attempt int) {
	a.mu.Lock()
	defer a.mu.Unlock()
	if v, ok := a.held[id]; ok {
		a.held[fmt.Sprintf("%s#%d", id, attempt)] = v
	}
	a.held[id] = DiskFloor
}

// settle waits until no carlos-dbread@ unit is running beyond this agent's
// open connections, so a retry opens its next worker only once the last one
// is gone, and never into the probe's connection. It releases retired
// reservations once no unit is left at all.
func (a *admission) settle(ctx context.Context, poll time.Duration) error {
	for {
		a.mu.Lock()
		err := a.reconcileLocked(ctx)
		a.mu.Unlock()
		if !errors.Is(err, errOrphans) {
			return err
		}
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-time.After(poll):
		}
	}
}

// admitProbe admits the readiness probe: no orphan and no other probe. The
// probe's connection is the third (opened checks the count).
func (a *admission) admitProbe(ctx context.Context) bool {
	a.mu.Lock()
	defer a.mu.Unlock()
	if a.probing || a.reconcileLocked(ctx) != nil {
		return false
	}
	a.probing = true
	return true
}

func (a *admission) probeDone() {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.probing = false
}

// opened takes a connection slot; the agent never opens a fourth.
func (a *admission) opened() bool {
	a.mu.Lock()
	defer a.mu.Unlock()
	if a.conns >= MaxConnections {
		return false
	}
	a.conns++
	return true
}

func (a *admission) closed() {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.conns--
}
```

- [ ] **Step 4: Run the tests**

Run: `go test ./internal/dbreads/ -run 'TestAdmission' -count=1 -race`
Expected: PASS.

- [ ] **Step 5: Commit**

```bash
git add internal/dbreads/admission.go internal/dbreads/admission_test.go
git commit -m "dbreads: admission, held until the worker unit is gone"
```

---

### Task 10: The agent's identity check and the election

**Files:**
- Create: `internal/dbreads/class.go`
- Create: `internal/dbreads/agent.go`
- Create: `internal/dbreads/fixture_test.go`
- Create: `internal/dbreads/agent_test.go`
- Modify: `internal/console/apidb.go:236-250` (`dbClassRefusal` delegates)

**Interfaces:**
- Consumes: `provision.GetRecord`, `provision.ValidHostShape`, `hostclaim.Incarnation`, `registry.FleetPlacement`, `admission` (Task 9), `Verify`, `QueueMatches` (Task 4), `ServeWorker` (Task 7).
- Produces: `ClassRefusal(rec provision.Record) string`; `type AgentConfig struct` (fields below); `NewAgent(cfg AgentConfig) *Agent`; `(*Agent).Capable() bool`; `(*Agent).Wait()`; unexported `check(ctx, req) (provision.Record, string, error)`, `elect(ctx, id) (Picked, bool)`, `consider(ctx, e QueueEntry)`, `dial(ctx) (net.Conn, error)`, `decide(id)`, `isDecided(id) bool`, `prune(now)`, `askProbe()`; `serve` is Task 11's and is called from `consider`.

- [ ] **Step 1: Write the test fixture**

Create `internal/dbreads/fixture_test.go`. It is shared by Tasks 10 to 12. Its in-process worker runs the real `ServeWorker` over `net.Pipe`: not acceptance.

```go
package dbreads

import (
	"bytes"
	"context"
	"crypto/ecdh"
	"crypto/ed25519"
	"crypto/rand"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"net"
	"os"
	"sort"
	"sync"
	"sync/atomic"
	"testing"
	"time"

	lsfile "github.com/benbjohnson/litestream/file"

	"github.com/carlosframework/platform/internal/dbdoor"
	"github.com/carlosframework/platform/internal/dbdoor/dbdoortest"
	"github.com/carlosframework/platform/internal/hostclaim"
	"github.com/carlosframework/platform/internal/provision"
	"github.com/carlosframework/platform/internal/release"
)

const fxAccount, fxApp, fxHost = "bab", "shop", "shop.example.com"

// inProcWorkers runs the real ServeWorker in process over net.Pipe: not
// acceptance (Task 15 drives the installed units). units counts the live
// workers, the way the box counts carlos-dbread@ units.
type inProcWorkers struct {
	t     *testing.T
	opt   WorkerOptions
	live  atomic.Int64
	dials atomic.Int64
	// linger keeps a finished worker counted as a live unit for a while,
	// as systemd's deactivation does; liveAtDial records the live count
	// each dial saw.
	linger     time.Duration
	mu         sync.Mutex
	liveAtDial []int64
	// failStart makes the worker end at once without a word, as a unit
	// whose service fails to start after the socket accepted does.
	failStart atomic.Bool
}

func (w *inProcWorkers) dial(context.Context) (net.Conn, error) {
	agentEnd, workerEnd := net.Pipe()
	w.mu.Lock()
	w.liveAtDial = append(w.liveAtDial, w.live.Load())
	w.mu.Unlock()
	w.dials.Add(1)
	w.live.Add(1)
	if w.failStart.Load() {
		// The socket accepted and the service died: the plan's header is
		// read by nobody useful, and the connection drops.
		go func() {
			readFrame(workerEnd)
			workerEnd.Close()
			time.Sleep(w.linger)
			w.live.Add(-1)
		}()
		return agentEnd, nil
	}
	opt := w.opt
	if opt.Scratch == "" {
		opt.Scratch = w.t.TempDir()
	}
	if opt.Exit == nil {
		opt.Exit = func(int) {}
	}
	if opt.Self == nil {
		opt.Self = func() HelloReply { return HelloReply{V: ProtocolVersion, Interfaces: []string{"lo"}} }
	}
	go func() {
		ServeWorker(workerEnd, opt)
		workerEnd.Close()
		time.Sleep(w.linger)
		w.live.Add(-1)
	}()
	return agentEnd, nil
}

func (w *inProcWorkers) units(context.Context) (int, error) { return int(w.live.Load()), nil }

func plentyFree() (uint64, uint64, error) { return 100 << 30, 200 << 30, nil }

type fixture struct {
	t        *testing.T
	store    release.Store
	rootPub  ed25519.PublicKey
	rootPriv ed25519.PrivateKey
	reply    *ecdh.PrivateKey
	replica  string
	now      time.Time
}

// newFixture is a deployment store holding shop.example.com's record in uk,
// and a file replica of its database with batches*10 rows.
func newFixture(t *testing.T, batches int) *fixture {
	t.Helper()
	pub, priv, err := ed25519.GenerateKey(rand.Reader)
	if err != nil {
		t.Fatal(err)
	}
	reply, err := NewReplyKey()
	if err != nil {
		t.Fatal(err)
	}
	fx := &fixture{t: t, store: release.NewDirStore(t.TempDir()), rootPub: pub, rootPriv: priv, reply: reply,
		replica: t.TempDir(), now: time.Now().UTC().Truncate(time.Second)}
	if batches > 0 {
		dbdoortest.Replicate(t, fx.replica, batches)
	}
	fx.putRecord(provision.Record{Host: fxHost, Region: "uk", CreatedAt: time.Date(2026, 9, 1, 0, 0, 0, 0, time.UTC)})
	return fx
}

func (fx *fixture) putRecordUnder(acct string, rec provision.Record) {
	fx.t.Helper()
	rec.Account, rec.App = acct, fxApp
	if rec.Host == "" {
		rec.Host = fxHost
	}
	if rec.Hibernate == nil {
		yes := true
		rec.Hibernate = &yes
	}
	body, err := json.Marshal(rec)
	if err != nil {
		fx.t.Fatal(err)
	}
	key := provision.RecordKey(acct, fxApp, rec.Host)
	if err := fx.store.Delete(context.Background(), key); err != nil {
		fx.t.Fatal(err)
	}
	if _, err := fx.store.Put(context.Background(), key, body, ""); err != nil {
		fx.t.Fatal(err)
	}
}

func (fx *fixture) putRecord(rec provision.Record) { fx.putRecordUnder(fxAccount, rec) }

func (fx *fixture) record() provision.Record {
	fx.t.Helper()
	rec, err := provision.GetRecord(context.Background(), fx.store, fxAccount, fxApp, fxHost)
	if err != nil {
		fx.t.Fatal(err)
	}
	return *rec
}

// request is the envelope the console would sign for the current record.
func (fx *fixture) request(sqlText, at string) Request {
	fx.t.Helper()
	rec := fx.record()
	inc, err := hostclaim.Incarnation(rec.Account, rec.App, rec.Host, rec.CreatedAt)
	if err != nil {
		fx.t.Fatal(err)
	}
	id, err := MintID()
	if err != nil {
		fx.t.Fatal(err)
	}
	return Request{ID: id, Account: fxAccount, App: fxApp, Host: fxHost, Incarnation: inc, Region: "uk",
		Op: OpQuery, SQL: sqlText, At: at, ReplyKey: EncodeReplyKey(fx.reply.PublicKey()),
		By: "member@example.com", IssuedAt: fx.now.Format(time.RFC3339)}
}

// submit is the console's two creates: the signed request, then the queue
// entry.
func (fx *fixture) submit(req Request) QueueEntry {
	fx.t.Helper()
	wire, err := Sign(release.RootSigner(fx.rootPriv), req)
	if err != nil {
		fx.t.Fatal(err)
	}
	if _, err := fx.store.Put(context.Background(), RequestKey(req.ID), wire, ""); err != nil {
		fx.t.Fatal(err)
	}
	issued, _ := req.Issued()
	key := QueueKey(req.Region, issued, req.ID)
	if _, err := fx.store.Put(context.Background(), key, nil, ""); err != nil {
		fx.t.Fatal(err)
	}
	e, _ := ParseQueueKey(key)
	return e
}

// agent is a capable agent in uk over the fixture's store and replica.
// Its probe is Task 12's: it starts capable.
func (fx *fixture) agent(box string, mut ...func(*AgentConfig, *inProcWorkers)) (*Agent, *inProcWorkers) {
	w := &inProcWorkers{t: fx.t}
	cfg := AgentConfig{
		Store: fx.store, Region: "uk", Box: box, Boot: "boot-" + box, Pub: fx.rootPub, HibernatePrefix: "instances",
		OpenReplica: func(_ context.Context, prefix string) (dbdoor.ReplicaReader, error) {
			if prefix != "instances/"+fxHost {
				fx.t.Errorf("the agent asked for prefix %q", prefix)
			}
			return lsfile.NewReplicaClient(fx.replica), nil
		},
		Units: w.units, Free: plentyFree, Logf: fx.t.Logf,
		Jitter: func() time.Duration { return 0 },
	}
	for _, m := range mut {
		m(&cfg, w)
	}
	cfg.DialWorker = w.dial
	a := NewAgent(cfg)
	a.probeOK.Store(true)
	return a, w
}

// chunkKeys lists a read's chunk objects.
func (fx *fixture) chunkKeys(id string) []string {
	keys, err := fx.store.List(context.Background(), OutPrefix(id))
	if err != nil && !errors.Is(err, os.ErrNotExist) {
		fx.t.Fatal(err)
	}
	sort.Strings(keys)
	return keys
}

// answer reads a read's result and opens its chunks as the CLI would.
func (fx *fixture) answer(id string) ([]byte, Summary, Result) {
	fx.t.Helper()
	raw, _, err := fx.store.Get(context.Background(), ResultKey(id))
	if err != nil {
		fx.t.Fatalf("no result for %s: %v", id, err)
	}
	var r Result
	if err := json.Unmarshal(raw, &r); err != nil || r.Valid() != nil {
		fx.t.Fatalf("result %s: %v", raw, err)
	}
	s, err := OpenSummary(fx.reply, id, r.Sealed)
	if err != nil {
		fx.t.Fatal(err)
	}
	var out bytes.Buffer
	for seq := int64(1); seq <= r.LastSeq; seq++ {
		sealed, _, err := fx.store.Get(context.Background(), ChunkKey(id, seq))
		if err != nil {
			fx.t.Fatalf("chunk %d: %v", seq, err)
		}
		plain, err := OpenChunk(fx.reply, id, seq, StreamRows, seq == r.LastSeq, sealed)
		if err != nil {
			fx.t.Fatalf("chunk %d: %v", seq, err)
		}
		out.Write(plain)
	}
	sum := sha256.Sum256(out.Bytes())
	if r.State == StateDone && (int64(out.Len()) != s.Bytes || hex.EncodeToString(sum[:]) != s.SHA256) {
		fx.t.Fatalf("the answer does not add up: %d bytes, summary %+v", out.Len(), s)
	}
	return out.Bytes(), s, r
}
```

- [ ] **Step 2: Write the failing tests**

Create `internal/dbreads/agent_test.go`:

```go
package dbreads

import (
	"context"
	"errors"
	"math/rand/v2"
	"sync"
	"testing"
	"time"

	"github.com/carlosframework/platform/internal/provision"
	"github.com/carlosframework/platform/internal/release"
)

// The identity check (spec §8.2): the record as the envelope named it, or a
// code. T9's stages are Task 11's; this is the check itself.
func TestCheckIsTheRecordAsTheEnvelopeNamedIt(t *testing.T) {
	t.Parallel()
	no := false
	for name, c := range map[string]struct {
		change func(fx *fixture)
		want   string
	}{
		"unchanged":                   {func(*fixture) {}, ""},
		"moved to another region":     {func(fx *fixture) { r := fx.record(); r.Region = "ie"; fx.putRecord(r) }, CodeRecordChanged},
		"moving":                      {func(fx *fixture) { r := fx.record(); r.Move = &provision.MoveState{ID: "mv_x", To: "ie", State: "requested"}; fx.putRecord(r) }, CodeMoving},
		"recreated in the account":    {func(fx *fixture) { r := fx.record(); r.CreatedAt = r.CreatedAt.Add(time.Hour); fx.putRecord(r) }, CodeRecordChanged},
		"recreated in another account": {func(fx *fixture) {
			created := fx.record().CreatedAt
			fx.store.Delete(context.Background(), provision.RecordKey(fxAccount, fxApp, fxHost))
			fx.putRecordUnder("bac", provision.Record{Region: "uk", CreatedAt: created})
		}, CodeRecordChanged},
		"no longer sleeps":            {func(fx *fixture) { r := fx.record(); r.Hibernate = &no; fx.putRecord(r) }, CodeRecordChanged},
		"pooled":                      {func(fx *fixture) { r := fx.record(); r.Pool = "shared"; fx.putRecord(r) }, CodeRecordChanged},
		"placed on a fleet":           {func(fx *fixture) { r := fx.record(); r.Region = "fleet/acme"; fx.putRecord(r) }, CodeRecordChanged},
	} {
		t.Run(name, func(t *testing.T) {
			t.Parallel()
			fx := newFixture(t, 0)
			req := fx.request("SELECT 1", "")
			c.change(fx)
			a, _ := fx.agent("uk-1")
			_, code, err := a.check(context.Background(), req)
			if err != nil || code != c.want {
				t.Fatalf("check = %q, %v; want %q", code, err, c.want)
			}
		})
	}
}

// T5: two capable boxes in one region; exactly one owns each read, across
// 1,000 reads with random jitter.
func TestElectionOneOwnerAcrossTwoAgents(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 0)
	a, _ := fx.agent("uk-1")
	b, _ := fx.agent("uk-2")
	var mu sync.Mutex
	owners := map[string]int{}
	var wg sync.WaitGroup
	for i := 0; i < 1000; i++ {
		id, err := MintID()
		if err != nil {
			t.Fatal(err)
		}
		for _, ag := range []*Agent{a, b} {
			wg.Add(1)
			go func(ag *Agent) {
				defer wg.Done()
				time.Sleep(rand.N(2 * time.Millisecond))
				if _, ok := ag.elect(context.Background(), id); ok {
					mu.Lock()
					owners[id]++
					mu.Unlock()
				}
			}(ag)
		}
	}
	wg.Wait()
	if len(owners) != 1000 {
		t.Fatalf("%d reads have an owner, want 1000", len(owners))
	}
	for id, n := range owners {
		if n != 1 {
			t.Fatalf("%s has %d owners", id, n)
		}
	}
}

// lossyStore commits some Puts and then answers an error: a response lost
// on the way back (T5, codex 16).
type lossyStore struct {
	release.Store
	lose   func(key string) bool
	refuse func(key string) bool
}

func (s lossyStore) Put(ctx context.Context, key string, body []byte, ifMatch string) (string, error) {
	if s.refuse != nil && s.refuse(key) {
		return "", errors.New("connection reset before the write")
	}
	etag, err := s.Store.Put(ctx, key, body, ifMatch)
	if err == nil && s.lose != nil && s.lose(key) {
		return "", errors.New("connection reset after the write")
	}
	return etag, err
}

// A box whose picked create commits but answers an error reads it back and
// owns the read.
func TestElectionReadsBackALostAnswer(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 0)
	a, _ := fx.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) {
		c.Store = lossyStore{Store: fx.store, lose: func(string) bool { return true }}
	})
	if _, ok := a.elect(context.Background(), "dbr_aaaaaaaaaaaaaaaaaaaaaaaaaa"); !ok {
		t.Fatal("a lost answer to a create that landed was not owned")
	}
}

// A box whose create answers an error while another box owns the read steps
// away; so does one whose read-back fails.
func TestElectionStepsAwayFromAnotherOwner(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 0)
	a, _ := fx.agent("uk-1")
	id := "dbr_aaaaaaaaaaaaaaaaaaaaaaaaaa"
	if _, ok := a.elect(context.Background(), id); !ok {
		t.Fatal("the first create did not own")
	}
	b, _ := fx.agent("uk-2", func(c *AgentConfig, _ *inProcWorkers) {
		c.Store = lossyStore{Store: fx.store, refuse: func(string) bool { return true }}
	})
	if _, ok := b.elect(context.Background(), id); ok {
		t.Fatal("a box owned a read another box had picked")
	}
	c, _ := fx.agent("uk-3", func(cfg *AgentConfig, _ *inProcWorkers) {
		cfg.Store = failingGets{lossyStore{Store: fx.store, refuse: func(string) bool { return true }}}
	})
	if _, ok := c.elect(context.Background(), "dbr_bbbbbbbbbbbbbbbbbbbbbbbbbb"); ok {
		t.Fatal("a box owned a read it could not read back")
	}
}

type failingGets struct{ release.Store }

func (failingGets) Get(context.Context, string) ([]byte, string, error) {
	return nil, "", errors.New("timeout")
}
```

- [ ] **Step 3: Run them to verify they fail**

Run: `go test ./internal/dbreads/ -run 'TestCheck|TestElection' -count=1`
Expected: FAIL, undefined `NewAgent`, `AgentConfig`.

- [ ] **Step 4: Move the class rail**

Create `internal/dbreads/class.go` with `console.dbClassRefusal`'s body verbatim, renamed:

```go
package dbreads

import (
	"fmt"

	"github.com/carlosframework/platform/internal/provision"
)

// ClassRefusal is the class rail as a sentence, or "" for an
// activator-managed exec instance: the only class whose database the
// platform replicates. It moved here from the console's db door so the door
// and the box's identity bracket refuse on one rule (spec §8.2); the
// sentences are the door's, unchanged.
func ClassRefusal(rec provision.Record) string {
	if k := rec.Kind; k != "" && k != "instance" {
		return fmt.Sprintf("%s is a %s route. The platform keeps a database copy only for instances.", rec.Host, k)
	}
	if rec.Addr != "" || len(rec.Addrs) > 0 {
		return fmt.Sprintf("%s is served from its own address, so the platform does not manage its database.", rec.Host)
	}
	if !rec.HibernateOrDefault() {
		return fmt.Sprintf("%s does not sleep, so the platform does not keep a copy of its database.", rec.Host)
	}
	return ""
}
```

In `internal/console/apidb.go`, make `dbClassRefusal` delegate, keeping its doc comment and adding "The rule lives in dbreads.ClassRefusal (db region forward spec §8.2).":

```go
func dbClassRefusal(rec provision.Record) string { return dbreads.ClassRefusal(rec) }
```

- [ ] **Step 5: Write `agent.go`**

```go
package dbreads

import (
	"context"
	"crypto/ed25519"
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"errors"
	"net"
	"os"
	"sync"
	"sync/atomic"
	"time"

	mrand "math/rand/v2"

	"github.com/carlosframework/platform/internal/dbdoor"
	"github.com/carlosframework/platform/internal/hostclaim"
	"github.com/carlosframework/platform/internal/provision"
	"github.com/carlosframework/platform/internal/registry"
	"github.com/carlosframework/platform/internal/release"
)

// AgentConfig is what the box's db-reads loop needs (spec §7, §8).
// internal/host fills it from the box's environment; tests fill it with
// stand-ins.
type AgentConfig struct {
	Store           release.Store     // the deployment bucket
	Region          string            // CARLOS_REGION
	Box             string            // this box's label, as its edges file names it
	Boot            string            // this agent process's id
	Pub             ed25519.PublicKey // CARLOS_RELEASE_PUBKEY
	HibernatePrefix string            // CARLOS_HIBERNATE_PREFIX
	// OpenReplica opens the read side of this box's own region bucket at a
	// prefix the agent derived (lease.ReadReplicaClient in production).
	OpenReplica func(ctx context.Context, prefix string) (dbdoor.ReplicaReader, error)
	// DialWorker connects to carlos-dbread.socket.
	DialWorker func(ctx context.Context) (net.Conn, error)
	// Units counts carlos-dbread@ units active, activating or deactivating.
	Units func(ctx context.Context) (int, error)
	// Free reads the filesystem holding /var/tmp.
	Free        func() (avail, total uint64, err error)
	MaxRestored int64 // DefaultMaxRestored when zero
	Now         func() time.Time
	Jitter      func() time.Duration // 0 to MaxJitter
	Logf        func(format string, args ...any)
	// Draining is this box's own published draining flag (its edges file's
	// draining field); a draining box takes no new read. Never draining
	// when nil.
	Draining func() bool

	// Test seams; zero is the spec's value.
	OwnerDeadline time.Duration
	PlanBudget    time.Duration
	CancelEvery   time.Duration
	ChunkEvery    time.Duration
	MaxOutput     int64
}

// Agent is the box's half of forwarded reads (spec §8.1): it lists the
// region's queue, verifies requests, elects an owner, runs the identity
// bracket around planning and download, streams bytes to a worker, and
// seals and writes output. It never opens SQLite, decodes pages, runs SQL or
// writes a file.
type Agent struct {
	cfg AgentConfig
	adm *admission

	mu      sync.Mutex
	decided map[string]time.Time

	probeOK    atomic.Bool
	probeAfter chan struct{}
	reads      sync.WaitGroup
}

func NewAgent(cfg AgentConfig) *Agent {
	if cfg.MaxRestored <= 0 {
		cfg.MaxRestored = DefaultMaxRestored
	}
	if cfg.Now == nil {
		cfg.Now = time.Now
	}
	if cfg.Jitter == nil {
		cfg.Jitter = func() time.Duration { return mrand.N(MaxJitter) }
	}
	if cfg.Logf == nil {
		cfg.Logf = func(string, ...any) {}
	}
	if cfg.Draining == nil {
		cfg.Draining = func() bool { return false }
	}
	if cfg.OwnerDeadline == 0 {
		cfg.OwnerDeadline = OwnerDeadline
	}
	if cfg.PlanBudget == 0 {
		cfg.PlanBudget = PlanBudget
	}
	if cfg.CancelEvery == 0 {
		cfg.CancelEvery = CancelEvery
	}
	if cfg.ChunkEvery == 0 {
		cfg.ChunkEvery = ChunkEvery
	}
	if cfg.MaxOutput == 0 {
		cfg.MaxOutput = MaxOutputBytes
	}
	return &Agent{cfg: cfg, adm: newAdmission(cfg.Units, cfg.Free), decided: map[string]time.Time{},
		probeAfter: make(chan struct{}, 1)}
}

// Capable is whether this box may publish db-read-1: its last readiness
// probe passed (spec §7.1).
func (a *Agent) Capable() bool { return a.probeOK.Load() }

// Wait blocks until every read this agent owns has written its result.
func (a *Agent) Wait() { a.reads.Wait() }

func (a *Agent) now() time.Time { return a.cfg.Now().UTC() }

func (a *Agent) logf(format string, args ...any) { a.cfg.Logf(format, args...) }

func (a *Agent) decide(id string) {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.decided[id] = a.now()
}

func (a *Agent) isDecided(id string) bool {
	a.mu.Lock()
	defer a.mu.Unlock()
	_, ok := a.decided[id]
	return ok
}

// prune forgets decisions older than any listing can show again.
func (a *Agent) prune(now time.Time) {
	a.mu.Lock()
	defer a.mu.Unlock()
	for id, at := range a.decided {
		if now.Sub(at) > 2*time.Hour {
			delete(a.decided, id)
		}
	}
}

// askProbe asks the loop for a probe now: a read's worker failed to start
// (spec §7.1).
func (a *Agent) askProbe() {
	select {
	case a.probeAfter <- struct{}{}:
	default:
	}
}

// closeThenProbe gives the failed worker's connection slot back before
// asking for a probe, so admission sees the worker's unit as the orphan it
// now is and holds the probe until the unit has stopped (plan review
// finding 29). The deferred Close that follows is a no-op (countedConn).
func closeThenProbe(a *Agent, conn net.Conn) {
	conn.Close()
	a.askProbe()
}

// countedConn gives a worker connection's slot back exactly once.
type countedConn struct {
	net.Conn
	once sync.Once
	adm  *admission
}

func (c *countedConn) Close() error {
	err := c.Conn.Close()
	c.once.Do(c.adm.closed)
	return err
}

// dial opens a worker connection inside the three the socket allows.
func (a *Agent) dial(ctx context.Context) (net.Conn, error) {
	if !a.adm.opened() {
		return nil, errBusy
	}
	c, err := a.cfg.DialWorker(ctx)
	if err != nil {
		a.adm.closed()
		return nil, err
	}
	return &countedConn{Conn: c, adm: a.adm}, nil
}

// check is one half of the identity bracket (spec §8.2): the record read
// fresh, and refused unless it is the instance the envelope named, still a
// replicated instance, still in this box's region and not moving. A class,
// pool or fleet change after the console admitted the read is a record
// change.
func (a *Agent) check(ctx context.Context, req Request) (provision.Record, string, error) {
	rec, err := provision.GetRecord(ctx, a.cfg.Store, req.Account, req.App, req.Host)
	if errors.Is(err, os.ErrNotExist) {
		return provision.Record{}, CodeRecordChanged, nil
	}
	if err != nil {
		return provision.Record{}, "", err
	}
	inc, ierr := hostclaim.Incarnation(rec.Account, rec.App, rec.Host, rec.CreatedAt)
	_, fleet := registry.FleetPlacement(rec.Region)
	switch {
	case ierr != nil, inc != req.Incarnation, rec.Account != req.Account, rec.App != req.App,
		rec.Host != req.Host, !provision.ValidHostShape(rec.Host), ClassRefusal(*rec) != "",
		rec.Pool != "", fleet, rec.Region != a.cfg.Region:
		return *rec, CodeRecordChanged, nil
	case rec.Move != nil:
		return *rec, CodeMoving, nil
	}
	return *rec, "", nil
}

func nonce() string {
	var b [16]byte
	rand.Read(b[:])
	return hex.EncodeToString(b[:])
}

// elect is J3: the first create of picked owns the read. A create that
// answers an error or a conflict is decided by reading picked back: this
// agent's own nonce owns it, anything else, or a read that fails, does not.
func (a *Agent) elect(ctx context.Context, id string) (Picked, bool) {
	p := Picked{Box: a.cfg.Box, Boot: a.cfg.Boot, Nonce: nonce(), Deadline: a.now().Add(a.cfg.OwnerDeadline)}
	body, err := json.Marshal(p)
	if err != nil {
		return Picked{}, false
	}
	if _, err := a.cfg.Store.Put(ctx, PickedKey(id), body, ""); err == nil {
		return p, true
	}
	raw, _, err := a.cfg.Store.Get(ctx, PickedKey(id))
	if err != nil {
		return Picked{}, false
	}
	var got Picked
	if json.Unmarshal(raw, &got) != nil || got.Nonce != p.Nonce {
		return Picked{}, false
	}
	return got, true
}

// consider decides one in-window queue entry (spec §5.5 step 4): read and
// verify the request against its entry, check admission, wait the jitter,
// and enter the election. A refused or forged request is decided, and so
// logged once. A read that fails admission is not decided: a later pass may
// admit it while the window lasts.
func (a *Agent) consider(ctx context.Context, e QueueEntry) {
	raw, _, err := a.cfg.Store.Get(ctx, RequestKey(e.ID))
	if err != nil {
		if errors.Is(err, os.ErrNotExist) {
			a.decide(e.ID)
			a.logf("dbreads: %s: a queue entry with no request; ignored", e.ID)
		}
		return
	}
	req, err := Verify(a.cfg.Pub, raw, e.ID, a.cfg.Region, a.now())
	if err == nil && !QueueMatches(e, req) {
		err = ErrEnvelope
	}
	if err != nil {
		a.decide(e.ID)
		a.logf("dbreads: %s: refused the request: %v", e.ID, err)
		return
	}
	// A request whose console has already given up (its request ended
	// before it was announced) is never picked (spec §5.5 step 4).
	if _, _, err := a.cfg.Store.Get(ctx, CancelKey(e.ID)); err == nil {
		a.decide(e.ID)
		return
	}
	// A draining box does not enter the election (spec §7.1, D2).
	if a.cfg.Draining() {
		return
	}
	if err := a.adm.admitRead(ctx, e.ID); err != nil {
		return
	}
	if d := a.cfg.Jitter(); d > 0 {
		select {
		case <-ctx.Done():
			a.adm.abandon(e.ID)
			return
		case <-time.After(d):
		}
	}
	// It may have started draining during the jitter.
	if a.cfg.Draining() {
		a.adm.abandon(e.ID)
		return
	}
	p, owned := a.elect(ctx, e.ID)
	a.decide(e.ID)
	if !owned {
		a.adm.abandon(e.ID)
		return
	}
	a.reads.Add(1)
	go a.serve(ctx, req, p)
}
```

`serve` is Task 11's. Until Task 11 lands, add a temporary stub at the end of `agent.go` so this task builds, and delete it in Task 11:

```go
// serve is Task 11's.
func (a *Agent) serve(_ context.Context, req Request, _ Picked) {
	defer a.reads.Done()
	defer a.adm.finish(req.ID)
}
```

- [ ] **Step 6: Run the tests**

Run: `go test ./internal/dbreads/ -run 'TestCheck|TestElection' -count=1 -race && go test ./internal/console/ -run 'TestResolveReplica|TestDBClass|TestAPIDB' -count=1`
Expected: PASS.

- [ ] **Step 7: Commit**

```bash
git add internal/dbreads/class.go internal/dbreads/agent.go internal/dbreads/fixture_test.go internal/dbreads/agent_test.go internal/console/apidb.go
git commit -m "dbreads: the identity check, the create-only election with read-back, ClassRefusal moved"
```

---

### Task 11: One owned read: the bracket, the worker, the sealed output, the result

**Files:**
- Create: `internal/dbreads/read.go`
- Create: `internal/dbreads/chunks.go`
- Create: `internal/dbreads/read_test.go`
- Modify: `internal/dbreads/agent.go` (delete Task 10's `serve` stub)

**Interfaces:**
- Consumes: `check`, `elect`, `dial`, `askProbe`, `adm` (Task 10), `dbdoor.PlanFrom` and its errors (Task 6), the frames (Task 7), `SealChunk`, `SealSummary` (Task 5), `activator.HibernatePrefix`.
- Produces: `(*Agent).serve(ctx, req Request, p Picked)`; `read(ctx, req) Result`; `attempt(ctx, req, pub, at) (Result, bool)`; `sendFile(ctx, w io.Writer, rd dbdoor.ReplicaReader, f dbdoor.LTXFile) (vanished bool, err error)`; `relay(conn net.Conn, cw *chunkWriter) (code, sqlErr string, err error)`; `newChunkWriter(ctx, store, id string, pub *ecdh.PublicKey, stream string, every time.Duration, max int64) *chunkWriter`; `(*chunkWriter).Write`, `.close() (lastSeq, bytes int64, sha string, err error)`, `.capped() bool`; `putCreateOnly(ctx, s release.Store, key string, body []byte) error`; `errCapped`.

- [ ] **Step 1: Write the failing tests**

Create `internal/dbreads/read_test.go`. The in-process worker makes these unit tests, not acceptance.

```go
package dbreads

import (
	"bytes"
	"context"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"io"
	"os"
	"strings"
	"sync"
	"sync/atomic"
	"testing"
	"time"

	"github.com/benbjohnson/litestream"
	lsfile "github.com/benbjohnson/litestream/file"
	"github.com/superfly/ltx"

	"github.com/carlosframework/platform/internal/dbdoor"
	"github.com/carlosframework/platform/internal/provision"
	"github.com/carlosframework/platform/internal/release"
)

func serveOne(t *testing.T, a *Agent, fx *fixture, req Request) ([]byte, Summary, Result) {
	t.Helper()
	e := fx.submit(req)
	a.consider(context.Background(), e)
	a.Wait()
	return fx.answer(req.ID)
}

func TestReadServesAQuery(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 3)
	a, w := fx.agent("uk-1")
	rows, s, r := serveOne(t, a, fx, fx.request("SELECT count(*) AS n FROM t", ""))
	if r.State != StateDone || r.Code != "" || string(rows) != "n\n30\n" || r.Box != "uk-1" {
		t.Fatalf("result %+v, rows %q", r, rows)
	}
	plan, err := dbdoor.PlanFrom(context.Background(), lsfile.NewReplicaClient(fx.replica), time.Time{})
	if err != nil || s.TXID != plan.TXID || !s.At.Equal(plan.At) {
		t.Fatalf("summary %+v, plan %+v %v", s, plan, err)
	}
	if w.dials.Load() != 1 {
		t.Fatalf("%d worker connections for one read", w.dials.Load())
	}
}

// vanishing makes full-file opens of the first planned file answer
// os.ErrNotExist, `times` times: litestream's compaction removing an L0
// file under the plan.
type vanishing struct {
	dbdoor.ReplicaReader
	mu    sync.Mutex
	times int
}

func (v *vanishing) OpenLTXFile(ctx context.Context, level int, lo, hi ltx.TXID, off, size int64) (io.ReadCloser, error) {
	v.mu.Lock()
	gone := off == 0 && size == 0 && v.times > 0
	if gone {
		v.times--
	}
	v.mu.Unlock()
	if gone {
		return nil, os.ErrNotExist
	}
	return v.ReplicaReader.OpenLTXFile(ctx, level, lo, hi, off, size)
}

// Review Focus 3: one quiet re-plan, then changed-twice, and no chunk.
func TestReadRePlansOnceThenSaysChangedTwice(t *testing.T) {
	t.Parallel()
	for _, c := range []struct {
		times int
		want  string
	}{{1, ""}, {2, CodeChangedTwice}} {
		fx := newFixture(t, 2)
		v := &vanishing{ReplicaReader: lsfile.NewReplicaClient(fx.replica), times: c.times}
		a, _ := fx.agent("uk-1", func(cfg *AgentConfig, _ *inProcWorkers) {
			cfg.OpenReplica = func(context.Context, string) (dbdoor.ReplicaReader, error) { return v, nil }
		})
		req := fx.request("SELECT count(*) FROM t", "")
		_, _, r := serveOne(t, a, fx, req)
		if r.Code != c.want {
			t.Fatalf("vanished %d times: %+v", c.times, r)
		}
		if c.want != "" && len(fx.chunkKeys(req.ID)) != 0 {
			t.Fatal("a chunk exists for a read that never ran")
		}
	}
}

// Plan review finding 10: after a vanished file, the retry waits for the
// first worker's unit to stop before it dials again, and keeps that unit's
// reservation until then. 12 GiB of 20 fits one floor at a time.
// Mutations: drop the settle call in read (the second dial sees a live unit,
// and the retired floor makes the new one no-room); or drop retry's move of
// the old reservation (TestAdmissionRetryHoldsTheOldReservation goes red).
func TestRetryWaitsForTheFirstWorkerToStop(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 2)
	v := &vanishing{ReplicaReader: lsfile.NewReplicaClient(fx.replica), times: 1}
	a, w := fx.agent("uk-1", func(c *AgentConfig, w *inProcWorkers) {
		c.OpenReplica = func(context.Context, string) (dbdoor.ReplicaReader, error) { return v, nil }
		c.Free = func() (uint64, uint64, error) { return 12 << 30, 20 << 30, nil }
		w.linger = 300 * time.Millisecond
	})
	_, _, r := serveOne(t, a, fx, fx.request("SELECT count(*) FROM t", ""))
	if r.State != StateDone {
		t.Fatalf("result %+v", r)
	}
	w.mu.Lock()
	defer w.mu.Unlock()
	if len(w.liveAtDial) != 2 || w.liveAtDial[1] != 0 {
		t.Fatalf("live units at each dial: %v; the retry dialed beside the first worker", w.liveAtDial)
	}
}

// Plan review finding 15: a worker that ends before ready (its service
// failed after the socket accepted) asks for a probe at once. Mutation:
// drop the askProbe after a pre-ready sendFile or readFrame failure;
// probeAfter stays empty and this test is red.
func TestAWorkerThatNeverStartsAsksForAProbe(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	a, _ := fx.agent("uk-1", func(_ *AgentConfig, w *inProcWorkers) { w.failStart.Store(true) })
	_, _, r := serveOne(t, a, fx, fx.request("SELECT 1", ""))
	if r.Code != CodeInterrupted || len(a.probeAfter) != 1 {
		t.Fatalf("result %+v, probe asked %d", r, len(a.probeAfter))
	}
}

// stageHook changes the record at one stage of the read: planning (the
// first listing), download (the first full-file open), or after the last
// byte has been read from the bucket (EOF of the last planned file).
type stageHook struct {
	dbdoor.ReplicaReader
	stage, lastSpan string
	once            sync.Once
	change          func()
}

func (h *stageHook) LTXFiles(ctx context.Context, level int, seek ltx.TXID, m bool) (ltx.FileIterator, error) {
	if h.stage == "planning" {
		h.once.Do(h.change)
	}
	return h.ReplicaReader.LTXFiles(ctx, level, seek, m)
}

func (h *stageHook) OpenLTXFile(ctx context.Context, level int, lo, hi ltx.TXID, off, size int64) (io.ReadCloser, error) {
	rc, err := h.ReplicaReader.OpenLTXFile(ctx, level, lo, hi, off, size)
	if err != nil || off != 0 || size != 0 {
		return rc, err
	}
	switch {
	case h.stage == "download":
		h.once.Do(h.change)
	case h.stage == "after the last byte" && dbdoor.Span(uint64(lo), uint64(hi)) == h.lastSpan:
		return &eofHook{ReadCloser: rc, at: func() { h.once.Do(h.change) }}, nil
	}
	return rc, nil
}

type eofHook struct {
	io.ReadCloser
	at func()
}

func (e *eofHook) Read(p []byte) (int, error) {
	n, err := e.ReadCloser.Read(p)
	if err == io.EOF {
		e.at()
	}
	return n, err
}

// T9: a record change at every stage ends with its code, and no chunk is
// ever written (codex 1).
func TestRecordChangeAtEveryStageWritesNoChunk(t *testing.T) {
	t.Parallel()
	no := false
	changes := map[string]struct {
		change func(fx *fixture)
		want   string
	}{
		"moved":                       {func(fx *fixture) { r := fx.record(); r.Region = "ie"; fx.putRecord(r) }, CodeRecordChanged},
		"moving":                      {func(fx *fixture) { r := fx.record(); r.Move = &provision.MoveState{ID: "mv_x", To: "ie", State: "requested"}; fx.putRecord(r) }, CodeMoving},
		"recreated in the account":    {func(fx *fixture) { r := fx.record(); r.CreatedAt = r.CreatedAt.Add(time.Hour); fx.putRecord(r) }, CodeRecordChanged},
		"recreated in another account": {func(fx *fixture) {
			created := fx.record().CreatedAt
			fx.store.Delete(context.Background(), provision.RecordKey(fxAccount, fxApp, fxHost))
			fx.putRecordUnder("bac", provision.Record{Region: "uk", CreatedAt: created})
		}, CodeRecordChanged},
		"class changed": {func(fx *fixture) { r := fx.record(); r.Hibernate = &no; fx.putRecord(r) }, CodeRecordChanged},
	}
	for _, stage := range []string{"before the pick", "planning", "download", "after the last byte"} {
		for name, c := range changes {
			t.Run(stage+"/"+name, func(t *testing.T) {
				t.Parallel()
				fx := newFixture(t, 2)
				plan, err := dbdoor.PlanFrom(context.Background(), lsfile.NewReplicaClient(fx.replica), time.Time{})
				if err != nil {
					t.Fatal(err)
				}
				last := plan.Planned[len(plan.Planned)-1]
				hook := &stageHook{ReplicaReader: lsfile.NewReplicaClient(fx.replica), stage: stage,
					lastSpan: dbdoor.Span(last.MinTXID, last.MaxTXID), change: func() { c.change(fx) }}
				a, _ := fx.agent("uk-1", func(cfg *AgentConfig, _ *inProcWorkers) {
					cfg.OpenReplica = func(context.Context, string) (dbdoor.ReplicaReader, error) { return hook, nil }
				})
				req := fx.request("SELECT count(*) FROM t", "")
				if stage == "before the pick" {
					c.change(fx)
				}
				_, _, r := serveOne(t, a, fx, req)
				if r.State != StateRefused || r.Code != c.want {
					t.Fatalf("result %+v, want refused %s", r, c.want)
				}
				if keys := fx.chunkKeys(req.ID); len(keys) != 0 {
					t.Fatalf("chunks written: %v", keys)
				}
			})
		}
	}
}

func TestReadTooLargeAndNoRoom(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 2)
	a, _ := fx.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) { c.MaxRestored = 1024 })
	_, s, r := serveOne(t, a, fx, fx.request("SELECT 1", ""))
	if r.Code != CodeTooLarge || s.Cap != 1024 || s.Restored <= 1024 {
		t.Fatalf("too large: %+v %+v", r, s)
	}
	fx2 := newFixture(t, 2)
	b, _ := fx2.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) {
		calls := 0
		c.Free = func() (uint64, uint64, error) {
			calls++
			if calls == 1 { // the floor fits; the plan's growth does not
				return 11 << 30, 20 << 30, nil
			}
			return 5<<30 + 1, 20 << 30, nil
		}
	})
	_, _, r2 := serveOne(t, b, fx2, fx2.request("SELECT 1", ""))
	if r2.Code != CodeNoRoom {
		t.Fatalf("no room: %+v", r2)
	}
}

// Review Focus 4: the cap is exact, a row bigger than a chunk is split, and
// the summary covers exactly the kept bytes.
func TestChunkWriterCapIsExact(t *testing.T) {
	t.Parallel()
	for _, extra := range []int{0, 1} {
		fx := newFixture(t, 0)
		max := int64(3*ChunkBytes + 7)
		cw := newChunkWriter(context.Background(), fx.store, "dbr_aaaaaaaaaaaaaaaaaaaaaaaaaa", fx.reply.PublicKey(), StreamRows, time.Hour, max)
		big := bytes.Repeat([]byte("x"), 2*ChunkBytes+5)
		rest := bytes.Repeat([]byte("y"), int(max)-len(big)+extra)
		cw.Write(big)
		_, err := cw.Write(rest)
		if (extra == 1) != (err == errCapped) || cw.capped() != (extra == 1) {
			t.Fatalf("extra %d: Write = %v, capped %v", extra, err, cw.capped())
		}
		last, n, sum, err := cw.close()
		if err != nil || n != max {
			t.Fatalf("extra %d: kept %d of %d: %v", extra, n, max, err)
		}
		want := sha256.Sum256(append(append([]byte{}, big...), rest[:int(max)-len(big)]...))
		if sum != hex.EncodeToString(want[:]) {
			t.Fatal("the summary hash is not the kept bytes'")
		}
		for seq := int64(1); seq <= last; seq++ {
			sealed, _, err := fx.store.Get(context.Background(), ChunkKey("dbr_aaaaaaaaaaaaaaaaaaaaaaaaaa", seq))
			if err != nil || len(sealed)-SealOverhead > ChunkBytes {
				t.Fatalf("chunk %d: %d bytes, %v", seq, len(sealed), err)
			}
		}
	}
}

// The output cap end to end: done, output-cap, and exactly the cap kept.
func TestReadOutputCap(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 2)
	a, _ := fx.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) { c.MaxOutput = 100 })
	rows, s, r := serveOne(t, a, fx, fx.request("SELECT body FROM t", ""))
	if r.State != StateDone || r.Code != CodeOutputCap || len(rows) != 100 || s.Bytes != 100 {
		t.Fatalf("result %+v, %d bytes", r, len(rows))
	}
}

func TestCancelStopsTheOwner(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 2)
	hang := make(chan struct{})
	t.Cleanup(func() { close(hang) })
	a, _ := fx.agent("uk-1", func(c *AgentConfig, w *inProcWorkers) {
		c.CancelEvery = 20 * time.Millisecond
		w.opt.Restore = func(ctx context.Context, _ litestream.ReplicaClient, _ string, _ uint64) error {
			select {
			case <-ctx.Done():
			case <-hang:
			}
			return ctx.Err()
		}
	})
	req := fx.request("SELECT 1", "")
	e := fx.submit(req)
	a.consider(context.Background(), e)
	if _, err := fx.store.Put(context.Background(), CancelKey(req.ID), nil, ""); err != nil {
		t.Fatal(err)
	}
	done := make(chan struct{})
	go func() { a.Wait(); close(done) }()
	select {
	case <-done:
	case <-time.After(5 * time.Second):
		t.Fatal("the owner did not stop within 5 s of cancel")
	}
	if _, _, r := fx.answer(req.ID); r.State != StateCancelled {
		t.Fatalf("result %+v", r)
	}
}

// refusedChunk never lets one chunk's create land: every attempt answers an
// error and the object stays absent.
type refusedChunk struct {
	release.Store
	key string
}

func (s refusedChunk) Put(ctx context.Context, key string, body []byte, ifMatch string) (string, error) {
	if key == s.key {
		return "", errors.New("connection reset")
	}
	return s.Store.Put(ctx, key, body, ifMatch)
}

// Plan review finding 9: a chunk that is never confirmed is never named by
// the result. The read ends interrupted, and every chunk through its
// last_seq exists. Mutation: flushLocked increments seq before the create is
// confirmed; the result then names chunk 2 and this test is red.
func TestResultNamesOnlyConfirmedChunks(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	req := fx.request("SELECT hex(randomblob(300000))", "") // about 600 KB: three chunks
	a, _ := fx.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) {
		c.Store = refusedChunk{Store: fx.store, key: ChunkKey(req.ID, 2)}
		c.OwnerDeadline = 2 * time.Second
	})
	a.consider(context.Background(), fx.submit(req))
	a.Wait()
	raw, _, err := fx.store.Get(context.Background(), ResultKey(req.ID))
	if err != nil {
		t.Fatal(err)
	}
	var r Result
	json.Unmarshal(raw, &r)
	if r.State != StateFailed || r.Code != CodeInterrupted || r.LastSeq != 1 {
		t.Fatalf("result %+v", r)
	}
	for seq := int64(1); seq <= r.LastSeq; seq++ {
		if _, _, err := fx.store.Get(context.Background(), ChunkKey(req.ID, seq)); err != nil {
			t.Fatalf("the result names chunk %d, which does not exist", seq)
		}
	}
}

// strictStore fails the test on any protocol delete or replacing write
// under db-reads/ (T16, the box's half).
type strictStore struct {
	release.Store
	t *testing.T
}

func (s strictStore) Put(ctx context.Context, key string, body []byte, ifMatch string) (string, error) {
	if strings.HasPrefix(key, Prefix) && ifMatch != "" {
		s.t.Errorf("a replacing write of %s", key)
	}
	return s.Store.Put(ctx, key, body, ifMatch)
}

func (s strictStore) Delete(ctx context.Context, key string) error {
	if strings.HasPrefix(key, Prefix) {
		s.t.Errorf("a delete of %s", key)
	}
	return s.Store.Delete(ctx, key)
}

func TestReadNeverDeletesOrReplaces(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 2)
	a, _ := fx.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) { c.Store = strictStore{Store: fx.store, t: t} })
	if _, _, r := serveOne(t, a, fx, fx.request("SELECT count(*) FROM t", "")); r.State != StateDone {
		t.Fatalf("%+v", r)
	}
}

func TestOwnerDeadlineEndsAHungRead(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	var started atomic.Bool
	a, _ := fx.agent("uk-1", func(c *AgentConfig, w *inProcWorkers) {
		c.OwnerDeadline = 200 * time.Millisecond
		w.opt.Restore = func(ctx context.Context, _ litestream.ReplicaClient, _ string, _ uint64) error {
			started.Store(true)
			<-ctx.Done()
			return ctx.Err()
		}
	})
	_, _, r := serveOne(t, a, fx, fx.request("SELECT 1", ""))
	if !started.Load() || r.State != StateFailed || r.Code != CodeInterrupted {
		t.Fatalf("result %+v", r)
	}
}
```

- [ ] **Step 2: Run them to verify they fail**

Run: `go test ./internal/dbreads/ -run 'TestRead|TestRecordChange|TestChunkWriter|TestCancel|TestOwnerDeadline' -count=1`
Expected: FAIL, `newChunkWriter` undefined and the stub `serve` writes no result.

- [ ] **Step 3: Write `chunks.go`**

```go
package dbreads

import (
	"bytes"
	"context"
	"crypto/ecdh"
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"
	"hash"
	"sync"
	"time"

	"github.com/carlosframework/platform/internal/release"
)

var errCapped = errors.New("dbreads: the output cap was reached")

// putCreateOnly creates key with body, retrying until it lands or ctx ends.
// An error or a conflict is resolved by reading the key back: the same
// bytes mean an earlier attempt landed (spec §5.4). The caller keeps body
// until this returns, so a retry is the same bytes.
func putCreateOnly(ctx context.Context, s release.Store, key string, body []byte) error {
	wait := 250 * time.Millisecond
	for {
		_, err := s.Put(ctx, key, body, "")
		if err == nil {
			return nil
		}
		got, _, gerr := s.Get(ctx, key)
		switch {
		case gerr == nil && bytes.Equal(got, body):
			return nil
		case gerr == nil:
			return fmt.Errorf("dbreads: %s holds other bytes: %w", key, release.ErrCASConflict)
		}
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-time.After(wait):
		}
		wait = min(wait*2, 5*time.Second)
	}
}

// chunkWriter seals a read's output into out/<seq> objects: one every
// ChunkBytes, and whatever is pending every `every`; close seals what is
// left, possibly nothing, as the last chunk. Past max nothing more is kept
// and Write answers errCapped. Each put is create-only and confirmed before
// the next is sealed, under the lock, so seqs are in order (the run
// chunker's discipline).
type chunkWriter struct {
	ctx    context.Context
	store  release.Store
	id     string
	pub    *ecdh.PublicKey
	stream string
	max    int64

	mu       sync.Mutex
	pending  []byte
	seq      int64
	total    int64
	sum      hash.Hash
	err      error
	isCapped bool

	stop chan struct{}
	done chan struct{}
}

func newChunkWriter(ctx context.Context, s release.Store, id string, pub *ecdh.PublicKey, stream string, every time.Duration, max int64) *chunkWriter {
	c := &chunkWriter{ctx: ctx, store: s, id: id, pub: pub, stream: stream, max: max, sum: sha256.New(),
		stop: make(chan struct{}), done: make(chan struct{})}
	go c.tick(every)
	return c
}

func (c *chunkWriter) tick(every time.Duration) {
	defer close(c.done)
	t := time.NewTicker(every)
	defer t.Stop()
	for {
		select {
		case <-c.stop:
			return
		case <-t.C:
			c.mu.Lock()
			if len(c.pending) > 0 && c.err == nil {
				c.err = c.flushLocked(c.pending, false)
				c.pending = nil
			}
			c.mu.Unlock()
		}
	}
}

func (c *chunkWriter) Write(p []byte) (int, error) {
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.err != nil {
		return 0, c.err
	}
	if c.isCapped {
		return 0, errCapped
	}
	capped := false
	if room := c.max - c.total; int64(len(p)) > room {
		p, capped = p[:room], true
	}
	c.sum.Write(p)
	c.total += int64(len(p))
	c.pending = append(c.pending, p...)
	for len(c.pending) >= ChunkBytes {
		if err := c.flushLocked(c.pending[:ChunkBytes], false); err != nil {
			c.err = err
			return 0, err
		}
		c.pending = append([]byte(nil), c.pending[ChunkBytes:]...)
	}
	if capped {
		c.isCapped = true
		return len(p), errCapped
	}
	return len(p), nil
}

// flushLocked seals and creates the next chunk. seq moves only once the
// create is confirmed, so close never reports, and no result ever names, a
// chunk that was not confirmed (spec §5.4; plan review finding 9). A chunk
// whose create stayed ambiguous until the context ended may land later at
// seq+1; no result names it, so no reader relays it.
func (c *chunkWriter) flushLocked(b []byte, last bool) error {
	next := c.seq + 1
	sealed, err := SealChunk(c.pub, c.id, next, c.stream, last, b)
	if err != nil {
		return err
	}
	if err := putCreateOnly(c.ctx, c.store, ChunkKey(c.id, next), sealed); err != nil {
		return err
	}
	c.seq = next
	return nil
}

func (c *chunkWriter) capped() bool {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.isCapped
}

// close seals the pending bytes as the last chunk and reports the last seq,
// the plaintext byte count and its SHA-256.
func (c *chunkWriter) close() (int64, int64, string, error) {
	close(c.stop)
	<-c.done
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.err == nil {
		c.err = c.flushLocked(c.pending, true)
		c.pending = nil
	}
	return c.seq, c.total, hex.EncodeToString(c.sum.Sum(nil)), c.err
}
```

- [ ] **Step 4: Write `read.go`**

```go
package dbreads

import (
	"context"
	"crypto/ecdh"
	"encoding/json"
	"errors"
	"io"
	"net"
	"os"
	"sync/atomic"
	"time"

	"github.com/superfly/ltx"

	"github.com/carlosframework/platform/internal/activator"
	"github.com/carlosframework/platform/internal/dbdoor"
)

// serve runs one read this agent owns, inside the owner's deadline, and
// writes its result (spec §5.5 step 5). The read slot is given back here;
// the reservation stays until the worker unit is gone (J5).
func (a *Agent) serve(parent context.Context, req Request, p Picked) {
	defer a.reads.Done()
	defer a.adm.finish(req.ID)
	ctx, cancel := context.WithTimeout(parent, a.cfg.OwnerDeadline)
	defer cancel()
	var cancelled atomic.Bool
	go a.watchCancel(ctx, req.ID, cancel, &cancelled)
	started := a.now()
	res := a.read(ctx, req)
	if cancelled.Load() {
		res.State, res.Code = StateCancelled, ""
	}
	res.Box, res.Started, res.Ended = a.cfg.Box, started, a.now()
	body, err := json.Marshal(res)
	if err == nil {
		wctx, wcancel := context.WithTimeout(context.WithoutCancel(parent), 30*time.Second)
		err = putCreateOnly(wctx, a.cfg.Store, ResultKey(req.ID), body)
		wcancel()
	}
	if err != nil {
		a.logf("dbreads: %s: write the result: %v", req.ID, err)
	}
}

// watchCancel reads cancel every CancelEvery and ends the read when it
// appears: the console's best-effort word that nobody is waiting.
func (a *Agent) watchCancel(ctx context.Context, id string, cancel context.CancelFunc, seen *atomic.Bool) {
	t := time.NewTicker(a.cfg.CancelEvery)
	defer t.Stop()
	for {
		select {
		case <-ctx.Done():
			return
		case <-t.C:
			if _, _, err := a.cfg.Store.Get(ctx, CancelKey(id)); err == nil {
				seen.Store(true)
				cancel()
				return
			}
		}
	}
}

// ended seals the summary into a result.
func (a *Agent) ended(pub *ecdh.PublicKey, id, state, code string, s Summary, last int64) Result {
	sealed, err := SealSummary(pub, id, s)
	if err != nil {
		a.logf("dbreads: %s: seal the summary: %v", id, err)
	}
	return Result{State: state, Code: code, LastSeq: last, Sealed: sealed}
}

// read is today's "changed while it was being read" retry, box side: one
// fresh plan, with both checks again, then changed-twice.
func (a *Agent) read(ctx context.Context, req Request) Result {
	pub, err := ParseReplyKey(req.ReplyKey)
	if err != nil {
		return Result{State: StateFailed, Code: CodeInterrupted}
	}
	at, _ := req.AtTime()
	for attempt := 0; attempt < 2; attempt++ {
		if attempt > 0 {
			// The first attempt's worker may still be stopping: keep its
			// reservation, and wait for its unit before the next one (J5).
			a.adm.retry(req.ID, attempt)
			if err := a.adm.settle(ctx, settlePoll); err != nil {
				return a.ended(pub, req.ID, StateFailed, CodeInterrupted, Summary{}, 0)
			}
		}
		if res, retry := a.attempt(ctx, req, pub, at); !retry {
			return res
		}
	}
	return a.ended(pub, req.ID, StateFailed, CodeChangedTwice, Summary{}, 0)
}

// settlePoll is how often a retry rereads the unit listing while it waits.
var settlePoll = 200 * time.Millisecond

// attempt is the identity bracket (spec §8.2): check A, plan, stream every
// planned file into a worker that restores and checks it, check B after the
// last byte has left the bucket, and only then run. No output exists before
// check B passes. retry is true when a planned file vanished or changed.
func (a *Agent) attempt(ctx context.Context, req Request, pub *ecdh.PublicKey, at time.Time) (Result, bool) {
	fail := func(code string, s Summary) (Result, bool) {
		return a.ended(pub, req.ID, StateFailed, code, s, 0), false
	}
	refuse := func(code string) (Result, bool) {
		return a.ended(pub, req.ID, StateRefused, code, Summary{}, 0), false
	}
	attemptStart := time.Now()
	pctx, pcancel := context.WithTimeout(ctx, a.cfg.PlanBudget)
	defer pcancel()

	rec, code, err := a.check(pctx, req) // check A
	if err != nil {
		a.logf("dbreads: %s: check A: %v", req.ID, err)
		return fail(CodeInterrupted, Summary{})
	}
	if code != "" {
		return refuse(code)
	}
	rd, err := a.cfg.OpenReplica(pctx, activator.HibernatePrefix(a.cfg.HibernatePrefix, rec.Host))
	if err != nil {
		a.logf("dbreads: %s: open the replica: %v", req.ID, err)
		return fail(CodeInterrupted, Summary{})
	}
	plan, err := dbdoor.PlanFrom(pctx, rd, at)
	var before *dbdoor.BeforeHistoryError
	switch {
	case errors.Is(err, dbdoor.ErrNothingReplicated):
		return fail(CodeNothingReplicated, Summary{})
	case errors.As(err, &before):
		return fail(CodeHistoryGone, Summary{Oldest: before.Oldest})
	case errors.Is(err, dbdoor.ErrHistoryGone):
		return fail(CodeHistoryGone, Summary{})
	case errors.Is(err, os.ErrNotExist):
		return Result{}, true
	case err != nil:
		a.logf("dbreads: %s: plan: %v", req.ID, err)
		return fail(CodeInterrupted, Summary{})
	}
	if plan.RestoredBytes > a.cfg.MaxRestored {
		return fail(CodeTooLarge, Summary{Restored: plan.RestoredBytes, Cap: a.cfg.MaxRestored})
	}
	if err := a.adm.grow(req.ID, plan.LTXBytes+plan.RestoredBytes); err != nil {
		return fail(CodeNoRoom, Summary{})
	}
	conn, err := a.dial(pctx)
	if err != nil {
		a.logf("dbreads: %s: the worker did not start: %v", req.ID, err)
		a.askProbe()
		return fail(CodeInterrupted, Summary{})
	}
	defer conn.Close()
	defer context.AfterFunc(ctx, func() { conn.Close() })()
	stopPlanBound := context.AfterFunc(pctx, func() { conn.Close() })
	defer stopPlanBound()

	if err := writeJSONFrame(conn, frameHeader, planHeader{V: ProtocolVersion, Op: req.Op, Files: plan.Planned,
		Target: plan.TXID, MaxRestored: a.cfg.MaxRestored}); err != nil {
		closeThenProbe(a, conn)
		return fail(CodeInterrupted, Summary{})
	}
	for _, f := range plan.Planned {
		vanished, err := sendFile(pctx, conn, rd, f)
		if vanished {
			return Result{}, true
		}
		if err != nil {
			// The worker went before ready: its unit may have failed to
			// start after the socket accepted (spec §7.1; plan review
			// finding 15). Probe once this connection is closed.
			closeThenProbe(a, conn)
			return fail(CodeInterrupted, Summary{})
		}
	}
	typ, p, err := readFrame(conn)
	switch {
	case err != nil:
		closeThenProbe(a, conn)
		return fail(CodeInterrupted, Summary{})
	case typ == frameEnd:
		var e endMsg
		json.Unmarshal(p, &e)
		if e.Code != CodeTooLarge {
			e.Code = CodeCheckFailed
		}
		return fail(e.Code, Summary{Error: e.Error, Restored: plan.RestoredBytes, Cap: a.cfg.MaxRestored})
	}
	var ready readyMsg
	if typ != frameReady || json.Unmarshal(p, &ready) != nil || ready.TXID != plan.TXID {
		return fail(CodeCheckFailed, Summary{})
	}
	if _, code, err := a.check(pctx, req); err != nil || code != "" { // check B
		writeFrame(conn, frameStop, nil)
		if err != nil {
			return fail(CodeInterrupted, Summary{})
		}
		return refuse(code)
	}
	stopPlanBound() // the query is bounded by the worker and the owner's deadline
	// Phase timings, for operators and for plan 3's throughput measurement:
	// planning and the worker's restore, then the output's sealing and
	// confirmed creates.
	a.logf("dbreads: %s: planned %d files (%d bytes) and restored to %d in %s", req.ID, plan.Files, plan.LTXBytes, plan.TXID, time.Since(attemptStart).Round(time.Millisecond))
	runStart := time.Now()
	if err := writeJSONFrame(conn, frameRun, runMsg{SQL: req.SQL}); err != nil {
		return fail(CodeInterrupted, Summary{})
	}
	cw := newChunkWriter(ctx, a.cfg.Store, req.ID, pub, StreamRows, a.cfg.ChunkEvery, a.cfg.MaxOutput)
	endCode, sqlErr, rerr := relay(conn, cw)
	last, n, sum, werr := cw.close()
	a.logf("dbreads: %s: output %d bytes in %d confirmed chunks in %s", req.ID, n, last, time.Since(runStart).Round(time.Millisecond))
	s := Summary{TXID: plan.TXID, At: plan.At, Bytes: n, SHA256: sum, Error: sqlErr}
	switch {
	case werr != nil:
		a.logf("dbreads: %s: write output: %v", req.ID, werr)
		return a.ended(pub, req.ID, StateFailed, CodeInterrupted, Summary{}, last), false
	case cw.capped():
		return a.ended(pub, req.ID, StateDone, CodeOutputCap, s, last), false
	case rerr != nil:
		return a.ended(pub, req.ID, StateFailed, CodeInterrupted, Summary{}, last), false
	case endCode == "":
		return a.ended(pub, req.ID, StateDone, "", s, last), false
	case endCode == CodeSQLError, endCode == CodeTimeout:
		return a.ended(pub, req.ID, StateFailed, endCode, s, last), false
	}
	return a.ended(pub, req.ID, StateFailed, CodeInterrupted, Summary{}, last), false
}

// sendFile streams one planned file, whole, from the bucket into the
// worker. A file that is gone, or not the size the plan listed, vanished
// under the plan: the caller re-plans.
func sendFile(ctx context.Context, w io.Writer, rd dbdoor.ReplicaReader, f dbdoor.LTXFile) (bool, error) {
	rc, err := rd.OpenLTXFile(ctx, f.Level, ltx.TXID(f.MinTXID), ltx.TXID(f.MaxTXID), 0, 0)
	if errors.Is(err, os.ErrNotExist) {
		return true, nil
	}
	if err != nil {
		return false, err
	}
	defer rc.Close()
	buf := make([]byte, fileFrameBytes)
	var sent int64
	for {
		n, rerr := rc.Read(buf)
		if n > 0 {
			if sent+int64(n) > f.Size {
				return true, nil
			}
			if err := writeFrame(w, frameFile, buf[:n]); err != nil {
				return false, err
			}
			sent += int64(n)
		}
		if rerr == io.EOF {
			break
		}
		if errors.Is(rerr, os.ErrNotExist) {
			return true, nil
		}
		if rerr != nil {
			return false, rerr
		}
	}
	return sent != f.Size, nil
}

// relay moves the worker's output into the chunk writer until the worker's
// end frame, or until the cap: then the agent stops reading and closes the
// connection, which the worker sees as EOF.
func relay(conn net.Conn, cw *chunkWriter) (string, string, error) {
	for {
		typ, p, err := readFrame(conn)
		if err != nil {
			return "", "", err
		}
		switch typ {
		case frameOutput:
			if _, err := cw.Write(p); errors.Is(err, errCapped) {
				return "", "", nil
			} else if err != nil {
				return "", "", err
			}
		case frameEnd:
			var e endMsg
			if json.Unmarshal(p, &e) != nil {
				return "", "", errProtocol
			}
			return e.Code, e.Error, nil
		default:
			return "", "", errProtocol
		}
	}
}
```

Delete the `serve` stub from `agent.go`.

- [ ] **Step 5: Run the tests**

Run: `go test ./internal/dbreads/ -count=1 -race`
Expected: PASS. The package is new and small; running it whole is the targeted run.

- [ ] **Step 6: Commit**

```bash
git add internal/dbreads
git commit -m "dbreads: the owned read, its identity bracket, sealed chunks and result"
```

---

### Task 12: The loop: listing the queue, the probe, the capability

**Files:**
- Modify: `internal/dbreads/agent.go` (add `Run`, `Pass`, `Probe`, `probe`)
- Create: `internal/dbreads/loop_test.go`

**Interfaces:**
- Consumes: `consider`, `decide`, `isDecided`, `prune`, `dial`, `adm.admitProbe` (Tasks 9, 10).
- Produces: `(*Agent).Run(ctx context.Context, nudge <-chan struct{})`; `(*Agent).Pass(ctx context.Context)`; `(*Agent).Probe(ctx context.Context) bool` (false when admission skipped it); `probeRetry`; `errSandbox`.

- [ ] **Step 1: Write the failing tests**

Create `internal/dbreads/loop_test.go`:

```go
package dbreads

import (
	"context"
	"errors"
	"net"
	"strings"
	"sync/atomic"
	"testing"
	"time"

	"github.com/benbjohnson/litestream"

	"github.com/carlosframework/platform/internal/release"
)

// countingStore counts reads of request objects and lists.
type countingStore struct {
	release.Store
	requestGets, lists atomic.Int64
}

func (s *countingStore) Get(ctx context.Context, key string) ([]byte, string, error) {
	if strings.HasSuffix(key, "/request.json") {
		s.requestGets.Add(1)
	}
	return s.Store.Get(ctx, key)
}

func (s *countingStore) List(ctx context.Context, prefix string) ([]string, error) {
	s.lists.Add(1)
	return s.Store.List(ctx, prefix)
}

// Review Focus 2: a request issued at 10:59:50 is listed at 11:00:20 under
// the previous hour's prefix, and picked.
func TestPassFindsAnEntryFromThePreviousHour(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	fx.now = time.Date(2026, 10, 22, 10, 59, 50, 0, time.UTC)
	a, _ := fx.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) {
		c.Now = func() time.Time { return time.Date(2026, 10, 22, 11, 0, 20, 0, time.UTC) }
	})
	req := fx.request("SELECT count(*) FROM t", "")
	fx.submit(req)
	a.Pass(context.Background())
	a.Wait()
	if _, _, r := fx.answer(req.ID); r.State != StateDone {
		t.Fatalf("%+v", r)
	}
}

func TestPassSkipsAnOutOfWindowEntryWithoutReadingIt(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 0)
	cs := &countingStore{Store: fx.store}
	fx.now = time.Now().UTC().Add(-3 * time.Minute).Truncate(time.Second)
	fx.submit(fx.request("SELECT 1", ""))
	a, _ := fx.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) { c.Store = cs })
	a.Pass(context.Background())
	if cs.requestGets.Load() != 0 {
		t.Fatal("an out-of-window request was read")
	}
}

// T4, the box's half: a forged queue entry and an unsigned request are
// refused, decided, and logged once.
func TestPassRefusesForgedEntriesAndUnsignedRequests(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	var logged atomic.Int64
	a, w := fx.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) {
		c.Logf = func(format string, args ...any) {
			if strings.Contains(format, "refused the request") {
				logged.Add(1)
			}
		}
	})
	forged := fx.request("SELECT 1", "")
	wire, _ := Sign(release.RootSigner(fx.rootPriv), forged)
	fx.store.Put(context.Background(), RequestKey(forged.ID), wire, "")
	issued, _ := forged.Issued()
	fx.store.Put(context.Background(), QueueKey("uk", issued.Add(-time.Second), forged.ID), nil, "")
	unsigned := fx.request("SELECT 1", "")
	fx.store.Put(context.Background(), RequestKey(unsigned.ID), []byte(`{"payload":"e30=","sig":""}`), "")
	fx.store.Put(context.Background(), QueueKey("uk", issued, unsigned.ID), nil, "")
	a.Pass(context.Background())
	a.Pass(context.Background())
	a.Wait()
	for _, id := range []string{forged.ID, unsigned.ID} {
		if _, _, err := fx.store.Get(context.Background(), PickedKey(id)); err == nil {
			t.Errorf("%s was picked", id)
		}
	}
	if logged.Load() != 2 || w.dials.Load() != 0 {
		t.Fatalf("logged %d refusals, dialed %d workers", logged.Load(), w.dials.Load())
	}
}

// T4 and codex 5: the same envelope offered again, before and after the
// agent restarts, is never run twice: picked holds.
func TestReplayIsRefusedByPickedAcrossARestart(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	a, _ := fx.agent("uk-1")
	req := fx.request("SELECT count(*) FROM t", "")
	fx.submit(req)
	a.Pass(context.Background())
	a.Wait()
	a.Pass(context.Background()) // the same agent again
	restarted, w := fx.agent("uk-1")
	restarted.Pass(context.Background())
	restarted.Wait()
	if w.dials.Load() != 0 {
		t.Fatal("a restarted agent ran a read it had already picked")
	}
}

func TestTwoAgentsServeEachReadOnce(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	a, wa := fx.agent("uk-1")
	b, wb := fx.agent("uk-2")
	var ids []string
	for i := 0; i < 10; i++ {
		req := fx.request("SELECT count(*) FROM t", "")
		fx.submit(req)
		ids = append(ids, req.ID)
	}
	for round := 0; round < 20; round++ {
		done := make(chan struct{}, 2)
		go func() { a.Pass(context.Background()); done <- struct{}{} }()
		go func() { b.Pass(context.Background()); done <- struct{}{} }()
		<-done
		<-done
		a.Wait()
		b.Wait()
	}
	for _, id := range ids {
		if _, _, r := fx.answer(id); r.State != StateDone {
			t.Fatalf("%s: %+v", id, r)
		}
	}
	if got := wa.dials.Load() + wb.dials.Load(); got != int64(len(ids)) {
		t.Fatalf("%d worker connections for %d reads", got, len(ids))
	}
}

// Plan review finding 14 (spec §7.1, D2): a draining box beside a healthy
// one never wins a read, including one that starts draining during its
// jitter. Mutation: drop the Draining check after the jitter; the draining
// agent picks every read and this test is red. (The check before admission
// only spares a reservation; the one after the jitter is the gate.)
func TestADrainingBoxDoesNotPick(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	var flip atomic.Bool
	drain, dw := fx.agent("uk-drain", func(c *AgentConfig, _ *inProcWorkers) {
		c.Draining = flip.Load
		c.Jitter = func() time.Duration { flip.Store(true); return time.Millisecond }
	})
	healthy, _ := fx.agent("uk-1")
	for i := 0; i < 5; i++ {
		req := fx.request("SELECT 1", "")
		fx.submit(req)
		drain.Pass(context.Background()) // first: it passes the first check, then drains in its jitter
		drain.Wait()
		healthy.Pass(context.Background())
		healthy.Wait()
		if _, _, r := fx.answer(req.ID); r.Box != "uk-1" {
			t.Fatalf("read %d served by %s", i, r.Box)
		}
		flip.Store(false)
	}
	if dw.dials.Load() != 0 {
		t.Fatal("the draining box started a worker")
	}
}

// Finding 11's box half: a request already cancelled is never picked.
// Mutation: drop the cancel read in consider; the agent picks it.
func TestPassSkipsACancelledRequest(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	a, w := fx.agent("uk-1")
	req := fx.request("SELECT 1", "")
	fx.submit(req)
	fx.store.Put(context.Background(), CancelKey(req.ID), nil, "")
	a.Pass(context.Background())
	a.Wait()
	if _, _, err := fx.store.Get(context.Background(), PickedKey(req.ID)); err == nil || w.dials.Load() != 0 {
		t.Fatal("a cancelled request was picked")
	}
}

func TestPassNeedsTheCapability(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 0)
	cs := &countingStore{Store: fx.store}
	a, _ := fx.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) { c.Store = cs })
	a.probeOK.Store(false)
	a.Pass(context.Background())
	if cs.lists.Load() != 0 {
		t.Fatal("an incapable box listed the queue")
	}
}

func TestProbe(t *testing.T) {
	t.Parallel()
	for name, c := range map[string]struct {
		self func() HelloReply
		dial error
		want bool
	}{
		"a sandboxed worker": {func() HelloReply { return HelloReply{V: ProtocolVersion, Interfaces: []string{"lo"}} }, nil, true},
		"another version":    {func() HelloReply { return HelloReply{V: 2, Interfaces: []string{"lo"}} }, nil, false},
		"a network":          {func() HelloReply { return HelloReply{V: 1, Interfaces: []string{"lo", "eth0"}} }, nil, false},
		"a visible /data":    {func() HelloReply { return HelloReply{V: 1, Interfaces: []string{"lo"}, DataEntries: 3} }, nil, false},
		"a readable host.env": {func() HelloReply { return HelloReply{V: 1, Interfaces: []string{"lo"}, EtcReadable: true} }, nil, false},
		"an observation that failed": {func() HelloReply {
			return HelloReply{V: 1, Errors: []string{"interfaces: permission denied"}}
		}, nil, false},
		"no service":         {nil, errors.New("connection refused"), false},
	} {
		t.Run(name, func(t *testing.T) {
			t.Parallel()
			fx := newFixture(t, 0)
			a, _ := fx.agent("uk-1", func(cfg *AgentConfig, w *inProcWorkers) { w.opt.Self = c.self })
			if c.dial != nil {
				a.cfg.DialWorker = func(context.Context) (net.Conn, error) { return nil, c.dial }
			}
			a.probeOK.Store(!c.want)
			a.Probe(context.Background())
			if a.Capable() != c.want {
				t.Fatalf("Capable = %v", a.Capable())
			}
		})
	}
}

// Review Focus 5 and spec §7.1: a probe beside an orphan, or with no unit
// listing, is skipped and the last result stands.
func TestProbeIsSkippedWhileAdmissionIsBlocked(t *testing.T) {
	t.Parallel()
	for _, last := range []bool{true, false} {
		fx := newFixture(t, 0)
		a, _ := fx.agent("uk-1", func(c *AgentConfig, _ *inProcWorkers) {
			c.Units = func(context.Context) (int, error) { return 1, nil } // an orphan
		})
		a.probeOK.Store(last)
		a.Probe(context.Background())
		if a.Capable() != last {
			t.Fatalf("a skipped probe changed the capability from %v", last)
		}
	}
}

// T13, the unit half: a box running two reads keeps the capability; its
// probe gets the third connection.
func TestProbeOnTheThirdConnection(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	hang := make(chan struct{})
	a, w := fx.agent("uk-1", func(c *AgentConfig, w *inProcWorkers) {
		w.opt.Restore = func(ctx context.Context, _ litestream.ReplicaClient, _ string, _ uint64) error {
			<-hang
			return errors.New("released")
		}
	})
	for i := 0; i < 2; i++ {
		fx.submit(fx.request("SELECT 1", ""))
	}
	a.Pass(context.Background())
	deadline := time.Now().Add(5 * time.Second)
	for w.live.Load() < 2 && time.Now().Before(deadline) {
		time.Sleep(10 * time.Millisecond)
	}
	a.Probe(context.Background())
	if !a.Capable() {
		t.Fatal("a busy box lost the capability")
	}
	close(hang)
	a.Wait()
}

func TestRunPassesOnANudge(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	a, _ := fx.agent("uk-1")
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	nudge := make(chan struct{}, 1)
	go a.Run(ctx, nudge)
	req := fx.request("SELECT count(*) FROM t", "")
	fx.submit(req)
	nudge <- struct{}{}
	deadline := time.Now().Add(10 * time.Second)
	for time.Now().Before(deadline) {
		if _, _, err := fx.store.Get(context.Background(), ResultKey(req.ID)); err == nil {
			return
		}
		time.Sleep(20 * time.Millisecond)
	}
	t.Fatal("a nudge did not serve the read")
}

// Plan review finding 29, through the real loop: a read whose worker never
// starts asks for a probe while that worker's unit is still stopping, so
// admission skips it; the probe stays owed and runs once the unit is gone,
// and the capability is withdrawn well inside ProbeEvery. Mutation: Run
// calls Probe once on probeAfter and drops it when skipped (no retry):
// Capable stays true until ProbeEvery and this test is red.
func TestAProbeSkippedWhileTheUnitLingersRunsOnceItIsGone(t *testing.T) {
	t.Parallel()
	fx := newFixture(t, 1)
	a, w := fx.agent("uk-1", func(_ *AgentConfig, w *inProcWorkers) { w.linger = 700 * time.Millisecond })
	ctx, cancel := context.WithCancel(context.Background())
	nudge := make(chan struct{}, 1)
	done := make(chan struct{})
	go func() { a.Run(ctx, nudge); close(done) }()
	defer func() { cancel(); <-done }()
	until := func(what string, ok func() bool) {
		t.Helper()
		deadline := time.Now().Add(10 * time.Second)
		for !ok() {
			if time.Now().After(deadline) {
				t.Fatalf("never: %s", what)
			}
			time.Sleep(20 * time.Millisecond)
		}
	}
	// The start probe has run and its unit is gone.
	until("the start probe", func() bool { return w.dials.Load() >= 1 && w.live.Load() == 0 && a.Capable() })
	w.failStart.Store(true)
	req := fx.request("SELECT 1", "")
	fx.submit(req)
	nudge <- struct{}{}
	until("the read's result", func() bool {
		_, _, err := fx.store.Get(context.Background(), ResultKey(req.ID))
		return err == nil
	})
	until("the owed probe withdrawing the capability", func() bool { return !a.Capable() })
}
```

- [ ] **Step 2: Run them to verify they fail**

Run: `go test ./internal/dbreads/ -run 'TestPass|TestReplay|TestTwoAgents|TestProbe|TestRun|TestAProbeSkipped' -count=1`
Expected: FAIL, `Pass`, `Probe`, `Run` undefined.

- [ ] **Step 3: Add the loop to `agent.go`**

```go
var errSandbox = errors.New("dbreads: the worker can see more than its sandbox allows")

// probeRetry is how soon a probe that admission skipped is tried again.
var probeRetry = time.Second

// Run is the db-reads loop: a probe at start, a pass on every nudge (a
// serial move) and every ListEvery, a probe every ProbeEvery and whenever a
// read's worker failed to start (spec §5.5 step 4, §7.1). A probe that
// admission skips (the failed worker's unit is still stopping) stays owed
// and is tried every probeRetry until it runs (plan review finding 29).
func (a *Agent) Run(ctx context.Context, nudge <-chan struct{}) {
	var retry <-chan time.Time
	tryProbe := func() {
		retry = nil
		if !a.Probe(ctx) {
			retry = time.After(probeRetry)
		}
	}
	tryProbe()
	list := time.NewTicker(ListEvery)
	defer list.Stop()
	probe := time.NewTicker(ProbeEvery)
	defer probe.Stop()
	for {
		select {
		case <-ctx.Done():
			a.reads.Wait()
			return
		case <-nudge:
			a.Pass(ctx)
		case <-list.C:
			a.Pass(ctx)
		case <-probe.C:
			tryProbe()
		case <-a.probeAfter:
			tryProbe()
		case <-retry:
			tryProbe()
		}
	}
}

// Pass lists this region's queue for this hour and the last, and considers
// every in-window entry it has not decided. An out-of-window entry is
// skipped on its key alone. A box whose capability is withdrawn takes no
// new read; one it already holds runs on (spec §11.2).
func (a *Agent) Pass(ctx context.Context) {
	if !a.Capable() {
		return
	}
	now := a.now()
	a.prune(now)
	for _, hour := range []time.Time{now.Add(-time.Hour), now} {
		keys, err := a.cfg.Store.List(ctx, QueueHourPrefix(a.cfg.Region, hour))
		if err != nil {
			a.logf("dbreads: list the %s queue: %v", a.cfg.Region, err)
			continue
		}
		for _, key := range keys {
			e, ok := ParseQueueKey(key)
			if !ok || e.Region != a.cfg.Region || !InWindow(e.Issued, now) || a.isDecided(e.ID) {
				continue
			}
			a.consider(ctx, e)
		}
	}
}

// Probe is the readiness probe (spec §7.1): a hello on its own connection,
// so a busy box is never mistaken for a broken one. While admission is
// blocked (an orphan unit, or no unit listing) it is skipped, the last
// result stands, and it answers false so Run keeps it owed.
func (a *Agent) Probe(ctx context.Context) bool {
	if !a.adm.admitProbe(ctx) {
		return false
	}
	defer a.adm.probeDone()
	err := a.probe(ctx)
	if err != nil {
		a.logf("dbreads: readiness probe: %v", err)
	}
	a.probeOK.Store(err == nil)
	return true
}

func (a *Agent) probe(ctx context.Context) error {
	pctx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()
	conn, err := a.dial(pctx)
	if err != nil {
		return err
	}
	defer conn.Close()
	defer context.AfterFunc(pctx, func() { conn.Close() })()
	if err := writeJSONFrame(conn, frameHello, hello{V: ProtocolVersion}); err != nil {
		return err
	}
	typ, p, err := readFrame(conn)
	if err != nil {
		return err
	}
	var h HelloReply
	if typ != frameHelloReply || json.Unmarshal(p, &h) != nil {
		return errProtocol
	}
	if h.V != ProtocolVersion {
		return fmt.Errorf("dbreads: the worker speaks protocol %d, this agent %d", h.V, ProtocolVersion)
	}
	if len(h.Errors) != 0 || len(h.Interfaces) != 1 || h.Interfaces[0] != "lo" || h.DataEntries != 0 || h.EtcReadable {
		return fmt.Errorf("%w: %+v", errSandbox, h)
	}
	return nil
}
```

Add `"fmt"` to `agent.go`'s imports.

- [ ] **Step 4: Run the package**

Run: `go test ./internal/dbreads/ -count=1 -race`
Expected: PASS.

- [ ] **Step 5: Commit**

```bash
git add internal/dbreads
git commit -m "dbreads: the loop, the readiness probe and the capability"
```

---

### Task 13: Host wiring: the units, arming, the capability, the nudge

**Files:**
- Create: `internal/host/units/carlos-dbread.socket`
- Create: `internal/host/units/carlos-dbread@.service`
- Create: `internal/host/dbreads.go`
- Create: `internal/host/dbreads_linux.go`
- Create: `internal/host/dbreads_other.go`
- Create: `internal/host/dbreads_test.go`
- Modify: `internal/host/systemunits.go` (install and arm the two units)
- Modify: `internal/host/systemunits_test.go:66-71` (an armed box now answers four probes)
- Modify: `internal/host/edgesfile.go:890` (publish the capability)
- Modify: `internal/host/agent.go:612` (arm the loop) and the serial pass (`d.fullPass`, after `runRunsPass`)

**Interfaces:**
- Consumes: `dbreads.NewAgent`, `AgentConfig`, `Capability`, `ValidRegion`, `DefaultMaxRestored` (Tasks 3 to 12); `lease.ReadReplicaClient`; `openDeployStore`, `BoxLabel`, `newBootID`, `hibernationConfigured`, `hostwrite.Enabled`, `release.ParsePublicKey` (existing in `internal/host`).
- Produces: `dbReadsSettings(getenv func(string) string) (dbReadsEnv, string)`; `armDBReads(hib activator.Config)`; `nudgeDBReads()`; `dbReadsCapable() bool`; `withDBReadCapability(caps []string, capable bool) []string`; `countDBReadUnits(out string) int`; Linux-only `dialDBReadWorker(ctx) (net.Conn, error)`, `dbReadUnits(ctx) (int, error)`, `varTmpFree() (uint64, uint64, error)`, with `!linux` stubs; constants `dbReadSocketUnit`, `dbReadSocketPath`.

- [ ] **Step 1: Write the failing tests**

Create `internal/host/dbreads_test.go`:

```go
package host

import (
	"bufio"
	"bytes"
	"crypto/ed25519"
	"crypto/rand"
	"encoding/base64"
	"os"
	"path/filepath"
	"slices"
	"strings"
	"testing"

	"github.com/carlosframework/platform/internal/dbreads"
)

func TestDBReadsSettingsAreSpec71(t *testing.T) {
	t.Parallel()
	pub, _, _ := ed25519.GenerateKey(rand.Reader)
	good := map[string]string{
		"CARLOS_HIBERNATE_BUCKET": "data-uk", "CARLOS_REGION": "uk",
		"CARLOS_RELEASE_PUBKEY": base64.StdEncoding.EncodeToString(pub),
	}
	env := func(over map[string]string) func(string) string {
		return func(k string) string {
			if v, ok := over[k]; ok {
				return v
			}
			return good[k]
		}
	}
	got, why := dbReadsSettings(env(nil))
	if why != "" || got.region != "uk" || got.maxRestored != dbreads.DefaultMaxRestored {
		t.Fatalf("a capable box: %+v %q", got, why)
	}
	if got, why := dbReadsSettings(env(map[string]string{"CARLOS_DB_READ_MAX_BYTES": "1073741824"})); why != "" || got.maxRestored != 1<<30 {
		t.Fatalf("the size cap: %+v %q", got, why)
	}
	for name, over := range map[string]map[string]string{
		"no hibernation":       {"CARLOS_HIBERNATE_BUCKET": ""},
		"no region":            {"CARLOS_REGION": ""},
		"a fleet placement":    {"CARLOS_REGION": "fleet/acme"},
		"no release key":       {"CARLOS_RELEASE_PUBKEY": ""},
		"switched off":         {"CARLOS_DB_READS": "0"},
		"host claims":          {"CARLOS_HOST_CLAIM": "1"},
		"a cap that is not a number": {"CARLOS_DB_READ_MAX_BYTES": "2GB"},
	} {
		if _, why := dbReadsSettings(env(over)); why == "" {
			t.Errorf("%s: armed", name)
		}
	}
}

func TestCountDBReadUnits(t *testing.T) {
	t.Parallel()
	out := strings.Join([]string{
		"carlos-dbread@0-1234-999.service loaded active running carlos db-read worker",
		"carlos-dbread@1-1235-999.service loaded activating start carlos db-read worker",
		"carlos-dbread@2-1236-999.service loaded deactivating stop-sigterm carlos db-read worker",
		"carlos-dbread@3-1237-999.service loaded failed failed carlos db-read worker",
		"carlos-dbread@4-1238-999.service loaded inactive dead carlos db-read worker",
		"",
	}, "\n")
	if n := countDBReadUnits(out); n != 3 {
		t.Fatalf("counted %d units, want active, activating and deactivating: 3", n)
	}
}

func TestWithDBReadCapability(t *testing.T) {
	t.Parallel()
	base := []string{"region-ha-1"}
	if got := withDBReadCapability(base, false); !slices.Equal(got, base) {
		t.Fatalf("incapable: %v", got)
	}
	if got := withDBReadCapability(base, true); !slices.Equal(got, []string{"region-ha-1", dbreads.Capability}) || len(base) != 1 {
		t.Fatalf("capable: %v (base %v)", got, base)
	}
}

func unitLines(t *testing.T, name string) []string {
	t.Helper()
	b, err := unitsFS.ReadFile("units/" + name)
	if err != nil {
		t.Fatal(err)
	}
	var lines []string
	sc := bufio.NewScanner(bytes.NewReader(b))
	for sc.Scan() {
		if l := strings.TrimSpace(sc.Text()); l != "" && !strings.HasPrefix(l, "#") {
			lines = append(lines, l)
		}
	}
	return lines
}

// The sandbox is the unit file (spec §8.3): every line the spec names is
// there, and nothing loosens it.
func TestDBReadUnitsCarryTheSandbox(t *testing.T) {
	t.Parallel()
	sock := unitLines(t, "carlos-dbread.socket")
	for _, want := range []string{"ListenStream=/run/carlos-dbread/worker.sock", "SocketUser=carlos", "SocketMode=0600", "Accept=yes", "MaxConnections=3"} {
		if !slices.Contains(sock, want) {
			t.Errorf("the socket lacks %q", want)
		}
	}
	svc := unitLines(t, "carlos-dbread@.service")
	for _, want := range []string{
		"ExecStart=/opt/carlos/carlos system db-worker",
		"StandardInput=socket", "StandardOutput=socket", "StandardError=journal",
		"DynamicUser=yes", "PrivateNetwork=yes", "RestrictAddressFamilies=AF_UNIX",
		"TemporaryFileSystem=/data:ro /var/lib:ro /opt/carlos:ro /run/carlos:ro",
		"BindReadOnlyPaths=/opt/carlos/carlos",
		"InaccessiblePaths=/etc/carlos -/run/carlos-control",
		"PrivateTmp=yes", "MemoryMax=512M", "CPUQuota=100%", "TasksMax=16",
		"LimitFSIZE=2147483648", "RuntimeMaxSec=20min",
		"SystemCallFilter=@system-service", "NoNewPrivileges=yes", "CapabilityBoundingSet=", "ProtectProc=invisible",
		"ProtectSystem=strict",
	} {
		if !slices.Contains(svc, want) {
			t.Errorf("the service lacks %q", want)
		}
	}
	for _, l := range svc {
		for _, bad := range []string{"User=", "StandardOutput=file:", "IPAddressAllow=", "ReadWritePaths=", "AmbientCapabilities=CAP"} {
			if strings.HasPrefix(l, bad) {
				t.Errorf("the service loosens its sandbox: %q", l)
			}
		}
	}
}

func TestEnsureSystemUnitsInstallsTheDBReadUnits(t *testing.T) {
	t.Parallel()
	etc := t.TempDir()
	os.MkdirAll(filepath.Join(etc, "systemd", "system"), 0o755)
	var calls []string
	systemctl := func(args ...string) (string, error) {
		calls = append(calls, strings.Join(args, " "))
		return "", nil
	}
	probe := func(args ...string) (string, error) {
		calls = append(calls, strings.Join(args, " "))
		if args[0] == "is-active" {
			return "inactive\n", systemctlExit(3)
		}
		return "disabled\n", systemctlExit(1)
	}
	ensureSystemUnits(etc, filepath.Join(t.TempDir(), "lock"), systemctl, probe, t.Logf)
	for _, u := range []string{"carlos-dbread.socket", "carlos-dbread@.service"} {
		got, err := os.ReadFile(filepath.Join(etc, "systemd", "system", u))
		want, _ := unitsFS.ReadFile("units/" + u)
		if err != nil || !bytes.Equal(got, want) {
			t.Errorf("%s not installed as embedded: %v", u, err)
		}
	}
	joined := strings.Join(calls, "\n")
	for _, want := range []string{"is-active carlos-dbread.socket", "carlos-dbread.socket"} {
		if !strings.Contains(joined, want) {
			t.Errorf("calls lack %q:\n%s", want, joined)
		}
	}
	// systemctlPlan starts every armed unit (sockets, paths, timers, mounts)
	// in the order passed (bootstrap.go armedUnits), and the service
	// template never.
	if !strings.Contains(joined, "start carlos-system-update.path carlos-instance-control.socket carlos-dbread.socket") {
		t.Errorf("the socket was not armed:\n%s", joined)
	}
	if strings.Contains(joined, "start carlos-dbread@") {
		t.Fatal("a worker service was started")
	}
}
```

In `internal/host/systemunits_test.go`, `TestEnsureSystemUnitsInstallsAndArmsWhatIsMissing`'s armed-box case answers one more `is-active` now. Change `if len(calls) != 3` to `if len(calls) != 4` and its comment to "(is-active x3: the self-update path unit, the control socket and the db-read socket, plus is-enabled)".

- [ ] **Step 2: Run them to verify they fail**

Run (sandbox off): `go test ./internal/host/ -run 'TestDBReads|TestCountDBReadUnits|TestWithDBReadCapability|TestDBReadUnits|TestEnsureSystemUnits' -count=1`
Expected: FAIL, undefined names and missing unit files.

- [ ] **Step 3: Write the units**

Create `internal/host/units/carlos-dbread.socket`:

```ini
# The db-read worker's socket (db region forward spec §8.3). Bound by root
# systemd and owned by carlos, so the agent connects with no privilege of
# its own. Each connection starts one carlos-dbread@ instance with the
# connection as its stdin and stdout. Three connections at most: two reads
# and the readiness probe (spec §7.1).
[Unit]
Description=carlos db-read worker socket

[Socket]
ListenStream=/run/carlos-dbread/worker.sock
SocketUser=carlos
SocketGroup=carlos
SocketMode=0600
Accept=yes
MaxConnections=3

[Install]
WantedBy=sockets.target
```

Create `internal/host/units/carlos-dbread@.service`:

```ini
# The db-read worker (db region forward spec §8.3): one instance per
# connection to carlos-dbread.socket. It writes one forwarded read's planned
# LTX files into its own private /var/tmp, restores them, checks the copy,
# and runs the member's one read-only statement. Everything that decodes
# tenant bytes runs here, as a DynamicUser with no network; the agent only
# moves bytes. systemd removes /tmp and /var/tmp when the unit stops,
# however it stops.
#
# StandardInput/StandardOutput=socket: with Accept=yes systemd passes the
# connection as a descriptor and puts it on stdin only when told to. The
# claim-bound template's StandardOutput=file: line is deliberately absent.
#
# LimitFSIZE is the default restored-size cap (CARLOS_DB_READ_MAX_BYTES,
# 2 GiB). A box that raises the cap needs a drop-in raising this too.
[Unit]
Description=carlos db-read worker

[Service]
ExecStart=/opt/carlos/carlos system db-worker
StandardInput=socket
StandardOutput=socket
StandardError=journal
DynamicUser=yes
PrivateNetwork=yes
RestrictAddressFamilies=AF_UNIX
TemporaryFileSystem=/data:ro /var/lib:ro /opt/carlos:ro /run/carlos:ro
BindReadOnlyPaths=/opt/carlos/carlos
InaccessiblePaths=/etc/carlos -/run/carlos-control
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
PrivateDevices=yes
ProtectProc=invisible
ProcSubset=pid
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectClock=yes
ProtectHostname=yes
ProtectControlGroups=yes
RemoveIPC=yes
LockPersonality=yes
RestrictRealtime=yes
RestrictNamespaces=yes
RestrictSUIDSGID=yes
NoNewPrivileges=yes
CapabilityBoundingSet=
SystemCallFilter=@system-service
SystemCallArchitectures=native
MemoryDenyWriteExecute=yes
MemoryMax=512M
CPUQuota=100%
TasksMax=16
LimitFSIZE=2147483648
RuntimeMaxSec=20min
```

`/run/carlos-control` carries `-` because a box without the isolated-exec control socket has no such directory, and a missing path would fail every worker start (and so withdraw the capability on a box that is otherwise fine). `/etc/carlos` exists on every box and stays strict.

- [ ] **Step 4: Install and arm them in `ensureSystemUnits`**

In `internal/host/systemunits.go`:
- add `"carlos-dbread.socket", "carlos-dbread@.service"` to `systemUnitFiles`;
- after the `ctlActiveOut` probe add `dbrActiveOut, dbrActiveErr := probe("is-active", dbReadSocketUnit)` and `dbrActive := parseIsActive(dbrActiveOut)`, include `dbrActive == nil` in the "systemctl said nothing" refusal (with `dbrActiveErr` in its log line), and `*dbrActive` in the all-armed early return;
- arm it: `systemctlPlan([]string{systemUpdatePathUnit, systemRecoverUnit, instanceControlSocket, dbReadSocketUnit})`.

The service template is never started: `armedUnits` starts sockets, timers, paths and mounts only.

- [ ] **Step 5: Write `dbreads.go` and the platform files**

Create `internal/host/dbreads.go`:

```go
package host

import (
	"context"
	"crypto/ed25519"
	"log"
	"os"
	"slices"
	"strconv"
	"strings"
	"sync/atomic"

	"github.com/carlosframework/platform/internal/activator"
	"github.com/carlosframework/platform/internal/dbdoor"
	"github.com/carlosframework/platform/internal/dbreads"
	"github.com/carlosframework/platform/internal/hostwrite"
	"github.com/carlosframework/platform/internal/lease"
	"github.com/carlosframework/platform/internal/release"
)

const (
	dbReadSocketUnit  = "carlos-dbread.socket"
	dbReadSocketPath  = "/run/carlos-dbread/worker.sock"
	dbReadMaxBytesEnv = "CARLOS_DB_READ_MAX_BYTES"
	dbReadsSwitchEnv  = "CARLOS_DB_READS"
)

type dbReadsEnv struct {
	region      string
	pub         ed25519.PublicKey
	maxRestored int64
}

// dbReadsSettings is the environment half of spec §7.1's conditions:
// hibernation configured, CARLOS_REGION a region, CARLOS_RELEASE_PUBKEY
// set, CARLOS_DB_READS not 0, CARLOS_HOST_CLAIM not set. The other half,
// a running loop whose last probe passed, is the agent's. why is "" when
// the loop may be armed.
func dbReadsSettings(getenv func(string) string) (dbReadsEnv, string) {
	switch {
	case !hibernationConfigured(getenv):
		return dbReadsEnv{}, "hibernation is not configured (CARLOS_HIBERNATE_BUCKET)"
	case hostwrite.Enabled(getenv):
		return dbReadsEnv{}, "CARLOS_HOST_CLAIM is set"
	case strings.TrimSpace(getenv(dbReadsSwitchEnv)) == "0":
		return dbReadsEnv{}, dbReadsSwitchEnv + " is 0"
	}
	region := strings.TrimSpace(getenv("CARLOS_REGION"))
	if !dbreads.ValidRegion(region) {
		return dbReadsEnv{}, "CARLOS_REGION is not a region"
	}
	pub, err := release.ParsePublicKey(getenv("CARLOS_RELEASE_PUBKEY"), "CARLOS_RELEASE_PUBKEY")
	if err != nil {
		return dbReadsEnv{}, err.Error()
	}
	env := dbReadsEnv{region: region, pub: pub, maxRestored: dbreads.DefaultMaxRestored}
	if raw := strings.TrimSpace(getenv(dbReadMaxBytesEnv)); raw != "" {
		n, err := strconv.ParseInt(raw, 10, 64)
		if err != nil || n <= 0 {
			return dbReadsEnv{}, dbReadMaxBytesEnv + " is not a whole number of bytes"
		}
		env.maxRestored = n
	}
	return env, ""
}

// armedDBReads is the armed loop; nil on a box that cannot serve.
var armedDBReads atomic.Pointer[dbreads.Agent]

// dbReadsNudge is the serial pass's word to the loop: list the queue now.
var dbReadsNudge = make(chan struct{}, 1)

// dbReadsDraining is the draining flag this box last published in its edges
// file, which the edges loop stores on every pass. The agent reads the same
// value the console's evidence rule reads, so the two never disagree (spec
// §7.1). Nothing on main sets an edges file's Draining yet (region HA's
// placer will); until then it is false.
var dbReadsDraining atomic.Bool

func nudgeDBReads() {
	select {
	case dbReadsNudge <- struct{}{}:
	default:
	}
}

// dbReadsCapable is whether this box publishes db-read-1: the loop is armed
// and its last readiness probe passed (spec §7.1).
func dbReadsCapable() bool {
	a := armedDBReads.Load()
	return a != nil && a.Capable()
}

// withDBReadCapability is caps with db-read-1 when capable; caps is not
// modified.
func withDBReadCapability(caps []string, capable bool) []string {
	if !capable {
		return caps
	}
	return append(slices.Clone(caps), dbreads.Capability)
}

// countDBReadUnits reads `systemctl list-units --plain --no-legend` output:
// carlos-dbread@ units that are active, activating or deactivating. A
// stopped unit's scratch is gone; any other state may still hold it.
func countDBReadUnits(out string) int {
	n := 0
	for _, line := range strings.Split(out, "\n") {
		f := strings.Fields(line)
		if len(f) < 3 || !strings.HasPrefix(f[0], "carlos-dbread@") {
			continue
		}
		switch f[2] {
		case "active", "activating", "deactivating", "reloading", "refreshing":
			n++
		}
	}
	return n
}

// armDBReads arms the db-reads loop on a box that can serve (spec §7.1).
// Thin, like armRunsPass: the behaviour is dbreads.Agent's, tested there.
func armDBReads(hib activator.Config) {
	env, why := dbReadsSettings(os.Getenv)
	if why != "" {
		log.Printf("agent: db reads not armed: %s", why)
		return
	}
	ctx := context.Background()
	store, err := openDeployStore(ctx)
	if err != nil {
		log.Printf("agent: db reads not armed: %v", err)
		return
	}
	a := dbreads.NewAgent(dbreads.AgentConfig{
		Store: store, Region: env.region, Box: BoxLabel(), Boot: newBootID(), Pub: env.pub,
		HibernatePrefix: hib.Prefix,
		OpenReplica: func(ctx context.Context, prefix string) (dbdoor.ReplicaReader, error) {
			return lease.ReadReplicaClient(ctx, hib.Bucket, prefix, hib.Region)
		},
		DialWorker: dialDBReadWorker, Units: dbReadUnits, Free: varTmpFree,
		MaxRestored: env.maxRestored, Logf: log.Printf, Draining: dbReadsDraining.Load,
	})
	armedDBReads.Store(a)
	go a.Run(ctx, dbReadsNudge)
	log.Printf("agent: db reads armed (region %s)", env.region)
}
```

Create `internal/host/dbreads_linux.go`:

```go
//go:build linux

package host

import (
	"context"
	"net"
	"os/exec"

	"golang.org/x/sys/unix"
)

func dialDBReadWorker(ctx context.Context) (net.Conn, error) {
	var d net.Dialer
	return d.DialContext(ctx, "unix", dbReadSocketPath)
}

// dbReadUnits lists carlos-dbread@ units, readable without privilege.
func dbReadUnits(ctx context.Context) (int, error) {
	out, err := exec.CommandContext(ctx, "systemctl", "list-units", "--all", "--plain", "--no-legend", "--no-pager", "carlos-dbread@*.service").Output()
	if err != nil {
		return 0, err
	}
	return countDBReadUnits(string(out)), nil
}

// varTmpFree is the filesystem holding /var/tmp, where every worker's
// private /var/tmp lives.
func varTmpFree() (uint64, uint64, error) {
	var st unix.Statfs_t
	if err := unix.Statfs("/var/tmp", &st); err != nil {
		return 0, 0, err
	}
	return st.Bavail * uint64(st.Bsize), st.Blocks * uint64(st.Bsize), nil
}
```

Create `internal/host/dbreads_other.go`:

```go
//go:build !linux

package host

import (
	"context"
	"errors"
	"net"
)

var errDBReadsUnsupported = errors.New("db reads run only on Linux")

func dialDBReadWorker(context.Context) (net.Conn, error) { return nil, errDBReadsUnsupported }

func dbReadUnits(context.Context) (int, error) { return 0, errDBReadsUnsupported }

func varTmpFree() (uint64, uint64, error) { return 0, 0, errDBReadsUnsupported }
```

- [ ] **Step 6: Publish, arm and nudge**

In `internal/host/edgesfile.go`, line 890:

```go
		ident.Capabilities = withDBReadCapability(withOfflineCapability(baseCaps, armedOfflineCapable()), dbReadsCapable())
		dbReadsDraining.Store(ident.Draining)
```

and extend the comment above `baseCaps` to say db-read-1 joins per pass too, and that the agent's draining check reads the flag this file publishes.

In `internal/host/agent.go`, right after `armRunsPass(svc, reg, dd, rolloutSink)` (line 612):

```go
				// The db-reads loop (db region forward spec §7.1): armed
				// only on a box that can serve; it takes nothing until a
				// console asks.
				armDBReads(*cfg)
```

and in `d.fullPass`, after `runRunsPass(ctx)` and its `mark("runs")`:

```go
		// A serial move may be a forwarded db read: list the queue now.
		nudgeDBReads()
```

- [ ] **Step 7: Run the tests and the cross-compiles**

Run (sandbox off):
```bash
go test ./internal/host/ -run 'TestDBReads|TestCountDBReadUnits|TestWithDBReadCapability|TestDBReadUnits|TestEnsureSystemUnits' -count=1
go vet ./internal/host/ ./internal/dbreads/
GOOS=darwin GOARCH=arm64 go build ./... && GOOS=windows GOARCH=amd64 go build ./...
```
Expected: PASS, no vet findings, clean builds.

- [ ] **Step 8: Commit**

```bash
git add internal/host
git commit -m "host: carlos-dbread units, the db-reads loop armed dark, db-read-1 published while the probe passes"
```

---

### Task 14: The parity half of T6, and `dbreadstest`

**Files:**
- Create: `internal/dbreads/dbreadstest/dbreadstest.go`
- Create: `internal/console/dbreads_parity_test.go`

**Interfaces:**
- Consumes: `dbreads.NewAgent`, `Agent.Probe`, `Agent.Pass`, `Agent.Wait`, `ServeWorker`, `Sign`, `OpenSummary`, `OpenChunk`; the console's `replicaDoer` (`internal/console/seeddoer.go:28`); `dbdoor.RestoreAsOf`; `dbquery.RunContext`.
- Produces (test support, imported only by `_test.go` files): `dbreadstest.Options`, `dbreadstest.Start(t testing.TB, o Options) *Box`, `(*Box).Serve(t testing.TB, store release.Store, id string, timeout time.Duration)`, `(*Box).Dials`, `dbreadstest.Submit(t testing.TB, store release.Store, root ed25519.PrivateKey, req dbreads.Request)`, `dbreadstest.Answer(t testing.TB, store release.Store, id string, priv *ecdh.PrivateKey, stream string) ([]byte, dbreads.Summary, dbreads.Result)`.

- [ ] **Step 1: Write `dbreadstest`**

```go
// Package dbreadstest runs the box's half of a forwarded read inside a test
// process: the real dbreads.Agent and the real dbreads.ServeWorker, joined by
// net.Pipe instead of the installed socket. Test support only. It is not
// acceptance for the units (internal/host's root-runner tests are), and
// nothing outside a _test.go file may import it.
package dbreadstest

import (
	"bytes"
	"context"
	"crypto/ecdh"
	"crypto/ed25519"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"net"
	"sync/atomic"
	"testing"
	"time"

	"github.com/carlosframework/platform/internal/dbdoor"
	"github.com/carlosframework/platform/internal/dbreads"
	"github.com/carlosframework/platform/internal/release"
)

type Options struct {
	Store           release.Store
	Region          string
	Box             string
	Pub             ed25519.PublicKey
	HibernatePrefix string
	OpenReplica     func(ctx context.Context, prefix string) (dbdoor.ReplicaReader, error)
	MaxRestored     int64
	// Worker's Scratch, Exit and Self are filled in when empty.
	Worker dbreads.WorkerOptions
}

type Box struct {
	Agent  *dbreads.Agent
	Dials  atomic.Int64
	live   atomic.Int64
	worker dbreads.WorkerOptions
}

// Start builds a capable in-process box: its probe passes against an
// in-process worker reporting a sandboxed view.
func Start(t testing.TB, o Options) *Box {
	t.Helper()
	b := &Box{worker: o.Worker}
	if b.worker.Scratch == "" {
		b.worker.Scratch = t.TempDir()
	}
	if b.worker.Exit == nil {
		b.worker.Exit = func(int) {}
	}
	if b.worker.Self == nil {
		b.worker.Self = func() dbreads.HelloReply {
			return dbreads.HelloReply{V: dbreads.ProtocolVersion, Interfaces: []string{"lo"}}
		}
	}
	b.Agent = dbreads.NewAgent(dbreads.AgentConfig{
		Store: o.Store, Region: o.Region, Box: o.Box, Boot: "boot-" + o.Box, Pub: o.Pub,
		HibernatePrefix: o.HibernatePrefix, OpenReplica: o.OpenReplica,
		DialWorker: b.dial, Units: b.units,
		Free:        func() (uint64, uint64, error) { return 100 << 30, 200 << 30, nil },
		MaxRestored: o.MaxRestored, Jitter: func() time.Duration { return 0 }, Logf: t.Logf,
	})
	b.Agent.Probe(context.Background())
	if !b.Agent.Capable() {
		t.Fatal("dbreadstest: the in-process box failed its probe")
	}
	return b
}

func (b *Box) dial(context.Context) (net.Conn, error) {
	agentEnd, workerEnd := net.Pipe()
	b.Dials.Add(1)
	b.live.Add(1)
	go func() {
		defer b.live.Add(-1)
		dbreads.ServeWorker(workerEnd, b.worker)
		workerEnd.Close()
	}()
	return agentEnd, nil
}

func (b *Box) units(context.Context) (int, error) { return int(b.live.Load()), nil }

// Serve passes until the read's result exists.
func (b *Box) Serve(t testing.TB, store release.Store, id string, timeout time.Duration) {
	t.Helper()
	deadline := time.Now().Add(timeout)
	for time.Now().Before(deadline) {
		b.Agent.Pass(context.Background())
		b.Agent.Wait()
		if _, _, err := store.Get(context.Background(), dbreads.ResultKey(id)); err == nil {
			return
		}
		time.Sleep(20 * time.Millisecond)
	}
	t.Fatalf("dbreadstest: no result for %s within %s", id, timeout)
}

// Submit is the console's two creates for req, signed with root: for tests
// that have no console.
func Submit(t testing.TB, store release.Store, root ed25519.PrivateKey, req dbreads.Request) {
	t.Helper()
	wire, err := dbreads.Sign(release.RootSigner(root), req)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := store.Put(context.Background(), dbreads.RequestKey(req.ID), wire, ""); err != nil {
		t.Fatal(err)
	}
	issued, err := req.Issued()
	if err != nil {
		t.Fatal(err)
	}
	if _, err := store.Put(context.Background(), dbreads.QueueKey(req.Region, issued, req.ID), nil, ""); err != nil {
		t.Fatal(err)
	}
}

// Answer reads a read's result and opens its chunks with the CLI's key,
// checking the count and hash a done read's summary carries.
func Answer(t testing.TB, store release.Store, id string, priv *ecdh.PrivateKey, stream string) ([]byte, dbreads.Summary, dbreads.Result) {
	t.Helper()
	raw, _, err := store.Get(context.Background(), dbreads.ResultKey(id))
	if err != nil {
		t.Fatalf("dbreadstest: no result for %s: %v", id, err)
	}
	var r dbreads.Result
	if err := json.Unmarshal(raw, &r); err != nil || r.Valid() != nil {
		t.Fatalf("dbreadstest: result %s: %v", raw, err)
	}
	s, err := dbreads.OpenSummary(priv, id, r.Sealed)
	if err != nil {
		t.Fatal(err)
	}
	var out bytes.Buffer
	for seq := int64(1); seq <= r.LastSeq; seq++ {
		sealed, _, err := store.Get(context.Background(), dbreads.ChunkKey(id, seq))
		if err != nil {
			t.Fatalf("dbreadstest: chunk %d: %v", seq, err)
		}
		plain, err := dbreads.OpenChunk(priv, id, seq, stream, seq == r.LastSeq, sealed)
		if err != nil {
			t.Fatalf("dbreadstest: chunk %d: %v", seq, err)
		}
		out.Write(plain)
	}
	if r.State == dbreads.StateDone {
		sum := sha256.Sum256(out.Bytes())
		if int64(out.Len()) != s.Bytes || hex.EncodeToString(sum[:]) != s.SHA256 {
			t.Fatalf("dbreadstest: the answer does not add up: %d bytes, summary %+v", out.Len(), s)
		}
	}
	return out.Bytes(), s, r
}
```

- [ ] **Step 2: Write the parity test**

Create `internal/console/dbreads_parity_test.go`:

```go
package console

import (
	"bytes"
	"context"
	"crypto/ed25519"
	"crypto/rand"
	"database/sql"
	"encoding/json"
	"path/filepath"
	"testing"
	"time"

	lsfile "github.com/benbjohnson/litestream/file"

	"github.com/carlosframework/platform/internal/dbdoor"
	"github.com/carlosframework/platform/internal/dbdoor/dbdoortest"
	"github.com/carlosframework/platform/internal/dbquery"
	"github.com/carlosframework/platform/internal/dbreads"
	"github.com/carlosframework/platform/internal/dbreads/dbreadstest"
	"github.com/carlosframework/platform/internal/hostclaim"
	"github.com/carlosframework/platform/internal/provision"
	"github.com/carlosframework/platform/internal/release"
)

// The parity half of spec T6 that needs no console server (plan 1): the box
// path (dbreads.Agent through the real worker code, joined in process: not
// acceptance for the units) and the CLI's in-region path (dbdoor.RestoreAsOf
// over this package's own door code, replicaDoer and listReplicaLevel, then
// dbquery.RunContext) print the same bytes, as of the same transaction: the
// newest copy, a time between writes, and a time in the same second as a
// write. Plan 2's T6 runs the same comparison through the console server and
// the CLI binary.
func TestDBReadsParityWithTheInRegionDoor(t *testing.T) {
	const host = "shop.example.com"
	dir := t.TempDir()
	src := filepath.Join(t.TempDir(), "shop.db")
	db, err := sql.Open("sqlite", src)
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	exec := func(q string, args ...any) {
		t.Helper()
		if _, err := db.Exec(q, args...); err != nil {
			t.Fatal(err)
		}
	}
	nextSecond := func() time.Time {
		time.Sleep(time.Until(time.Now().Truncate(time.Second).Add(time.Second + 10*time.Millisecond)))
		return time.Now()
	}
	exec(`PRAGMA journal_mode=WAL; CREATE TABLE orders (id INTEGER PRIMARY KEY, note TEXT, data BLOB, at DATETIME)`)
	exec(`INSERT INTO orders (note, data, at) VALUES (?, ?, ?), (NULL, NULL, NULL), (?, ?, ?)`,
		"a\ttab", []byte{0, 0xff}, time.Date(2026, 10, 7, 14, 0, 0, 0, time.UTC),
		"two\nlines", []byte("x"), time.Date(2026, 10, 7, 14, 0, 1, 500, time.UTC))
	dbdoortest.Sync(t, src, dir)
	between := nextSecond()
	nextSecond()
	exec(`INSERT INTO orders (note) VALUES ('later')`)
	dbdoortest.Sync(t, src, dir)
	sameSecond := time.Now() // in the second the last file was written
	nextSecond()

	store := release.NewDirStore(t.TempDir())
	pub, priv, _ := ed25519.GenerateKey(rand.Reader)
	yes := true
	rec := provision.Record{Host: host, App: "shop", Account: "bab", Region: "uk", Hibernate: &yes, CreatedAt: time.Date(2026, 9, 1, 0, 0, 0, 0, time.UTC)}
	body, _ := json.Marshal(rec)
	if _, err := store.Put(context.Background(), provision.RecordKey("bab", "shop", host), body, ""); err != nil {
		t.Fatal(err)
	}
	inc, _ := hostclaim.Incarnation("bab", "shop", host, rec.CreatedAt)
	box := dbreadstest.Start(t, dbreadstest.Options{Store: store, Region: "uk", Box: "uk-1", Pub: pub, HibernatePrefix: "instances",
		OpenReplica: func(context.Context, string) (dbdoor.ReplicaReader, error) { return lsfile.NewReplicaClient(dir), nil }})
	const query = "SELECT id, note, data, at FROM orders ORDER BY id"
	for name, at := range map[string]time.Time{"newest": {}, "between writes": between, "same second as a write": sameSecond} {
		got, err := dbdoor.RestoreAsOf(context.Background(), dbdoor.NewClient(replicaDoer(lsfile.NewReplicaClient(dir))), t.TempDir(), at)
		if err != nil {
			t.Fatalf("%s: in-region: %v", name, err)
		}
		var want bytes.Buffer
		if err := dbquery.RunContext(context.Background(), &want, got.Path, query, dbquery.Options{}); err != nil {
			t.Fatal(err)
		}
		reply, _ := dbreads.NewReplyKey()
		id, _ := dbreads.MintID()
		atRaw := ""
		if !at.IsZero() {
			atRaw = at.UTC().Format(time.RFC3339Nano)
		}
		req := dbreads.Request{ID: id, Account: "bab", App: "shop", Host: host, Incarnation: inc, Region: "uk",
			Op: dbreads.OpQuery, SQL: query, At: atRaw, ReplyKey: dbreads.EncodeReplyKey(reply.PublicKey()),
			By: "member@example.com", IssuedAt: time.Now().UTC().Format(time.RFC3339)}
		dbreadstest.Submit(t, store, priv, req)
		box.Serve(t, store, id, 30*time.Second)
		rows, s, r := dbreadstest.Answer(t, store, id, reply, dbreads.StreamRows)
		if r.State != dbreads.StateDone || !bytes.Equal(rows, want.Bytes()) || s.TXID != got.TXID || !s.At.Equal(got.At) {
			t.Fatalf("%s: box %+v txid %d at %v rows %q; in-region txid %d at %v rows %q",
				name, r, s.TXID, s.At, rows, got.TXID, got.At, want.Bytes())
		}
	}
}
```

The `at` parameter of a request is RFC 3339; the CLI sends it with sub-second precision when the person typed it, and both paths truncate to the second. `Request.AtTime` parses with `time.RFC3339`, which accepts fractional seconds.

- [ ] **Step 3: Run it**

Run (sandbox off): `go test ./internal/console/ -run 'TestDBReadsParityWithTheInRegionDoor' -count=1 -v`
Expected: PASS, three cases. If it fails only on the "same second" case, the two paths disagree on rounding: that is the bug T6 exists to catch; fix `dbdoor.PlanFrom`, not the test.

- [ ] **Step 4: Commit**

```bash
git add internal/dbreads/dbreadstest internal/console/dbreads_parity_test.go
git commit -m "dbreads: dbreadstest, and T6's parity half against the in-region door"
```

---

### Task 15: Root-runner acceptance: T2, T3, T12, T13

These are the plan's acceptance gate. They run only on the throwaway root runner (`root-runner.py`, see the root-runner contract), never in CI and never on DOCS-T1.

**Files:**
- Create: `internal/host/dbreads_worker_dispatch_linux_test.go` (`//go:build linux`)
- Create: `internal/host/dbreads_rootrunner_linux_test.go` (`//go:build linux && rootrunner`)
- Modify: `internal/host/plan14_generation_registry_root_linux_test.go:18` (`TestMain`: two dispatches at the top)

**Interfaces:**
- Consumes: `ensureSystemUnits`, `systemctlProbe`, `dialDBReadWorker`, `dbReadUnits`, `varTmpFree`, `withDBReadCapability` (Task 13); `dbreads.RunWorkerWith`, `StdinConn`, `CarlosUID`, `SelfView`, `NewAgent`, `Sign`, `OpenSummary`, `OpenChunk` (Tasks 5 to 12); `dbdoortest.Replicate`.
- Produces: test functions `TestRootDBReadServesThroughTheInstalledUnits` (T2), `TestRootDBReadWorkerSandbox` (T3), `TestRootDBReadAdmissionWithRealUnits` (T12), `TestRootDBReadReadiness` (T13), and the payload `TestRootDBReadPayload` (run only as a child, never by name).

- [ ] **Step 1: Write the worker dispatch**

Create `internal/host/dbreads_worker_dispatch_linux_test.go`:

```go
//go:build linux

package host

import (
	"context"
	"database/sql"
	"encoding/json"
	"errors"
	"net"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/benbjohnson/litestream"

	"github.com/carlosframework/platform/internal/dbreads"
)

// dbreadTestMarkers holds marker files the root-runner tests drop to change
// one thing about the worker. The unit can read /run outside /run/carlos.
const dbreadTestMarkers = "/run/carlos-dbread-test"

func dbreadMarker(name string) bool {
	_, err := os.Stat(filepath.Join(dbreadTestMarkers, name))
	return err == nil
}

// dbreadsTestWorker is this test binary acting as /opt/carlos/carlos system
// db-worker inside the installed carlos-dbread@ unit. Without a marker it is
// the real worker (dbreads.RunWorkerWith with RunWorker's options).
func dbreadsTestWorker() {
	opt := dbreads.WorkerOptions{Scratch: "/var/tmp"}
	switch {
	case dbreadMarker("exit-1"):
		os.Exit(1)
	case dbreadMarker("witness"):
		dbreadsWitness()
		return
	}
	if dbreadMarker("version-2") {
		opt.Self = func() dbreads.HelloReply { h := dbreads.SelfView(); h.V = 2; return h }
	}
	if dbreadMarker("hang-restore") {
		// A restore that ignores its context, as litestream's compactor
		// does (spec §8.3): only the 5 s exit ends it.
		opt.Restore = func(context.Context, litestream.ReplicaClient, string, uint64) error {
			time.Sleep(time.Hour)
			return nil
		}
	}
	dbreads.RunWorkerWith(opt)
}

// dbreadsWitness is T3 from inside the unit: everything a member's SQL could
// reach for if SQLite let it, tried directly. It reports each attempt's
// error ("" for success) as one JSON object on the connection.
func dbreadsWitness() {
	conn, err := dbreads.StdinConn(os.Stdin, dbreads.CarlosUID)
	if err != nil {
		os.Exit(2)
	}
	defer conn.Close()
	report := map[string]string{}
	try := func(name string, f func() error) {
		if err := f(); err != nil {
			report[name] = err.Error()
		} else {
			report[name] = ""
		}
	}
	open := func(p string) func() error {
		return func() error {
			f, err := os.Open(p)
			if err == nil {
				f.Close()
			}
			return err
		}
	}
	dial := func(addr string) func() error {
		return func() error {
			c, err := net.DialTimeout("tcp", addr, 2*time.Second)
			if err == nil {
				c.Close()
			}
			return err
		}
	}
	write := func(p string) func() error { return func() error { return os.WriteFile(p, []byte("x"), 0o600) } }
	try("open /data/registry.db", open("/data/registry.db"))
	try("open /etc/carlos/host.env", open("/etc/carlos/host.env"))
	try("open another instance", open("/data/instances/other.example.com/other.db"))
	try("connect the metadata service", dial("169.254.169.254:80"))
	try("connect a TCP address", dial("1.1.1.1:443"))
	// Network-namespace evidence that needs no socket (plan review finding
	// 17): with RestrictAddressFamilies=AF_UNIX the TCP dials above fail
	// even without PrivateNetwork, so they cannot witness it. This can: it
	// "succeeds" (and so fails the test) when any interface but loopback is
	// visible, which is the case the moment PrivateNetwork is removed.
	try("see an interface other than loopback", func() error {
		raw, err := os.ReadFile("/proc/self/net/dev")
		if err != nil {
			return nil // unobservable counts as reachable: the test fails
		}
		ifs := strings.Join(dbreadsParseNetDev(string(raw)), ",")
		if ifs == "lo" {
			return errors.New("only lo")
		}
		return nil
	})
	try("write /opt/carlos", write("/opt/carlos/witness"))
	try("write /var/lib", write("/var/lib/witness"))
	try("write /etc", write("/etc/witness"))
	try("write /var/tmp", write("/var/tmp/witness")) // the positive control
	// SQLite with the attach limit removed: the mutation. Only the sandbox
	// stands between these statements and the box. The attached targets are
	// real SQLite databases the runner wrote on the host, so a statement
	// fails only because the file cannot be reached, never because it is
	// not a database.
	sqlTry := func(name, q string) {
		try(name, func() error {
			db, err := sql.Open("sqlite", "file:/var/tmp/witness.db")
			if err != nil {
				return err
			}
			defer db.Close()
			_, err = db.Exec(q)
			return err
		})
	}
	sqlTry("attach /data/registry.db", "ATTACH DATABASE '/data/registry.db' AS r; SELECT count(*) FROM r.sqlite_master")
	sqlTry("attach /etc/carlos/witness.db", "ATTACH DATABASE '/etc/carlos/witness.db' AS e; SELECT count(*) FROM e.sqlite_master")
	sqlTry("vacuum into /opt/carlos", "VACUUM INTO '/opt/carlos/copy.db'")
	sqlTry("load_extension", "SELECT load_extension('/lib/x86_64-linux-gnu/libc.so.6')")
	json.NewEncoder(conn).Encode(report)
}

// dbreadsParseNetDev is dbreads.parseNetDev, restated: that one is
// unexported in another package.
func dbreadsParseNetDev(s string) []string {
	var out []string
	for i, line := range strings.Split(s, "\n") {
		if i < 2 {
			continue
		}
		if name, _, ok := strings.Cut(line, ":"); ok && strings.TrimSpace(name) != "" {
			out = append(out, strings.TrimSpace(name))
		}
	}
	return out
}
```

The SQLite driver is already linked into the host test binary (`internal/registry` imports `modernc.org/sqlite`).

In `TestMain` (`internal/host/plan14_generation_registry_root_linux_test.go:18`), add at the very top:

```go
	// The installed carlos-dbread@ unit runs this binary as
	// /opt/carlos/carlos system db-worker (dbreads_rootrunner_linux_test.go).
	if len(os.Args) == 3 && os.Args[1] == "system" && os.Args[2] == "db-worker" {
		dbreadsTestWorker()
		return
	}
	// The agent half of the db-read root-runner tests, run as carlos.
	if os.Getenv("DBREAD_RUNNER_PAYLOAD") != "" {
		flag.Set("test.run", "^TestRootDBReadPayload$")
		flag.Set("test.v", "false")
		flag.Set("test.timeout", "5m")
		os.Exit(m.Run())
	}
```

- [ ] **Step 2: Write the root-runner tests**

Create `internal/host/dbreads_rootrunner_linux_test.go`:

```go
//go:build linux && rootrunner

package host

import (
	"bufio"
	"bytes"
	"context"
	"crypto/ecdh"
	"crypto/ed25519"
	"crypto/rand"
	"database/sql"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
	"testing"
	"time"

	lsfile "github.com/benbjohnson/litestream/file"

	"github.com/carlosframework/platform/internal/dbdoor"
	"github.com/carlosframework/platform/internal/dbdoor/dbdoortest"
	"github.com/carlosframework/platform/internal/dbreads"
	"github.com/carlosframework/platform/internal/hostclaim"
	"github.com/carlosframework/platform/internal/provision"
	"github.com/carlosframework/platform/internal/release"
)

const (
	dbreadRunnerHost = "shop.example.com"
	// dbreadReportPrefix marks the payload's one report line. m.Run prints
	// PASS after the payload test returns, so the report is never the last
	// line (plan review finding 3).
	dbreadReportPrefix = "DBREAD-REPORT "
	// dbreadServiceFile is where ensureSystemUnits("/etc", ...) installs the
	// worker's service (plan review finding 4).
	dbreadServiceFile = "/etc/systemd/system/carlos-dbread@.service"
)

// dbreadRunner is the production wiring on a throwaway root runner: the real
// units installed by the real ensureSystemUnits into /etc, as the agent's
// adopt pass installs them (agent.go), this test binary at /opt/carlos/carlos
// where the unit's ExecStart finds it, and the agent half run as carlos in a
// child process, because the worker serves only the carlos user's
// connections. /var/tmp is a tmpfs of tmpSize: the runner's small root
// volume would refuse every read's 5 GiB floor, and tmpfs only spends memory
// on what is written.
type dbreadRunner struct {
	t        *testing.T
	dir      string // owned by carlos: the store and the replica
	uid, gid int
	rootPub  ed25519.PublicKey
	rootPriv ed25519.PrivateKey
}

func runSystemctl(args ...string) (string, error) {
	out, err := exec.Command("systemctl", args...).CombinedOutput()
	return string(out), err
}

func mustSystemctl(t *testing.T, args ...string) {
	t.Helper()
	if out, err := runSystemctl(args...); err != nil {
		t.Fatalf("systemctl %s: %v: %s", strings.Join(args, " "), err, out)
	}
}

// sqliteFixture writes a real SQLite database at path, so an ATTACH of it
// fails only when the file cannot be reached (plan review finding 17).
func sqliteFixture(t *testing.T, path string) {
	t.Helper()
	db, err := sql.Open("sqlite", path)
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS secret (v TEXT); INSERT INTO secret VALUES ('not for tenants')`); err != nil {
		t.Fatal(err)
	}
}

func newDBReadRunner(t *testing.T, tmpSize string) *dbreadRunner {
	t.Helper()
	if os.Geteuid() != 0 {
		t.Fatal("run on the root runner, as root")
	}
	r := &dbreadRunner{t: t}
	if out, err := exec.Command("mount", "-t", "tmpfs", "-o", "size="+tmpSize+",mode=1777", "tmpfs", "/var/tmp").CombinedOutput(); err != nil {
		t.Fatalf("mount /var/tmp: %v: %s", err, out)
	}
	t.Cleanup(func() { exec.Command("umount", "/var/tmp").Run() })
	u, err := user.Lookup("carlos")
	if err != nil {
		if out, err := exec.Command("useradd", "--system", "--user-group", "--no-create-home", "--shell", "/usr/sbin/nologin", "carlos").CombinedOutput(); err != nil {
			t.Fatalf("useradd: %v: %s", err, out)
		}
		t.Cleanup(func() { exec.Command("userdel", "carlos").Run() })
		if u, err = user.Lookup("carlos"); err != nil {
			t.Fatal(err)
		}
	}
	r.uid, _ = strconv.Atoi(u.Uid)
	r.gid, _ = strconv.Atoi(u.Gid)
	if _, err := os.Stat("/opt/carlos/carlos"); err == nil {
		t.Fatal("/opt/carlos/carlos exists: this test runs only on a fresh runner")
	}
	self, err := os.ReadFile(os.Args[0])
	if err != nil {
		t.Fatal(err)
	}
	for _, d := range []string{"/opt/carlos", "/etc/carlos", "/data/instances/other.example.com", "/run/carlos", dbreadTestMarkers} {
		if err := os.MkdirAll(d, 0o755); err != nil {
			t.Fatal(err)
		}
	}
	// Things the witness must not reach, present on the host: real SQLite
	// databases where the witness ATTACHes, a host.env it opens.
	sqliteFixture(t, "/data/registry.db")
	sqliteFixture(t, "/etc/carlos/witness.db")
	sqliteFixture(t, "/data/instances/other.example.com/other.db")
	if err := os.WriteFile("/etc/carlos/host.env", []byte("CARLOS_REGION=uk\n"), 0o640); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile("/opt/carlos/carlos", self, 0o755); err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() {
		for _, p := range []string{"/opt/carlos/carlos", "/data/registry.db", "/etc/carlos/witness.db", "/etc/carlos/host.env"} {
			os.Remove(p)
		}
		os.RemoveAll("/data/instances/other.example.com")
		os.RemoveAll(dbreadTestMarkers)
	})
	ensureSystemUnits("/etc", filepath.Join(t.TempDir(), "lock"), runSystemctl, systemctlProbe, t.Logf)
	t.Cleanup(func() {
		runSystemctl("stop", "carlos-dbread.socket", "carlos-instance-control.socket", "carlos-system-update.path")
		runSystemctl("disable", "carlos-dbread.socket", "carlos-instance-control.socket", "carlos-system-update.path", "carlos-system-recover.service")
		for _, u := range systemUnitFiles {
			os.Remove(filepath.Join("/etc/systemd/system", u))
		}
		runSystemctl("daemon-reload")
	})
	if _, err := os.Stat(dbreadServiceFile); err != nil {
		t.Fatalf("ensureSystemUnits installed no %s: %v", dbreadServiceFile, err)
	}
	if out, _ := systemctlProbe("is-active", dbReadSocketUnit); strings.TrimSpace(out) != "active" {
		t.Fatalf("carlos-dbread.socket is %q after ensureSystemUnits", out)
	}
	r.dir, err = os.MkdirTemp("/var/lib", "carlos-dbread-runner-")
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { os.RemoveAll(r.dir) })
	r.rootPub, r.rootPriv, _ = ed25519.GenerateKey(rand.Reader)
	replica := filepath.Join(r.dir, "replica", "instances", dbreadRunnerHost)
	dbdoortest.Replicate(t, replica, 3)
	yes := true
	rec := provision.Record{Host: dbreadRunnerHost, App: "shop", Account: "bab", Region: "uk", Hibernate: &yes,
		CreatedAt: time.Date(2026, 9, 1, 0, 0, 0, 0, time.UTC)}
	body, _ := json.Marshal(rec)
	if _, err := r.store().Put(context.Background(), provision.RecordKey("bab", "shop", dbreadRunnerHost), body, ""); err != nil {
		t.Fatal(err)
	}
	r.chown()
	return r
}

func (r *dbreadRunner) store() release.Store { return release.NewDirStore(filepath.Join(r.dir, "store")) }

func (r *dbreadRunner) chown() {
	filepath.Walk(r.dir, func(p string, _ os.FileInfo, _ error) error { return os.Lchown(p, r.uid, r.gid) })
}

func (r *dbreadRunner) marker(name string, on bool) {
	r.t.Helper()
	p := filepath.Join(dbreadTestMarkers, name)
	var err error
	if on {
		err = os.WriteFile(p, nil, 0o644)
	} else if err = os.Remove(p); os.IsNotExist(err) {
		err = nil
	}
	if err != nil {
		r.t.Fatal(err)
	}
}

// submit is the console's two creates for a read of op; it returns the
// read's id and reply key.
func (r *dbreadRunner) submit(op, sqlText string) (string, *ecdh.PrivateKey) {
	r.t.Helper()
	reply, _ := dbreads.NewReplyKey()
	id, _ := dbreads.MintID()
	inc, _ := hostclaim.Incarnation("bab", "shop", dbreadRunnerHost, time.Date(2026, 9, 1, 0, 0, 0, 0, time.UTC))
	req := dbreads.Request{ID: id, Account: "bab", App: "shop", Host: dbreadRunnerHost, Incarnation: inc, Region: "uk",
		Op: op, SQL: sqlText, ReplyKey: dbreads.EncodeReplyKey(reply.PublicKey()),
		By: "member@example.com", IssuedAt: time.Now().UTC().Format(time.RFC3339)}
	wire, err := dbreads.Sign(release.RootSigner(r.rootPriv), req)
	if err != nil {
		r.t.Fatal(err)
	}
	s := r.store()
	if _, err := s.Put(context.Background(), dbreads.RequestKey(id), wire, ""); err != nil {
		r.t.Fatal(err)
	}
	issued, _ := req.Issued()
	if _, err := s.Put(context.Background(), dbreads.QueueKey("uk", issued, id), nil, ""); err != nil {
		r.t.Fatal(err)
	}
	r.chown()
	return id, reply
}

// payload runs the agent half as carlos. With wait it returns the payload's
// report, the line marked dbreadReportPrefix; without, the running command.
// id, when set, is the read the scenario waits on or reports about.
func (r *dbreadRunner) payload(scenario string, wait bool, id string) (map[string]any, *exec.Cmd) {
	r.t.Helper()
	cmd := exec.Command(os.Args[0])
	cmd.Env = append(os.Environ(), "DBREAD_RUNNER_PAYLOAD="+scenario, "DBREAD_RUNNER_DIR="+r.dir,
		"DBREAD_RUNNER_ID="+id, "DBREAD_RUNNER_PUB="+base64.StdEncoding.EncodeToString(r.rootPub))
	cmd.SysProcAttr = &syscall.SysProcAttr{Credential: &syscall.Credential{Uid: uint32(r.uid), Gid: uint32(r.gid)}}
	var out bytes.Buffer
	cmd.Stdout, cmd.Stderr = &out, os.Stderr
	if !wait {
		if err := cmd.Start(); err != nil {
			r.t.Fatal(err)
		}
		return nil, cmd
	}
	if err := cmd.Run(); err != nil {
		r.t.Fatalf("payload %s: %v: %s", scenario, err, out.String())
	}
	sc := bufio.NewScanner(&out)
	for sc.Scan() {
		if line, ok := strings.CutPrefix(sc.Text(), dbreadReportPrefix); ok {
			var rep map[string]any
			if err := json.Unmarshal([]byte(line), &rep); err != nil {
				r.t.Fatalf("payload %s: unreadable report %q", scenario, line)
			}
			return rep, cmd
		}
	}
	r.t.Fatalf("payload %s gave no report: %s", scenario, out.String())
	return nil, cmd
}

func (r *dbreadRunner) answer(id string, reply *ecdh.PrivateKey, stream string) ([]byte, dbreads.Result) {
	r.t.Helper()
	s := r.store()
	raw, _, err := s.Get(context.Background(), dbreads.ResultKey(id))
	if err != nil {
		r.t.Fatalf("no result: %v", err)
	}
	var res dbreads.Result
	json.Unmarshal(raw, &res)
	var out bytes.Buffer
	for seq := int64(1); seq <= res.LastSeq; seq++ {
		sealed, _, _ := s.Get(context.Background(), dbreads.ChunkKey(id, seq))
		plain, err := dbreads.OpenChunk(reply, id, seq, stream, seq == res.LastSeq, sealed)
		if err != nil {
			r.t.Fatal(err)
		}
		out.Write(plain)
	}
	return out.Bytes(), res
}

// privateTmpGone waits up to limit for every worker's private /var/tmp to
// be removed.
func privateTmpGone(t *testing.T, limit time.Duration) {
	t.Helper()
	deadline := time.Now().Add(limit)
	for {
		left, _ := filepath.Glob("/var/tmp/systemd-private-*-carlos-dbread@*")
		if len(left) == 0 {
			return
		}
		if time.Now().After(deadline) {
			t.Fatalf("a worker's private tmp outlived it: %v", left)
		}
		time.Sleep(200 * time.Millisecond)
	}
}

func unitsActive(t *testing.T) int {
	n, err := dbReadUnits(context.Background())
	if err != nil {
		t.Fatal(err)
	}
	return n
}

// dbreadWaitFor polls ok until it holds or limit passes. (waitFor is
// housekeeper_test.go's, with another signature: plan review finding 2.)
func dbreadWaitFor(t *testing.T, limit time.Duration, ok func() bool) {
	t.Helper()
	deadline := time.Now().Add(limit)
	for !ok() {
		if time.Now().After(deadline) {
			t.Fatal("timed out")
		}
		time.Sleep(200 * time.Millisecond)
	}
}

// T2: a forwarded query through the real socket and the real service,
// installed by the real ensureSystemUnits; the socket is the worker's stdin
// and stdout (codex 2). The probe that makes the box capable runs the
// default SelfView inside the unit (plan review finding 1).
func TestRootDBReadServesThroughTheInstalledUnits(t *testing.T) {
	r := newDBReadRunner(t, "40g")
	id, reply := r.submit(dbreads.OpQuery, "SELECT count(*) AS n FROM t")
	rep, _ := r.payload("serve", true, id)
	if rep["capable"] != true {
		t.Fatalf("the installed worker failed its probe: %v", rep)
	}
	rows, res := r.answer(id, reply, dbreads.StreamRows)
	if res.State != dbreads.StateDone || string(rows) != "n\n30\n" {
		t.Fatalf("result %+v rows %q", res, rows)
	}
	privateTmpGone(t, 10*time.Second)
}

// T3: from inside the worker, nothing outside its scratch is reachable,
// including any network interface but loopback; the private tmp is gone
// after a normal end, a cancel and kill -9 of the agent. Mutation: remove
// PrivateNetwork=yes from the installed unit; "see an interface other than
// loopback" succeeds and this test is red (plan review finding 17).
func TestRootDBReadWorkerSandbox(t *testing.T) {
	r := newDBReadRunner(t, "40g")
	r.marker("witness", true)
	rep, _ := r.payload("witness", true, "")
	r.marker("witness", false)
	report, _ := rep["report"].(map[string]any)
	if len(report) != 14 {
		t.Fatalf("an incomplete witness report: %v", rep)
	}
	for name, v := range report {
		failed := v.(string) != ""
		if name == "write /var/tmp" {
			if failed {
				t.Errorf("the positive control failed: %s", v)
			}
			continue
		}
		if !failed {
			t.Errorf("%s succeeded inside the worker", name)
		}
	}
	// A cancel, then kill -9 of the agent, mid-read.
	r.marker("hang-restore", true)
	defer r.marker("hang-restore", false)
	id, _ := r.submit(dbreads.OpQuery, "SELECT 1")
	_, cmd := r.payload("serve-and-hang", false, "")
	dbreadWaitFor(t, 30*time.Second, func() bool { return unitsActive(t) >= 1 })
	if _, err := r.store().Put(context.Background(), dbreads.CancelKey(id), nil, ""); err != nil {
		t.Fatal(err)
	}
	dbreadWaitFor(t, 20*time.Second, func() bool { return unitsActive(t) == 0 })
	privateTmpGone(t, 10*time.Second)
	cmd.Process.Kill()
	cmd.Wait()
	r.submit(dbreads.OpQuery, "SELECT 1")
	_, cmd = r.payload("serve-and-hang", false, "")
	dbreadWaitFor(t, 30*time.Second, func() bool { return unitsActive(t) >= 1 })
	cmd.Process.Signal(syscall.SIGKILL)
	cmd.Wait()
	dbreadWaitFor(t, 20*time.Second, func() bool { return unitsActive(t) == 0 })
	privateTmpGone(t, 10*time.Second)
}

// T12 with real units. The disk floor: /var/tmp on a 12 GiB tmpfs fits one
// read's floor reservation (5 GiB and 10%) and not two. The first read is
// running (its unit observed) before the second is submitted, so which read
// waits never depends on queue order (plan review finding 16); the agent
// passes every second and still never picks the second while the first
// holds its floor. A fixture database small enough for the runner cannot
// make the plan's growth bind, so the no-room result itself is pinned by
// TestReadTooLargeAndNoRoom. Then the agent is killed mid-read: the
// restarted agent takes no read and no probe while the old unit is active,
// the old worker ends within 5 s of losing the connection though its
// restore ignores the context, and the restarted agent admits the held-back
// read once the unit and its scratch are gone. Mutations: drop the orphan
// rule in reconcileLocked (the restarted agent picks beside the old unit),
// or drop the worker's 5 s exit (the old unit outlives the 15 s bound).
func TestRootDBReadAdmissionWithRealUnits(t *testing.T) {
	r := newDBReadRunner(t, "12g")
	r.marker("hang-restore", true)
	r.submit(dbreads.OpQuery, "SELECT 1")
	_, hung := r.payload("serve-and-hang", false, "")
	dbreadWaitFor(t, 30*time.Second, func() bool { return unitsActive(t) == 1 })
	second, reply := r.submit(dbreads.OpQuery, "SELECT count(*) AS n FROM t")
	time.Sleep(5 * time.Second) // five passes
	if _, _, err := r.store().Get(context.Background(), dbreads.PickedKey(second)); err == nil {
		t.Fatal("a second read was picked with room for one")
	}
	hung.Process.Signal(syscall.SIGKILL)
	hung.Wait()
	killedAt := time.Now()
	rep, _ := r.payload("restarted", true, second)
	if rep["units_at_start"].(float64) < 1 {
		t.Fatalf("the old unit was gone before the restarted agent looked: %v", rep)
	}
	if rep["capable"] == true || rep["picked"] == true {
		t.Fatalf("a restarted agent admitted beside the old unit: %v", rep)
	}
	dbreadWaitFor(t, 20*time.Second, func() bool { return unitsActive(t) == 0 })
	if gone := time.Since(killedAt); gone > 15*time.Second {
		t.Fatalf("the old worker took %s to stop; its 5 s exit did not hold", gone)
	}
	privateTmpGone(t, 10*time.Second)
	r.marker("hang-restore", false)
	rep, _ = r.payload("serve", true, second)
	if rep["capable"] != true {
		t.Fatalf("the agent did not admit once the unit was gone: %v", rep)
	}
	if rows, res := r.answer(second, reply, dbreads.StreamRows); res.State != dbreads.StateDone || string(rows) != "n\n30\n" {
		t.Fatalf("the held-back read: %+v %q", res, rows)
	}
}

// T13: a socket whose service is missing, masked, failing to start or
// speaking another protocol version withdraws db-read-1 within one probe and
// edges pass; a read whose worker fails to start withdraws it at once
// through the real loop (plan review finding 15); a box running two reads
// keeps it (codex 9).
func TestRootDBReadReadiness(t *testing.T) {
	r := newDBReadRunner(t, "40g")
	capable := func() bool {
		rep, _ := r.payload("probe", true, "")
		return rep["capable"] == true && rep["published"] == true
	}
	if !capable() {
		t.Fatal("baseline: not capable")
	}
	body, err := os.ReadFile(dbreadServiceFile)
	if err != nil {
		t.Fatal(err)
	}
	// Cleanup removes first: during the mask the path is a symlink to
	// /dev/null, and writing through it would write nothing.
	t.Cleanup(func() {
		os.Remove(dbreadServiceFile)
		os.WriteFile(dbreadServiceFile, body, 0o644)
		runSystemctl("daemon-reload")
	})
	if err := os.Remove(dbreadServiceFile); err != nil {
		t.Fatal(err)
	}
	mustSystemctl(t, "daemon-reload")
	if capable() {
		t.Error("capable with the service missing")
	}
	if err := os.WriteFile(dbreadServiceFile, body, 0o644); err != nil {
		t.Fatal(err)
	}
	mustSystemctl(t, "daemon-reload")
	if !capable() {
		t.Fatal("not capable once the service file is back")
	}
	// Masked where the unit is installed (plan review finding 27): a mask is
	// a /dev/null symlink, and only one in /etc/systemd/system itself
	// outranks the unit file ensureSystemUnits writes there. `systemctl
	// mask` refuses while the file exists, and `--runtime` would land in
	// /run/systemd/system, which /etc outranks; so swap the file for the
	// symlink by hand, and prove the mask took before asking.
	if err := os.Remove(dbreadServiceFile); err != nil {
		t.Fatal(err)
	}
	if err := os.Symlink("/dev/null", dbreadServiceFile); err != nil {
		t.Fatal(err)
	}
	mustSystemctl(t, "daemon-reload")
	if out, _ := runSystemctl("show", "-p", "LoadState", "--value", "carlos-dbread@probe.service"); strings.TrimSpace(out) != "masked" {
		t.Fatalf("the mask did not take: LoadState %q", out)
	}
	if capable() {
		t.Error("capable with the service masked")
	}
	if err := os.Remove(dbreadServiceFile); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(dbreadServiceFile, body, 0o644); err != nil {
		t.Fatal(err)
	}
	mustSystemctl(t, "daemon-reload")
	for _, m := range []string{"exit-1", "version-2"} {
		r.marker(m, true)
		if capable() {
			t.Errorf("capable with %s", m)
		}
		r.marker(m, false)
	}
	if !capable() {
		t.Fatal("not capable again once restored")
	}

	// A read whose worker fails to start, through the real loop.
	_, loop := r.payload("fail-start", false, "")
	dbreadWaitFor(t, 30*time.Second, func() bool { _, err := os.Stat(filepath.Join(r.dir, "probed")); return err == nil })
	r.marker("exit-1", true)
	r.submit(dbreads.OpQuery, "SELECT 1")
	if err := os.WriteFile(filepath.Join(r.dir, "go"), nil, 0o644); err != nil {
		t.Fatal(err)
	}
	if err := loop.Wait(); err != nil {
		t.Fatalf("fail-start payload: %v", err)
	}
	if _, err := os.Stat(filepath.Join(r.dir, "withdrawn")); err != nil {
		t.Fatal("the loop kept db-read-1 after a worker failed to start")
	}
	r.marker("exit-1", false)

	r.marker("hang-restore", true)
	defer r.marker("hang-restore", false)
	r.submit(dbreads.OpQuery, "SELECT 1")
	r.submit(dbreads.OpQuery, "SELECT 1")
	rep, _ := r.payload("busy-probe", true, "")
	if rep["capable"] != true {
		t.Fatalf("a box running two reads lost the capability: %v", rep)
	}
}

// TestRootDBReadPayload is the agent half, run as carlos by payload();
// never run it by name.
func TestRootDBReadPayload(t *testing.T) {
	scenario := os.Getenv("DBREAD_RUNNER_PAYLOAD")
	if scenario == "" {
		t.Skip("run by the db-read root-runner tests as their carlos child")
	}
	dir := os.Getenv("DBREAD_RUNNER_DIR")
	pubRaw, _ := base64.StdEncoding.DecodeString(os.Getenv("DBREAD_RUNNER_PUB"))
	store := release.NewDirStore(filepath.Join(dir, "store"))
	a := dbreads.NewAgent(dbreads.AgentConfig{
		Store: store, Region: "uk", Box: "runner", Boot: newBootID(), Pub: ed25519.PublicKey(pubRaw),
		HibernatePrefix: "instances",
		OpenReplica: func(_ context.Context, prefix string) (dbdoor.ReplicaReader, error) {
			return lsfile.NewReplicaClient(filepath.Join(dir, "replica", prefix)), nil
		},
		DialWorker: dialDBReadWorker, Units: dbReadUnits, Free: varTmpFree, Logf: t.Logf,
	})
	ctx := context.Background()
	report := map[string]any{}
	say := func() {
		b, _ := json.Marshal(report)
		fmt.Println(dbreadReportPrefix + string(b))
	}
	switch scenario {
	case "probe":
		a.Probe(ctx)
		report["capable"] = a.Capable()
		report["published"] = len(withDBReadCapability(nil, a.Capable())) == 1
	case "serve":
		a.Probe(ctx)
		report["capable"] = a.Capable()
		id := os.Getenv("DBREAD_RUNNER_ID")
		deadline := time.Now().Add(2 * time.Minute)
		for time.Now().Before(deadline) {
			a.Pass(ctx)
			a.Wait()
			if _, _, err := store.Get(ctx, dbreads.ResultKey(id)); err == nil {
				break
			}
			time.Sleep(time.Second)
		}
	case "serve-and-hang":
		a.Probe(ctx)
		for { // the parent kills this process
			a.Pass(ctx)
			time.Sleep(time.Second)
		}
	case "restarted":
		units, _ := dbReadUnits(ctx)
		report["units_at_start"] = units
		a.Probe(ctx)
		a.Pass(ctx)
		report["capable"] = a.Capable()
		_, _, err := store.Get(ctx, dbreads.PickedKey(os.Getenv("DBREAD_RUNNER_ID")))
		report["picked"] = err == nil
	case "fail-start":
		// The production loop: probe at start, a pass on a nudge, a probe
		// as soon as a read's worker fails to start.
		nudge := make(chan struct{}, 1)
		rctx, cancel := context.WithCancel(ctx)
		defer cancel()
		go a.Run(rctx, nudge)
		for !a.Capable() {
			time.Sleep(100 * time.Millisecond)
		}
		os.WriteFile(filepath.Join(dir, "probed"), nil, 0o644)
		for {
			if _, err := os.Stat(filepath.Join(dir, "go")); err == nil {
				break
			}
			time.Sleep(100 * time.Millisecond)
		}
		nudge <- struct{}{}
		deadline := time.Now().Add(30 * time.Second)
		for a.Capable() && time.Now().Before(deadline) {
			time.Sleep(100 * time.Millisecond)
		}
		if !a.Capable() {
			os.WriteFile(filepath.Join(dir, "withdrawn"), nil, 0o644)
		}
	case "busy-probe":
		a.Probe(ctx)
		a.Pass(ctx)
		deadline := time.Now().Add(30 * time.Second)
		for n, _ := dbReadUnits(ctx); n < 2 && time.Now().Before(deadline); n, _ = dbReadUnits(ctx) {
			time.Sleep(200 * time.Millisecond)
		}
		a.Probe(ctx)
		report["capable"] = a.Capable()
	case "witness":
		c, err := dialDBReadWorker(ctx)
		if err != nil {
			t.Fatal(err)
		}
		var w map[string]string
		json.NewDecoder(io.LimitReader(c, 1<<20)).Decode(&w)
		c.Close()
		report["report"] = w
	}
	say()
}
```

- [ ] **Step 3: Cross-compile the root-runner binary locally**

Run (sandbox off): `GOOS=linux GOARCH=arm64 go test -c -tags rootrunner -o "$TMPDIR/dbreads-rootrunner.test" ./internal/host && rm "$TMPDIR/dbreads-rootrunner.test"`
Expected: it builds. Do not run it on DOCS-T1.

- [ ] **Step 4: Run them on the root runner**

These need the sandbox off (assumed-role credentials). Before the run, check for leftover instances tagged `purpose=plan14-root-runner`. Then, one test per run, each with a bounded timeout:

```bash
~/.cache/tmp/claude-1001/own/after236/root-runner.py --worktree "$PWD" --pkg ./internal/host --run '^TestRootDBReadServesThroughTheInstalledUnits$'
~/.cache/tmp/claude-1001/own/after236/root-runner.py --worktree "$PWD" --pkg ./internal/host --run '^TestRootDBReadWorkerSandbox$'
~/.cache/tmp/claude-1001/own/after236/root-runner.py --worktree "$PWD" --pkg ./internal/host --run '^TestRootDBReadAdmissionWithRealUnits$'
~/.cache/tmp/claude-1001/own/after236/root-runner.py --worktree "$PWD" --pkg ./internal/host --run '^TestRootDBReadReadiness$'
```

Expected: four PASS lines, each with its run id. Record the run ids in the branch description. If the runner script is unavailable to the executing session, list the four tests under "Root-runner acceptance: pending" in the report, with the commit they apply to, and stop: the plan is not accepted until they pass.

- [ ] **Step 5: Commit**

```bash
git add internal/host/dbreads_worker_dispatch_linux_test.go internal/host/dbreads_rootrunner_linux_test.go internal/host/plan14_generation_registry_root_linux_test.go
git commit -m "host: T2, T3, T12 and T13 on the root runner, through the installed units"
```

---

### Task 16: DBF-31 in the CLI page

Waits for Task 1 Step 5 (DBF-31 approved).

**Files:**
- Modify: `docs/site/cli.md` (the `carlos system` section, after "Host lifecycle guard")
- Modify: `approved_db_forward_copy_test.go` (`dbForwardCopyBuilt`)

**Interfaces:**
- Consumes: the approved DBF-31 text from `docs/superpowers/plans/2026-10-22-db-region-forward-copy.md`.

- [ ] **Step 1: Add the id to the built list**

In `approved_db_forward_copy_test.go`: `var dbForwardCopyBuilt = []string{"DBF-31"}`.

- [ ] **Step 2: Run the gate to verify it fails**

Run: `go test . -run 'TestDBForwardBuiltCopy' -count=1`
Expected: FAIL in `TestDBForwardBuiltCopyIsApplied`: "docs/site/cli.md does not contain the approved text".

- [ ] **Step 3: Write the docs**

In `docs/site/cli.md`, after the "Host lifecycle guard" subsection of `### carlos system`, add (the paragraph is the approved row's text, on one line):

```markdown
#### carlos system db-worker

carlos system db-worker runs on platform boxes only. systemd starts it for each forwarded database query. you never run it yourself.
```

If Paul changed the text in review, write his text, not this.

- [ ] **Step 4: Run the gate and the docs check**

Run: `go test . -run 'TestDBForward' -count=1 && go test ./internal/docsite/ -count=1`
Expected: PASS.

- [ ] **Step 5: Commit**

```bash
git add docs/site/cli.md approved_db_forward_copy_test.go
git commit -m "docs: carlos system db-worker (DBF-31)"
```

---

### Task 17: Census, test weights, merge main, CI, and the dev LIST-rate check

**Files:**
- Create: `internal/provision/testdata/plan14-root-reads-db-region-forward-1.tsv`
- Modify: `internal/provision/plan14_root_reads_test.go` (load the overlay last; the seal)
- Create: `internal/provision/db_region_forward_census_test.go` (9B8 entries)
- Modify: `internal/provision/plan9_b8_census_test.go:369` (the inventory function `TestPlan9B8RecordWriteCensus` calls)
- Create: `docs/superpowers/notes/census-proposal-db-region-forward-1.md`
- Modify: `.amadan/test-weights.tsv` (only if a new console or root test takes a second or more)

**Interfaces:**
- Consumes: `rootReadProduction`, `censusProduction`, `rootReadLegacyFingerprint`, `rootReadLegacySeal`, `loadRootReadInventory`, `checkRootReadLegacy` (`internal/provision` tests).

- [ ] **Step 1: Merge main**

```bash
git fetch origin && git merge origin/main
go build ./...
```
Resolve conflicts, then re-read `TestPlan14RootReadCensus` to find the overlay main now loads last and the seal it sets.

- [ ] **Step 2: Dump the new and changed census units**

Create a temporary file `internal/provision/zz_dbforward_dump_test.go` (never committed):

```go
package provision

import (
	"strings"
	"testing"
)

func TestZZDBForwardCensusDump(t *testing.T) {
	root := censusRoot(t)
	got, err := rootReadProduction(root)
	if err != nil {
		t.Fatal(err)
	}
	for _, e := range got.Entries {
		for _, p := range []string{"db.go", "internal/dbquery/", "internal/dbreads/", "internal/dbdoor/", "internal/host/dbreads", "internal/host/units/carlos-dbread", "internal/host/systemunits.go", "internal/host/edgesfile.go", "internal/host/agent.go", "internal/console/apidb.go", "system.go"} {
			if strings.HasPrefix(e.File, p) {
				t.Logf("READ\t%s\t%s\t%s\t%s", e.File, e.Unit, e.Kinds, e.Digest)
			}
		}
	}
	for dir, hash := range got.Coverage {
		t.Logf("@coverage\t%s\t%s", dir, hash)
	}
	writes, err := censusProduction(root)
	if err != nil {
		t.Fatal(err)
	}
	for id, w := range writes {
		if strings.HasPrefix(id, "internal/dbreads/") {
			t.Logf("WRITE\t%s\t%s\t%s\t%s", w.File, w.Unit, w.Kinds, w.Digest)
		}
	}
}
```

Run (sandbox off): `go test ./internal/provision/ -run 'TestZZDBForwardCensusDump|TestPlan14RootReadCensus$|TestPlan9B8RecordWriteCensus$' -count=1 -v 2>&1 | tee "$TMPDIR/dbf-census.log"`. The two census tests fail and name every unclassified, changed or stale unit and envelope; the dump gives each unit's kinds and digest.

- [ ] **Step 3: Write the overlay**

Create `internal/provision/testdata/plan14-root-reads-db-region-forward-1.tsv`. Header lines (`#`) say what the branch is, that it is loaded LAST after the overlay main loads last, that every row is `rev3=PROPOSED-db-region-forward-1` awaiting the census owner on #280, and that the seal moves. Then one row per unit the census reported, in the formats below (tab-separated; `<kinds>` and `<digest>` are the dump's):

- **The retired CLI runner** (its reads moved to `dbquery.RunContext`):
  ```
  @remove	db.go	runQueryContext
  @removed	db.go	runQueryContext	H3	census-ruling-db-region-forward-1 (PROPOSED, awaiting the census owner on #280): still declared, and reads nothing now: it calls dbquery.RunContext, which holds its former open and query unchanged but for the immutable=1 option, an accepted-legacy row in this overlay. It runs in the carlos CLI as the person.
  ```
- **A new or changed legacy unit** is two lines, the frozen declaration and the entry:
  ```
  @legacy	<fingerprint>	<file>	<unit>	legacy	accepted-legacy	<basis>	<kinds>	<digest>
  <file>	<unit>	legacy	accepted-legacy	<basis>	<kinds>	<digest>
  ```
  with `<basis>` by identity:
  - `internal/dbquery` `RunContext`: `accepted-legacy;rev3=PROPOSED-db-region-forward-1;basis=root-input (J4, the footing main gave db.go runQueryContext); the carlos CLI on a person's machine, as the person, and the db-read worker (carlos system db-worker, carlos-dbread@.service, a DynamicUser with no network): db.go's runQueryContext body moved unchanged but for the immutable=1 open option the worker passes; opens one restored copy read-only (mode=ro, query_only, temp_store(2), no attached databases) and runs one guarded statement; neither caller is root and neither decides anything for root`
  - agent units in `internal/dbreads` (`Agent.*`, `chunkWriter.*`, `putCreateOnly`, `sendFile`, `relay`, `readFrame` when it is the agent's): `accepted-legacy;rev3=PROPOSED-db-region-forward-1;basis=route-and-input (J1,J4, as the offline move's agent units); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, <one clause: what this unit reads, for example "reads the region's db-reads/ queue listing and one request object, verified against the root key">; makes no root decision`
  - worker units in `internal/dbreads` (`ServeWorker`, `receiveFile`, `SelfView`, `StdinConn`, `CarlosUID`, `RunWorker*`): `accepted-legacy;rev3=PROPOSED-db-region-forward-1;basis=root-input (J4); the db-read worker (carlos system db-worker, carlos-dbread@.service, a DynamicUser with no network, PrivateTmp, /data and /etc/carlos hidden): new, <one clause>; reads only the files the agent sent and its own scratch`
  - `internal/dbdoor` `ListLevel`, `PlanFrom`, `finishPlan`, `listing.*`, `RestoreLocal`: `accepted-legacy;rev3=PROPOSED-db-region-forward-1;basis=root-input (J4, as main's dbdoor units); the console's db door, the carlos CLI as the person, the agent and the db-read worker: <one clause>`
  - `internal/host/dbreads*.go` (`dbReadUnits`, `varTmpFree`, `armDBReads`): `accepted-legacy;rev3=PROPOSED-db-region-forward-1;basis=root-input (J4); the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): new, <for example "one Statfs of /var/tmp for the disk reservation" or "systemctl list-units of carlos-dbread@ units, readable without privilege">`
  - the two unit files, as `internal/host/units/carlos-instance-cmd@.service` took: `<file>	external	legacy	accepted-legacy	accepted-legacy;rev3=PROPOSED-db-region-forward-1;basis=the db-read worker's units (written by root's ensureSystemUnits; carlos-dbread.socket bound by PID 1 and owned by carlos; carlos-dbread@.service runs as a DynamicUser with no network, its own PrivateTmp, /data, /var/lib, /opt/carlos and /run/carlos empty, /etc/carlos inaccessible): new	file:external@0	<digest>`
  - changed existing legacy units (for example `edgesFileLoop`, `ensureSystemUnits`, `runAgent`, `listReplicaLevel`, `dbClassRefusal` if the census lists them): re-frozen at main's own class and basis text with this branch's change appended in one clause, the form console-switcher-filter used.
- **The probe** (`Agent.Probe` / `Agent.probe`, whichever the census names), one row, not legacy:
  ```
  internal/dbreads/agent.go	Agent.probe	diagnostic	J4	rev3=PROPOSED-db-region-forward-1;identity=the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos);basis=the readiness probe: a hello on its own worker connection; decides only whether this box publishes db-read-1, never any root action	<kinds>	<digest>
  ```
- **Envelopes:** one `@coverage	<dir>	<hash>` line for every directory the census reports changed or new.

Compute each `@legacy` fingerprint straight from the row's seven fields, never by loading the unfinished overlay: the loader refuses a `@legacy` line whose fingerprint is wrong (`plan14_root_reads_test.go:413-421`) and an `@remove` of an entry no earlier file declared (`:470`), so it cannot bootstrap its own fingerprints (plan review finding 5). Add to the temporary dump test:

```go
// TestZZDBForwardFingerprints prints the @legacy line for every plain legacy
// row of the overlay, from the row's own seven fields.
func TestZZDBForwardFingerprints(t *testing.T) {
	raw, err := os.ReadFile(filepath.Join(censusRoot(t), "internal/provision/testdata/plan14-root-reads-db-region-forward-1.tsv"))
	if err != nil {
		t.Fatal(err)
	}
	for _, line := range strings.Split(string(raw), "\n") {
		col := strings.Split(line, "\t")
		if len(col) != 7 || strings.HasPrefix(line, "#") || strings.HasPrefix(line, "@") || col[2] != "legacy" {
			continue
		}
		e := classifiedRootRead{rootReadEntry: rootReadEntry{File: col[0], Unit: col[1], Kinds: col[5], Digest: col[6]}, Class: col[2], Task: col[3], Basis: col[4]}
		t.Logf("@legacy\t%s\t%s", rootReadLegacyFingerprint(e), line)
	}
}
```

(add `"os"` and `"path/filepath"` to the dump file's imports). Write the plain rows first, run this, paste each printed `@legacy` line above its row, and only then run `TestPlan14RootReadCensus`, which loads the finished overlay over main's layered inventory, so its `@remove` finds main's `db.go runQueryContext` entry. Plans 2 and 3 use this same procedure with their own overlay file names.

- [ ] **Step 4: Load the overlay last, with the seal**

In `TestPlan14RootReadCensus`, after the last overlay main loads and before the final `errs := append(compareRootReads(got, inv), ...)` line, add:

```go
	// Census overlay db-region-forward-1 (db region forward plan 1: the box
	// side and the wire, dark), loaded last, after <main's last overlay>.
	// PROPOSED-db-region-forward-1, asked of the census owner on #280
	// (docs/superpowers/notes/census-proposal-db-region-forward-1.md).
	// db.go runQueryContext is retired by an H3 removal; its body is
	// internal/dbquery RunContext, accepted legacy at the same J4 footing
	// with both callers named; the agent's db-reads units are accepted
	// legacy at J1 and J4, the worker's at J4, the probe is diagnostic, and
	// the two carlos-dbread units join as external units. Frozen
	// declarations are added, so the seal moves; <main's last overlay>'s is
	// checked first.
	if errs := checkRootReadLegacy(inv, seal); len(errs) != 0 {
		t.Fatal(errs)
	}
	if err = loadRootReadInventory(filepath.Join(root, "internal/provision/testdata/plan14-root-reads-db-region-forward-1.tsv"), &inv, true); err != nil {
		t.Fatal(err)
	}
	seal = "<the new seal>"
```

To get the new seal, add a temporary `t.Logf("seal %s", rootReadLegacySeal(inv))` right after the `loadRootReadInventory` call, run `go test ./internal/provision/ -run 'TestPlan14RootReadCensus$' -count=1 -v`, paste the value, and delete the `t.Logf`.

- [ ] **Step 5: The 9B8 entries**

Create `internal/provision/db_region_forward_census_test.go`, layered on whichever inventory function `TestPlan9B8RecordWriteCensus` calls on the merged main (at `5f341f33` it is `plans2WriteCensusInventory`):

```go
package provision

// Record-write census entries for db region forward plan 1, layered on
// plans2WriteCensusInventory. Reviewed by the branch author; the census owner
// rules on #280 (PROPOSED-db-region-forward-1). Every new Put is a
// conditional create under db-reads/ in the deployment bucket (picked, the
// sealed chunks, result.json), never an instance or sidecar record:
// nonrecord. There is no Delete site.
func dbRegionForward1WriteCensusInventory() []censusEntry {
	return append(append([]censusEntry(nil), plans2WriteCensusInventory()...),
		censusEntry{"internal/dbreads/agent.go", "Agent.elect", "nonrecord", "<kinds>", "<digest>"},
		censusEntry{"internal/dbreads/chunks.go", "putCreateOnly", "nonrecord", "<kinds>", "<digest>"},
	)
}
```

with one entry per unit the census lists as an unlisted site under `internal/dbreads/` (the `<kinds>` and `<digest>` are the dump's `WRITE` lines), and point `TestPlan9B8RecordWriteCensus` at `dbRegionForward1WriteCensusInventory()`.

- [ ] **Step 6: Run the census and remove the dump**

```bash
rm internal/provision/zz_dbforward_dump_test.go
go test ./internal/provision/ -run 'TestPlan14RootReadCensus$|TestPlan9B8RecordWriteCensus$|TestPlan14' -count=1
```
Expected: PASS.

- [ ] **Step 7: Write the census proposal**

Create `docs/superpowers/notes/census-proposal-db-region-forward-1.md` in the form of `census-proposal-console-switcher-filter.md`: status PROPOSED, the branch and its base, the overlay's name and load position, and one table row per unit (unit, change, executing identity, proposed disposition), the H3 removal, the two unit files, the 9B8 entries, the envelopes, and the old and new seals. Post it as a reply on amadan discussion #280 (`amadan discuss reply carlos/platform 280 -body -`), as the branch's agent account.

- [ ] **Step 8: Test weights**

The new top-level tests in `internal/console` and the root package are `TestDBReadsParityWithTheInRegionDoor` and the copy gate. Measure the console one without a full run:

```bash
go test -count=1 -json -run 'TestDBReadsParityWithTheInRegionDoor' ./internal/console/ > "$TMPDIR/dbf-weights.json"
grep '"Action":"pass"' "$TMPDIR/dbf-weights.json" | grep '"Test":"TestDBReadsParityWithTheInRegionDoor"'
rm "$TMPDIR/dbf-weights.json"
```
If its `Elapsed` is 1.0 or more, add a row `github.com/carlosframework/platform/internal/console	TestDBReadsParityWithTheInRegionDoor	<seconds>` to `.amadan/test-weights.tsv` in descending order among the console rows, keeping the header. Do not rewrite the file with `.amadan/test-weights.sh`: that needs a full package run.

- [ ] **Step 8b: Mutation checks (spec §11.4)**

Each mutation below must turn its test red. Make them in a copy of the tree, never in the worktree: `cp -a . "$TMPDIR/dbf1-mut"` once, then for each mutation edit the copy, run the named test there, record red or green, and revert the edit (`git -C "$TMPDIR/dbf1-mut" checkout -- <file>`). Remove the copy by its name when done.

| Mutation (in the copy) | Test that must fail |
|---|---|
| `Verify` returns the decoded request without calling `release.VerifyRootEnvelope` | `TestEnvelopeRefusesForgeryAndReplay`, `TestPassRefusesForgedEntriesAndUnsignedRequests` |
| `check` drops its `rec.Host != req.Host` and incarnation comparisons | `TestCheckIsTheRecordAsTheEnvelopeNamedIt`, `TestRecordChangeAtEveryStageWritesNoChunk` (the prefix-from-the-request mutation is plan 2's, through T1's second tenant) |
| `PrivateNetwork=yes` removed from `carlos-dbread@.service` | `TestDBReadUnitsCarryTheSandbox`; on the root runner, `TestRootDBReadWorkerSandbox` (its "see an interface other than loopback" witness, which needs no socket) |
| `SelfView` back on `net.Interfaces` | on the root runner, `TestRootDBReadServesThroughTheInstalledUnits` and `TestRootDBReadReadiness` (the probe fails inside the AF_UNIX-only unit) |
| `flushLocked` increments `seq` before the create is confirmed | `TestResultNamesOnlyConfirmedChunks` |
| `read` drops `settle` before a retry | `TestRetryWaitsForTheFirstWorkerToStop` |
| `retry` leaves the old reservation under the read's own key | `TestAdmissionRetryHoldsTheOldReservation` |
| `consider` drops the Draining check after the jitter | `TestADrainingBoxDoesNotPick` |
| `consider` drops the cancel read | `TestPassSkipsACancelledRequest` |
| `attempt` drops `askProbe` after a pre-ready `sendFile` or `readFrame` failure | `TestAWorkerThatNeverStartsAsksForAProbe`; on the root runner, `TestRootDBReadReadiness`'s fail-start case |
| `Run` drops a probe that admission skipped (no `retry`) (plan review finding 29) | `TestAProbeSkippedWhileTheUnitLingersRunsOnceItIsGone` |
| check B removed from `attempt` | `TestRecordChangeAtEveryStageWritesNoChunk` |
| `putCreateOnly` called with a non-empty `ifMatch`, or a `Delete` added after `result.json` | `TestReadNeverDeletesOrReplaces` |
| `elect` returns `false` without reading `picked` back | `TestElectionReadsBackALostAnswer` |
| `reconcileLocked` ignores `n > a.conns` | `TestAdmissionRefusesBesideAnOrphan`; on the root runner, `TestRootDBReadAdmissionWithRealUnits` |
| `MaxConnections` set to 2 | `TestAdmissionTwoReadsThenBusy`, `TestProbeOnTheThirdConnection` |
| the worker's `time.After(opt.Grace)` exit removed | `TestWorkerExitsWhenTheAgentGoesMidRestore` |

Record the table, with red for every row, in the branch description.

- [ ] **Step 9: Final local checks, push, describe, CI**

```bash
gofmt -l . ; go vet ./internal/dbreads/... ./internal/dbquery/ ./internal/dbdoor/ ./internal/host/
go build ./... && GOOS=darwin GOARCH=arm64 go build ./... && GOOS=windows GOARCH=amd64 go build ./...
git add internal/provision docs/superpowers/notes/census-proposal-db-region-forward-1.md .amadan/test-weights.tsv
git commit -m "census: db-region-forward-1 overlay (PROPOSED), 9B8 entries"
git push origin db-region-forward-1-box
amadan branch describe carlos/platform db-region-forward-1-box -body - < "$TMPDIR/dbf-1-description.md"
amadan ci status carlos/platform -branch db-region-forward-1-box
```
The description says: what plan 1 builds and that it is dark (no console asks until plan 2; boxes publish `db-read-1` only while their probe passes); the spec and plan paths; the root-runner run ids for T2, T3, T12, T13; the census proposal and that the ruling is owed on #280; the copy state (DBF-31 approved and built; the rest pending for plan 2). Expected: CI green on the tip. A red run is read, not re-run.

- [ ] **Step 10: Review, then merge**

Ask for the whole-branch review (Astra, by a committed brief, or Opus per AGENTS.md's delegation rule). After fixes and the census ruling: merge main again (Step 1), rebuild the overlay's digests if main moved anything, push, wait for green, squash to one commit per AGENTS.md, and merge only with `git merge-base --is-ancestor origin/main HEAD && amadan branch merge carlos/platform db-region-forward-1-box -expect <tip> -message "..."`. Read main's CI afterwards.

- [ ] **Step 11: The dev roll and the LIST-rate measurement (spec §5.8, §11.3)**

At the next dev roll, in Paul's order (dev boxes, dev console, check), once Paul has said to roll: after the dev boxes run this build, confirm in each box's edges file that `db-read-1` is published (`carlos` operator view of the edges files, or the console's fleet page), and measure the LIST rate the loop adds: the S3 request metrics or access log for the dev deployment bucket, `ListObjectsV2` requests on prefix `db-reads/queue/`, per box per hour, over at least one hour with no reads. Expect about 2 LISTs every 30 s per capable box plus 2 per serial move. Report the number on the branch's amadan discussion and in the plan 2 branch description before the flagship roll. No flagship roll happens in this plan.

