Plan isolated Calendar recurrence canary fixture
1 file changed,
+66
−0
docs/superpowers/plans/2026-09-08-recurrence-canary-fixture.md+66 −0
CI passed — run details
diff --git a/docs/superpowers/plans/2026-09-08-recurrence-canary-fixture.md b/docs/superpowers/plans/2026-09-08-recurrence-canary-fixture.md| new file mode 100644 |
| index 0000000..eda7513 |
| --- /dev/null |
| +++ b/docs/superpowers/plans/2026-09-08-recurrence-canary-fixture.md |
| @@ -0,0 +1,66 @@ |
| +# Calendar synthetic recurrence canary bootstrap |
| + |
| +LLM-only design, revision1, UNAPPROVED. Branch plan/recurrence-canary-fixture from frozen1a6dcd0753568e63b9cafeaaf2b75d1e807d1926. Calendar discussion3. No implementation/deployment approval is claimed. This adapts the independently reviewed Sheets fixture design and tools/canaryfixture; their approval is precedent, not Calendar approval. |
| + |
| +## Scope and exact target |
| + |
| +A disposable session fixture allows the unchanged normal Calendar binary to exercise recurrence and public booking correctness without a controlled mailbox. It does not test sign-in, mailbox ownership, magic-link binding, SMTP delivery, reminder delivery or booking confirmation mail. No application auth endpoint, middleware exception, default development key or persistent backdoor is added. |
| + |
| +Only account bds, app calendar, hostname overnight-calendar.bds.oncarlos.com, HTTPS origin https://overnight-calendar.bds.oncarlos.com, channel canary/overnight-recurrence and named environment overnight-recurrence are permitted. On2026-09-08 root reported successful console-backed instances create with these exact values; the console's manifest admission verifies this hostname. Root's full instance/environment/route record remains required before preflight activation. Seed argv count is UNVERIFIED: current console source exposes only PUT /instances-manifest, and invoking instancesEnable to inspect it would mutate shared configuration. Do not use that path as a read. Domain admission does not establish an empty DB or actual runtime DB path. |
| + |
| +Use the verified current CLI /tmp/oficina-carlos-current/carlos. Its instances create --environment and instances set-environment bind the console-backed instance record. Never use box-side route --environment: the reconciler reverts it. The initial read-only audit's PATH carlos was older; /tmp/oficina-calendar-release-audit/platform-cli.json records the corrected binary hash/help/source. Root owns all platform changes and maintains the live calendar.oficina.works route on d961b65/default environment throughout. |
| + |
| +Root read-only receipt /tmp/oficina-calendar-release-audit/canary-record.json now confirms exact host/channel/environment, provisioned exec-child route and /run/carlos/overnight-calendar.bds.oncarlos.com.sock, no unit/backing override; seed_argv_verified=false. It does not expose DB argv. Root's build receipt /tmp/oficina-calendar-recurrence-release/build.json identifies the unchanged1a6dcd0 linux-arm64 CGO-disabled archive build, SHA256709bb127a0205da6db5948658aaeeb794ea1182bc46d30d6ba2753b6773b1cc9, not deployed. No canary keys/config payload have been written yet. |
| + |
| +Normal candidate remains1a6dcd0 with no fixture package or command in its import graph. Any eventual integration candidate requires its own frozen source SHA and release review. The support approval is only the seven-file recurrence correction over2074881; it is not approval to merge181files into scaffold main. |
| + |
| +## Two separate commands, no observer-to-writer switch |
| + |
| +1. cmd/calendar-fixture-preflight is standard-library-only. Its link-stamped version/run ID and exact target constants are compiled. It performs no filesystem open/stat, DB open, migration, socket listen, SMTP, auth or app construction. It parses only the supported exec-child argv shape --socket <absolute> --db <absolute>; no -addr, extra flags, LISTEN_FDS, seed invocation or other shape. It validates all actual resolved child environment values below. The socket must equal /run/carlos/overnight-calendar.bds.oncarlos.com.sock. The DB must be a clean absolute path with exact basename overnight-calendar.bds.oncarlos.com.db. It reports only its preflight stamp and those validated activation paths, then exits. This is path observation, not permission for a writer to accept arbitrary parents. A missing/relative/unclean path refuses before Resolve could join it. STATE_DIRECTORY may be absent for exec-child; if present it must equal the observed DB parent. Unknown seed configuration does not justify clearing or editing it. A seed invocation lacks --socket and must exit nonzero at the first argv guard before any environment-dependent observation or filesystem action. Root may attempt only the reviewed observer, inspect this canary's supported logs for its fixed refusal, and stop if seed invocation prevents the normal supported exec-child shape. Seed count remains unverified until authoritative evidence exists. Expected failed readiness from an observer that exits is not a candidate test failure. |
| +2. After root reviews the actual path receipt, a separate cmd/calendar-fixture writer compiles that one exact absolute DB path and the exact socket. /data/overnight-calendar.bds.oncarlos.com.db is only the current platform default, NOT runtime evidence and NOT frozen writer authority yet. A nondefault parent needs an explicit reviewed path revision. The writer requires a fresh run ID different from preflight; it never accepts its expected DB path from environment or observer output at runtime. It validates raw argv before rastrillo.Resolve, then requires Resolve to return the same DB/socket and no address/activation alternate. It opens only the confirmed canary DB, seeds one ordinary session under empty-state guards, and serves only framework health/version on an otherwise empty mux while root replaces it. No Calendar router is mounted. No browser recurrence assertion runs against bootstrap. Removing required fixture env renders a reawakened bootstrap inert/refusing. |
| + |
| +Both commands live only on this temporary fixture branch, with distinct clean-archive build targets/stamps <sha>-fixture-preflight-<runID> and <sha>-fixture-<runID>. The normal production release remains built from frozen candidate, with ordinary SHA stamp and an import-graph gate excluding both command packages and tools/canaryfixture. There is no normal-candidate env toggle that enables either tool. |
| + |
| +## Effective runtime configuration guards |
| + |
| +Compile exact hostname/origin, synthetic subject oficina-fixture@example.test and a random one-use scope run ID. Require CALENDAR_ORIGIN exact, CALENDAR_ALLOWED_ADDRESSES exactly that single subject, CALENDAR_ENV exactly production and CALENDAR_FIXTURE_RUN_ID exact. An environment absence is distinct from an explicitly empty value. Reject development argv entirely. |
| + |
| +Require fresh canary CALENDAR_INSTANCE_KEY and CALENDAR_DEK, each generated by root under the named environment only. For this fixture the instance key must be canonical base64 of32 random bytes, and DEK canonical base64 of32 random bytes; reject equal keys, all-zero decoded keys and the known empty/development material. Their formats and non-equality can be checked without printing values. Freshness is an operator provisioning fact; do not read or compare production key values. Runtime guards check effective child values after platform/box-local merging, not merely control-plane declarations. |
| + |
| +For BOTH prefixes CALENDAR_SMTP and CARLOS_SMTP require HOST=smtp-fixture.invalid, FROM=oficina-fixture@example.test, PORT=587, USER explicitly empty, PASS explicitly empty. The app prefers CALENDAR when HOST and FROM exist; validating both avoids a silent fallback to production CARLOS credentials. This follows Sheets' reviewed explicit-empty named-bundle override mechanism. Root verifies overrides suppress inherited secret values; unsetting a name is not equivalent to empty override. No actual mail is permitted. Both host/from must be nonempty so normal main constructs mail.SMTP rather than failing boot or falling back to a content-logging sender. The .invalid relay and empty credentials prevent use of the real transport; fixture operations must additionally create no owed mail. This is nondelivery configuration, not a simulated successful mailer. |
| + |
| +Writer additionally requires CALENDAR_FIXTURE_TOKEN_HASH exactly64 lowercase hex and CALENDAR_FIXTURE_EXPIRES_AT canonical UTC RFC3339, strictly future and no later than now+2h. Neither observer nor writer prints hash, expiry credential material, keys, environment dumps, raw SQL or DB errors. Fixed guard codes and counts/stamps only. The observer need not receive token hash/expiry; it validates scope/config formats without handling session material. Unsupported or contradictory environment shape refuses. |
| + |
| +## Filesystem and empty-state guards |
| + |
| +After observed path confirmation, writer checks clean exact DB/socket strings, no symlink in parent chain, protected ownership/modes and expected process uid, regular single-link existing DB if any, no symlink/WAL/SHM alias or cross-scope attachment, no socket path occupied by another serving process. Root's stop/adoption receipt establishes one writer; the tool must not treat a matching pathname alone as proof another app is absent. Existing socket inode may remain after old process exits; distinguish stale owned socket from a live listener before framework Serve replaces it. Before/after DB open verify same file identity (or the new exclusive file's identity), and bind the opened SQLite descriptor to the expected identity where platform support permits. A moved live DB/path replacement or unknown ownership refuses, never resets. |
| + |
| +Check all existing user tables before migrations, then apply Calendar.BootSchema and recheck inside the insertion transaction. Enumerate sqlite_master type=table, excluding only the literal SQLite internal prefix sqlite_ (GLOB, not LIKE underscore wildcard) and exact rastrillo_migrations ledger. Every other table must be empty. Current Calendar schema has13 app tables: people, calendars, grants, events, reminders, reminder_queues, feeds, meta, attendees, booking_pages, booking_windows, bookings, booking_mails. Framework adds sessions, auth_links, auth_sessions. Empty means zero rows, not missing queries/errors; unknown future populated tables refuse too. No table deletion, reset, schema rewrite or production backup restore is allowed. Existing ledger-only state may be accepted if normal migrations validate it. Failed migration/open leaves preserved artifacts and a refusal, not an automatic retry/reset. |
| + |
| +Apply BootSchema in its settled order sessions.Schema, auth.Schema, calendar.Schema. Auth's backfill migration copies auth_sessions into sessions, so populated auth_sessions must refuse BEFORE migrations, not become an accepted migrated fixture. Use discarded/redacted database logging. Recheck emptiness under a transaction that owns the write lock; normal application must not serve concurrently. No business row is seeded. |
| + |
| +The only idempotent exception is the exact single session row described below while every other user table remains empty. A changed hash/subject/method/auth_time/expiry, extra session, invalid future creation time or expired row refuses; never extend expiry. Once ordinary Calendar routes create people/calendar/grant/meta or fixture events, bootstrap cannot run again. No custom marker table/migration is introduced. |
| + |
| +## Exact existing session contract |
| + |
| +Pinned Rastrillo v0.23.0 auth.New uses sessions.New; auth.RequireSession delegates to that core. Its table is sessions(token_hash TEXT PRIMARY KEY, subject TEXT NOT NULL, method TEXT NOT NULL DEFAULT '', auth_time TEXT NOT NULL DEFAULT '', created_at TEXT NOT NULL, expires_at TEXT NOT NULL). Calendar.BootSchema already owns it. Do NOT insert auth_sessions or mint an auth_links entry. |
| + |
| +Generate32 random bytes locally; encode base64.RawURLEncoding as raw token; compute sessions.HashToken, SHA256 of the encoded token string as lowercase hex. Keep raw token solely in local private0700 directory/0600 single-link non-symlink browser state. Only hash goes to dedicated named environment. Writer inserts one row: token_hash=validated hash, subject=oficina-fixture@example.test, method=fixture, auth_time='', created_at=actual UTC RFC3339, expires_at=supplied absolute UTC time<=creation+2h. An idempotent replay preserves exact creation and expiry; no refresh or alternative subject. |
| + |
| +The unchanged candidate resolves this row through real auth.RequireSession→sessions, then requirePerson→EnsurePersonSetup. Ordinary first signed-in GET creates the synthetic person and normal calendars/grants; do not pre-seed broader roles or bypass that seam. Method fixture does not assert a mailbox was verified. Cookie is __Host-rastrillo_session, Secure/HttpOnly, SameSite=Lax, Path=/, exact HTTPS canary host with no Domain cookie. Random/expired/revoked tokens must fail through the normal middleware. POST/signout must revoke the real row, followed by denial for the old cookie. Expiry bounds cleanup failure. |
| + |
| +## Candidate fixture and proof |
| + |
| +Root deploys reviewed observer, reviews activation/environment receipt, then reviewed exact-path writer, checks distinct bootstrap /api/version and nonplatform404, removes fixture-only run/hash/expiry settings, and replaces it with the exact reviewed normal candidate. Require process-served plain-text /api/version==candidate SHA, fresh isolated DB/config receipt, canary channel no longer referencing fixture, and production still d961b65. Bootstrap merely returning health200 does not certify application behavior. |
| + |
| +Only after candidate replacement, import synthetic ICS through authenticated ordinary routes and configure/publish a synthetic booking page. Explicitly disable/omit reminders; no attendees, booking holds, confirmations, cancellation/reschedule requests, real addresses or owed booking_mails. Browser automation blocks POST/signin and reminder/hold/mail-generating routes, cross-origin requests, traces and secret-bearing diagnostics. Signed-in GETs can run opportunistic drain, so verify empty queues before candidate requests and never claim GET means no mutations. Platform scheduled ticks may visit the new instance; with empty queues they have no messages to send. |
| + |
| +Use cases from /tmp/oficina-calendar-release-audit/proposal.txt: exact four-century historical occurrence; a400-year recurrence whose second instance is tomorrow removing09:00/09:30 but retaining10:00 from published slots; huge unbounded weekly interval returns prompt503+Retry-After60 rather than false free/hang; COUNT1 finite case remains usable; April1 after Dublin gap remains a valid30-minute occurrence. Isolate huge-rule and finite cases by ordinary event deletion between checks, not a second privileged bootstrap. All copied strings/fixture text are synthetic LLM test data, not new product UI copy. |
| + |
| +Real WebKit320/desktop scripts on/off checks normal candidate calendar views and public slot picker. No calendar content, session cookie, raw token, key or mail link in public logs, screenshots or discussions. Safe receipts bind source/artifact/processSHA to status/count/expected fixture hashes. The actual Dublin gap-day false-free semantics remain Calendar#2 unresolved; this tool does not decide policy. Invalid persisted start/end/zone tests remain local synthetic-store regressions rather than live DB corruption. |
| + |
| +## Required tests and review |
| + |
| +Design Fable review first; exact-path revision after observer receipt; writer/preflight whole-branch Fable review and green local/actual CI before use. Test wrong host/origin/env/run/owner/SMTP presence or nonempty inherited credentials; no fallback to development; equal/malformed keys; bad raw argv/path/socket/STATE_DIRECTORY/LISTEN_FDS. Prove observer has no filesystem/socket/DB effects and no app/framework/database dependencies. Test symlink parent/file, hardlink, moved/replaced DB, live socket, populated unknown/normal tables and auth_sessions before migrations. Verify enumeration covers all BootSchema user tables, including sqliteXfuture-like names. Test exact one-row idempotence/no expiry extension, unrelated session and expired/future-invalid timestamp refusal. Test real Calendar auth/person setup with the seeded hash plus random/expired/signout denial, without mail delivery. Assert candidate dependency graph excludes both fixture commands/packages and source normal cmd/calendar remains byte-identical to1a6dcd0. Mutation-prove at least scope guard, pre-migration emptiness and session expiry rejection. |
| + |
| +Teardown: normal signout then old-cookie denial; delete local private state; remove fixture-only named settings and all channel references to bootstrap/preflight. Root either retains normal candidate on this disposable canary or removes only this instance through supported console CLI. Do not delete production route/default bundles/keys/backups. A failed cleanup is recorded, never hidden by reseeding. Immutable inert fixture artifacts may remain if no supported deletion exists, but their run/origin/path guards and missing fixture env must refuse accidental selection. |