oficina / sheets Public

design: separate fixture identity and candidate boot prerequisites

Paul Campbell pushed by paul@keymail.dev c5ebba3488309fc9c7ee341f8e4d16b92e76edba parent 1aca44c
1 file changed, +10 −4
  • docs/superpowers/specs/2026-09-07-canary-fixture-bootstrap.md +10 −4

CI passed — run details

Intent

Attributed to this commit: 13.1 g CO₂e (863378 tokens). This is an attribution, not a measurement — usage counted from this commit's own marker forward to the next one on test/canary-session-fixture, never backward from it. A turn that produced more than one commit books all of its tokens to the last one, and a concurrent session on this branch can add to the same figure. Some of it was priced using the shared default rate, because no model-specific factor row exists yet for at least one model involved. The Carbon view has the repo total, which is never derived from this attribution.

diff --git a/docs/superpowers/specs/2026-09-07-canary-fixture-bootstrap.md b/docs/superpowers/specs/2026-09-07-canary-fixture-bootstrap.md
index 335b5bc..1cd62ef 100644
--- a/docs/superpowers/specs/2026-09-07-canary-fixture-bootstrap.md
+++ b/docs/superpowers/specs/2026-09-07-canary-fixture-bootstrap.md
@@ -1,6 +1,6 @@
# Isolated Sheets canary session fixture
-Status: proposed fallback for Fable review; do not deploy yet. Normal SMTP-based sign-in remains preferred and root has asked the user about a controlled mailbox. This design is only for testing unchanged session validation and editor behavior if that mailbox is unavailable.
+Status: revision 2 proposed fallback; Fable 5.1 (claude-fable-5-1) requested changes at 1aca44c, incorporated below for re-review. Isolated branch test/canary-session-fixture, Amadan discussion 21. Do not deploy yet. Normal SMTP-based sign-in remains preferred and root has asked the user about a controlled mailbox. This design is only for testing unchanged session validation and editor behavior if that mailbox is unavailable.
## Target and boundary
@@ -17,7 +17,11 @@ Use a temporary reviewed bootstrap binary on this isolated instance, then replac
- Validate both exact cleaned absolute paths and exact host-derived basenames. Reject parent traversal, a symlink database file, or a resolved parent directory outside the compiled expected root. For a fresh nonexistent DB, resolve/check the existing parent directory before opening it; after opening, confirm the path still identifies the expected file. Do not derive the expected paths from fixture-supplied environment values. If the deployment uses a non-default DataDir, review and compile that one actual absolute path rather than accepting arbitrary directories.
- STATE_DIRECTORY is not required for this exec-child shape. If present, it must not contradict the confirmed runtime paths, but its absence alone is not a failure. Supporting a systemd unit-backed shape later requires a separate explicit guard variant, not a basename-only fallback.
- Before deployment, root verifies the control-plane route has this exact host, named environment and canary-only channel. Runtime path/origin guards complement that check; neither a release name nor an HTTP Host header alone establishes isolation.
-- Refuse bootstrap if any app content or member/grant/session row already exists. This is a fresh-fixture tool, not a repair or reset tool. Existing migration ledger rows alone are harmless. Never clear tables to make the precondition pass.
+- Refuse bootstrap if any app content or member/grant/session row already exists. This is a fresh-fixture tool, not a repair or reset tool. Enumerate all application/framework user tables from sqlite_master and require them empty, except the existing migration ledger and the one exact idempotent sessions row. Exclude only SQLite internal tables and the exact framework migration-ledger name. Test that this enumeration covers every table BootSchema creates (currently 12 Sheets tables plus sessions, auth_links and auth_sessions). Existing migration ledger rows alone are harmless. Never clear tables to make the precondition pass.
+
+## Candidate boot and transport isolation
+
+Before building or deploying, root configures the named canary environment with CARLOS_SMTP_HOST=smtp-fixture.invalid, CARLOS_SMTP_FROM=oficina-fixture@example.test and CARLOS_SMTP_PORT=587. CARLOS_SMTP_USER and CARLOS_SMTP_PASS must be explicitly empty in the resolved child environment; root verifies supported named-environment semantics suppress any inherited credentials. These are synthetic nondelivering values, not a usable SMTP service. The candidate requires nonempty host/from to boot at a non-loopback origin even when session fixtures bypass email delivery. Bootstrap calls the same sheets.LoadAuthEnv as the normal candidate and validates this exact synthetic transport configuration. Never POST /signin during fixture assertions; local browser tests must intercept/fail any attempted sign-in POST. Normal GET /signin as a redirect destination remains valid. Email delivery remains untested. Root confirms exact resolved database path and transport binding before bootstrap implementation/deployment guards are finalized.
## Session material and initialization
@@ -41,8 +45,8 @@ Playwright state sets the cookie __Host-rastrillo_session for the exact HTTPS ca
## Deployment sequence and assertions
1. Record production process version and route/channel/environment bindings without reading secrets. Verify isolated canary has fresh keys and the expected empty database.
-2. After Fable approves bootstrap design/code and local fixture tests, deploy its uniquely stamped binary only to the explicit canary host/channel with carlos deploy. Verify bootstrap /api/version and that every non-platform route refuses; no app assertions yet.
-3. Remove the fixture-specific hash/run/expiry settings from the named environment before replacing bootstrap. They are not used by the normal candidate.
+2. After Fable approves bootstrap design/code and local fixture tests, build the separate cmd/sheets-fixture entry point with a distinct make fixture-release target. It must require a clean tree and stamp rastrillo.BuildVersion as <sha>-fixture-<runID>. The normal candidate is built by unchanged make release and reports its plain commit SHA. Assert these stamps differ before deployment and in the served step-2/step-4 checks. Deploy the uniquely stamped bootstrap binary only to the explicit canary host/channel with carlos deploy. Verify bootstrap /api/version and that every non-platform route refuses; no app assertions yet.
+3. Remove the fixture-specific hash/run/expiry settings from the named environment before replacing bootstrap. They are not used by the normal candidate. A hibernation/re-wake during this window makes the still-selected bootstrap refuse to boot; that is expected fail-closed behavior until candidate replacement, not evidence of a platform failure.
4. Deploy the exact clean candidate built with make release. Poll process-served /api/version until it equals the intended candidate SHA; verify the canary channel no longer names the bootstrap release. Verify production still names its previously recorded release. Never treat an edge version header or a successful promote as process proof.
5. Only now open Playwright with the private cookie state. Verify /sheets accepts this fixture session, unsigned and random-cookie requests cannot write, and then run deployed clipboard/batch, clear/reopen version regression, reload, second-observer and scriptless-table checks. Record candidate SHA alongside outcomes.
6. Do not claim these checks exercised email delivery, pending-cookie magic-link binding, SMTP credentials or mailbox access. They certify real persisted-session validation and candidate editor behavior only. Normal SMTP sign-in remains a separate readiness check.
@@ -57,6 +61,8 @@ Do not delete production routes, releases, keys, backups or configuration during
Fable review, wrong-host/wrong-origin/nonempty-database/expired-session/local-session-acceptance tests, supported CLI route/environment inspection, bootstrap replacement proof, and exact candidate process SHA. No bootstrap deployment has occurred as part of writing this proposal.
+Required focused tests also include: relative DB arguments rejected before Resolve can join them; wrong directory with matching basename; symlink DB/parent; wrong socket; exact idempotency without expiry extension; same hash/different expiry refusal; normal sessions.New plus auth.RequireSession accepting the fixture and refusing random/expired cookies; teardown with old cookie redirecting to /signin and deleted row. Add an import-graph gate using go list -deps ./cmd/sheets that rejects the fixture package: production candidate must have no dependency on bootstrap code. The temporary command serves only platform health/version routes, never the application router. No fixture implementation or build target is added to the normal candidate branch.
+
## Native seed path
The existing platform supports a first-boot seed argv on an instance record; ExecBackend.Seed invokes that release binary with the configured argv followed by --db <path>, under the same merged environment, only when no local database or replica exists. This is an existing supported lifecycle, not an HTTP auth mechanism. It can be used only if root verifies the actual instance seed configuration through the supported CLI/API and Fable reviews the separate bootstrap command. The command must retain the same origin/run/owner/empty-database/exact-DB-path guards; a one-shot native seed has no socket argument and must verify the corresponding expected route socket in root's control-plane preflight. It writes ordinary session hashes into the existing schema, exits, and introduces no fixture command into the normal candidate. The candidate's deployed manifest/instance record must not keep a bootstrap seed argv referring to unsupported candidate commands. The initial fallback remains the simpler reviewed startup-only bootstrap; no native seed configuration has been changed.