First release runbook
The full operator runbook is the file infra/RUNBOOK-first-release.md in the infra repository; this
page summarises it. Its status banner reads COMPLETE 2026-09-13 for steps 0 to 6, 8 and 9; step 7 (the
identity-provider registration) is still open. The outcome and the identifiers are on the
deployment record page. Run the steps in order; do not start a step
before the previous checkpoint is green; every step has a rollback. Only step 5 is manual (the registrar’s
name-server page); step 7 needs the identity administrator to enter two redirect URIs.
Hosts trovensa.com, docs.trovensa.com, console.trovensa.com and api.trovensa.com answer since
2026-09-13. Every product keeps the status designed: sign-in waits for step 7.
State of the tree when the runbook was written (2026-09-13)
| Gate | Result |
|---|---|
make tf-validate | Success! The configuration is valid. (root and bootstrap/; fmt -check clean) |
make k8s-render | check-render: ok (16 documents; no spec.replicas on api and web) |
make release-check | Dry-run complete - nothing was executed, exit 0, warnings only |
python3 -m pytest -q tests | passing (the count varies with the number of files the attribution test scans) |
Fixed identifiers
Project trovensa, environment dev (prefix trovensa-dev), cluster trovensa-dev, namespace
trovensa, repositories trovensa-api, trovensa-web, trovensa-agent, secret trovensa/dev/app, zone
trovensa.com, web redirect URIs http://localhost:3100/auth/bridge and
https://console.trovensa.com/auth/bridge. Local ports 3100, 8100 and 5434 because 3000, 8000 and 5433 are
taken on the build machine.
Steps
| Step | What it does | Checkpoint | Rollback |
|---|---|---|---|
| 0 Pre-flight | identity, tool versions, make check, tests, clean trees, current DNS answers recorded | every command exits 0 | none needed |
| 1 Bootstrap remote state | state bucket and lock table, backend and tfvars files from the examples | plan shows “No changes”, root init without a prompt | none needed (prevent_destroy) |
| 2 Network, cluster, database, registries, secret shell, zone, certificate | one plan and apply; the agent runtime module stays off | plan = “No changes”, nodes Ready, certificate PENDING_VALIDATION, forge.config.json release values updated by the contracts owner | terraform destroy |
| 3 Runtime secret and namespace | namespace with restricted pod security; secret with DATABASE_URL, DEV_TOKEN_SECRET, AGENT_MODEL_ID | the Secret has the three keys, no value printed | delete the Secret, rotate the value |
| 4 First images | build and push api and web with sha tags | both tags listed, no CRITICAL scan finding | delete the tags |
| 5 DNS handover (manual) | mirror records, validation CNAMEs, name servers at the registrar, certificate validation, pin the certificate in the overlay | both resolvers return the new name servers, certificate ISSUED, render shows the real ARN | old name servers back, placeholder restored |
| 6 First release of api and web | scripts/release.sh --api --web: migration Job, rollouts, health curls | health 200, /auth/bridge 200, TLS SANs, CORS preflight 200, overlay commit with both tags | previous tags or kubectl delete -k |
| 7 Identity provider | redirect URIs in the portal, AUTH_* values, web rebuilt with the client id | sign-in round trip with zero console errors, /me 200 | previous web sha, blank AUTH_* (dev identity) |
| 8 Site and docs | deploy-static.sh for site and docs, then apex, www, docs and verification records | three names resolve, both hosts answer 200 | empty the variables and apply |
| 9 Agent runtime (optional) | release.sh --agent, runtime module on, AGENT_RUNTIME_ARN and FEATURE_AGENT_RUNS in the config map | config map carries the ARN, an agent run reaches succeeded or a documented error | FEATURE_AGENT_RUNS: "false", runtime_enabled = false |
Final verification
Name servers, a curl matrix over the four hosts, the two health routes, /auth/bridge, the deployments,
terraform plan = “No changes”, a clean infra tree, and a browser pass at 1440 x 900 and 390 x 844 in
both themes with zero console errors and every seeded record visibly labelled “Illustrative”. Then the
release values in forge.config.json are updated, the runbook banner changes to COMPLETE with the date,
and the deployment record (hosts, images, certificate, zone) is added to this page.
Things to know while executing
- The
.comNS TTL is up to 48 hours; mirror records cover the window. Use a public resolver for checks. - The certificate validation CNAME is written by one module only; never add it a second time.
- Registries are immutable: an existing tag is never rebuilt; a dirty tree gets a
-dirty-tag and a warning. - A runtime version update wipes live sessions; the release refuses while
agent_runshasqueuedorrunningrows unless forced. - Keep the app service accounts annotation-free so the pod identity association wins in the credential chain.
Source: infra/RUNBOOK-first-release.md, forge.config.json, PRODUCT-CONTRACT.md, decisions/0010-repository-layout-and-deferred-release.md