main. GitHub Actions
verifies the code and archives a release manifest. The production frontend is
served through Render and the API through Supabase project
fdrjqcyjklatdrmjdnys. The Docker main function is a self-host router and must
never be included in the cloud function inventory.
Release checks
Install frontend dependencies first; the release CLI reuses the repository’s TypeScript and Zod dependencies. It performs read-only checks and does not deploy, apply migrations, repair migration history, or delete remote functions.SUPABASE_ACCESS_TOKEN. On macOS it can use the existing Supabase CLI native
credential. Never paste the token into a command argument or report. The check
downloads each cloud function into its own temporary directory, compares all
runtime source files, reads schema metadata through Supabase’s read-only SQL API,
and removes the temporary downloads. It checks function inventory again afterward
to reject a snapshot collected during another deployment.
The manifest records the commit, dirty-worktree state, every cloud entry point,
explicit gateway policy, shared runtime dependencies, declarations, import map,
Deno lockfile, migration hashes and schema requirements. A shared helper change
therefore invalidates every function that imports it. Remote verification fails
on missing or extra functions, unexpected modules, old source bytes, changed
gateway settings, changed schema effects or an uncommitted checkout. It verifies
source/configuration compatibility, not provider secrets or remote package/CDN
integrity. Preserve the manifest and verification report with each release.
CI runs the local checks without production credentials. The owner confirms that
Render automatically deploys main. Run the remote gate against the reviewed
commit before merging, then verify that the live frontend publishes the new
artifact and passes its smoke checks. A Render dashboard login is not needed to
trigger that deployment.
Render’s exact build command, cache behavior, rollback configuration and automatic
enforcement of this gate remain infrastructure audit follow-ups. Until automatic
enforcement is verified, the release operator must require a passing remote report
before merging to main. Any provider release step should use the same command
above, rather than maintaining a second inventory or schema checker.
Reconciled database baseline
Production had nosupabase_migrations.schema_migrations ledger when inspected
on September 5, 2026. supabase/release/baseline.json records the hashes of the
seven historical migration files and 134 observed schema objects/grants. This
confirms their resulting effects, not the order or mechanism by which they ran:
- Character
updated_atis non-null with its update trigger and function. - Anonymous and authenticated roles can read public profile/campaign columns,
and cannot read
public_user.api,public_user.patreonorcampaign.join_key. - The campaign join-grant table has the expected keys, RLS with no public policies, and membership trigger/function.
- All 13 content tables have timestamp columns/triggers, 12 child tables bump
source timestamps, and both functions exclude generated
search_tsvcolumns when checking whether content changed. - All 12 content metadata columns are JSONB with GIN indexes.
supabase/release/schema-state.sql. Baseline format 2 names
each fingerprint with a sha256 field, making its algorithm explicit even when
the schema identifier names a protected column. These fingerprints describe schema
definitions and migration files; they contain no account credentials. Definition hashes pin
the inspected database functions, enabled triggers, columns, indexes, constraints
and grants. A difference requires investigation and a reviewed compatibility
update. Do not overwrite the baseline from an unreviewed production snapshot just
to make a failing gate green.
Do not run supabase db push against this project to replay historical files.
Do not run migration repair merely to create a ledger. Historical SQL is immutable;
use new migrations. Every new migration needs an entry and read-only effect check
in supabase/release/requirements.json. If a ledger is introduced in a separately
reviewed reconciliation, the gate also checks recorded post-baseline versions and
rejects unknown versions. Absence of a ledger never substitutes for effect checks.
Rollout order
- Freeze the reviewed commit and preserve the previous compatible release manifest, function source, frontend artifact and provider configuration. Check CI/E2E and the current remote report. Investigate differences instead of treating them as permission to overwrite production.
- Apply additive prerequisites before dependent functions. For this release,
apply only
20260905000000_edge_work_budget.sqlusing the approved database connection,ON_ERROR_STOPand a transaction. Its quota table/RPC is compatible with old handlers; new paid-work handlers return 503 if it is missing. The read-only requirement verifies the reviewed RPC body and service-role-only access. No historical migration replay is needed. - Deploy the complete cloud inventory from the reviewed checkout. Use
node scripts/release.mjs function-namesas the name source. Deploy those names explicitly with Supabase CLI and the repositorysupabase/config.toml; do not use an unscoped deploy-all command or a global--no-verify-jwtoverride. A shared-module change must deploy all its dependents, and deploying the full 54-function inventory is the simple safe default. - For a future restrictive grant/schema change, first deploy handlers compatible
with both schemas, smoke-test them, then apply the restriction. July 18’s
public_userpermission failure is the reason this order matters. - Run semantic smoke checks: public content and a public profile; authenticated own-profile and character reads; an authorized test-character save followed by a read; conflict handling; admin authorization and rejected anonymous paid-work requests. Use dedicated test identities/data. HTTP 200 alone is not success: inspect the JSend status and saved value. Expensive service success tests should use a controlled quota and approved test input.
- Retire obsolete functions after consumer review, then run
release:verifyagain and require a passing report before publishing the frontend. On September 5 the unexpected live routes werefind-campaigns,find-characters,find-encounters,get-sheet-contentand self-hostmain. Seven complete UTC days (August 29–September 4) contained 1,764,530 function-edge events and zero events for all five routes, including OPTIONS. Their source bundles and gateway inventory are backed up under.agents/legacy/infra-release-2026-09-05/. This supports retirement but does not establish that dormant clients do not exist. A retained compatibility route must be brought back into reviewed source with current authorization and tests; do not simply allowlist an opaque old bundle. - Merge the verified commit to
mainto trigger Render’s auto-deploy. Confirm the live entry point references the new frontend artifact, inspect the rendered app, repeat public/authenticated/save smoke checks, and inspect available logs for permission, auth, worker and paid-work failures. Archive the final manifest and successful report. Provider telemetry and semantic checks remain necessary even when hashes agree.

