oficina / sheets Public
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.
Target and boundary
The only permitted target is app sheets, account bds, instance overnight-sheets.bds.oncarlos.com, channel canary/overnight-batch, with named environment overnight-batch, separately bound by root. Root has verified current platform CLI supports instance environment binding. Never change the app's default environment, production origin or production channel. The fixture receives fresh canary SHEETSDEK and SHEETSINSTANCE_KEY and an owner address oficina-fixture@example.test. It does not read or copy production secrets, sessions, databases or content.
Use a temporary reviewed bootstrap binary on this isolated instance, then replace it with the exact normal candidate binary. The bootstrap binary contains no login endpoint, alternate auth middleware, universal cookie, content endpoint or API backdoor. It initializes existing schema/session rows during startup only, then serves only platform health/version responses while awaiting replacement. It never serves the editor, so no browser behavior can accidentally be certified against bootstrap code.
Host and environment guards
- Compile the single expected HTTPS origin and canary hostname into the bootstrap. Require SHEETS_ORIGIN to equal that origin exactly (scheme/host, no wildcard or suffix match).
- Require a one-use fixture run ID in a dedicated canary environment variable, and require it to equal the run ID compiled into this bootstrap build. It is a scope guard, not an authentication mechanism.
- Require SHEETS_OWNERS to equal exactly the synthetic owner address, with no additional addresses. Validate the key formats normally and require root's fresh-key provisioning record; do not compare against or obtain production key values.
- The supported target is the platform exec-child contract: ExecBackend.Start invokes the binary with --socket <route.Socket> --db <route.DBPath or DataDir/host.db>. Read both through rastrillo.Resolve, not by parsing HTTP Host. The observed canary socket is exactly /run/carlos/overnight-sheets.bds.oncarlos.com.sock. The expected default database is /data/overnight-sheets.bds.oncarlos.com.db (platform DataDir defaults to /data). Root must confirm that resolved DB path from the route/activation configuration before building. Compile the confirmed absolute DB and socket paths, and reject any different path even if its basename matches.
- 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.
Session material and initialization
Generate a random 32-byte session token locally using the framework's token format (base64 raw URL encoding), and compute SHA-256 hex with sessions.HashToken. Keep the raw token only in a chmod-0600 local Playwright storage-state file. Send only the hash, synthetic subject and bounded expiry through the dedicated canary environment. No token, key, cookie or sign-in link goes into stdout, logs, discussions, screenshots, commits or release metadata.
Run sheets.BootSchema through the normal migrate.Apply path. Seed only one row in the existing sessions table in one transaction after rechecking the empty-state precondition. The pinned sessions schema contains tokenhash, subject, method, authtime, createdat and expiresat. Use:
- token_hash: supplied 64-character lowercase hex hash, validated strictly;
- subject: exactly oficina-fixture@example.test;
- method: fixture (do not claim the mailbox was verified);
- auth_time: empty;
- created_at: current UTC RFC3339;
- expires_at: a supplied absolute UTC time no later than two hours after creation, validated before insertion.
No custom table or migration is added. A repeated bootstrap start may accept exactly the same single hash/subject/expiry row as an idempotent success but must not extend its expiry or mint another session. Any other session or app data causes refusal. Once the candidate browser creates app content, bootstrap is intentionally unable to run again on that database.
The normal candidate's actor() resolves the session subject and memberFor admits/promotes only the synthetic owner listed in SHEETS_OWNERS. Do not seed a broader role or grant independently. Local tests must prove the seeded row is accepted by the real sessions.New lookup/adoption path, while a random token and an expired fixture row are rejected.
Playwright state sets the cookie _Host-rastrillosession for the exact HTTPS canary origin: Secure=true, HttpOnly=true, SameSite=Lax, path=/, no Domain attribute. The raw value never reaches bootstrap. The cookie is a fixture for the existing session store, not a signature forged using an application key.
Deployment sequence and assertions
- Record production process version and route/channel/environment bindings without reading secrets. Verify isolated canary has fresh keys and the expected empty database.
- 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.
- Remove the fixture-specific hash/run/expiry settings from the named environment before replacing bootstrap. They are not used by the normal candidate.
- 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.
- 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.
- 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.
Teardown
Use the candidate's normal POST /signout while the fixture cookie is present; confirm it deletes/revokes the row and the old cookie no longer accesses /sheets. Close browser contexts and delete the private storage-state/token files. Fixture expiry is a second bound if signout fails. Remove remaining fixture-specific named-environment variables. Keep the canary channel on the normal candidate or remove only this disposable instance through supported CLI, according to root's overnight verification needs. Never leave bootstrap selected by any channel. Remove its channel reference first; an immutable release artifact may remain in storage if the platform has no safe deletion verb, but its origin/path/run guards and missing fixture env must make it inert if mistakenly selected.
Do not delete production routes, releases, keys, backups or configuration during teardown. Any authentication or cleanup failure is recorded as a failed/limited canary check, not hidden by reseeding.
Evidence required before use
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.
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.