SOP-09 — Release and deployment

Owner: Owner-operator (Document Owner and Records Owner for every SOP; no delegate exists). Version 2026-10-09 · effective 2026-09-15 · reviewed every 180 days · last reviewed 2026-10-09 · next review due 2027-04-07.

Purpose

Put only tested changes into production and confirm what landed.

Scope

All code and copy changes.

Procedure

  1. Change in preview; run the backend tests for the touched area and the browser checks; smoke-check the page; lint clean.
  2. Write the change to memory/PRD.md (what, why, test evidence) and, for customer-visible change, as a dated change-log line in the governing SOP (published at /api/trust/sops/changes).
  3. Deploy through the hosting provider's pipeline under the owner's account. No direct edits to production.
  4. Production readback: curl the changed endpoints and open the changed page in production; record the readback in PRD.md. A deploy without readback is not complete.
  5. Rollback is a redeploy of the previous release; the database is forward-only.
  6. Front door rule: the homepage keeps one screen for the professional reader — the record statement, the four heaviest-paperwork doors, the three-door chooser, one search box. Everything else (consumer records, the held-file table, demonstrations, counts) lives behind a closed disclosure or on its own page. Any change to the front door is released with a notation in this change log and a measured before/after (height, words, links).
  7. Readback after every deploy: GET /api/health must show bootstrap.status 'ok' and the specific string the release changed (an SOP version, a register count, a route) must be read from production before the release is called live. A deploy dispatched while another is queued may land only the earlier snapshot — read the string, not the panel. Before a release adds a collection or index: grep the backend for the collection name (legacy modules keep theirs), and wrap every index build in bootstrap so one failure cannot leave later jobs unarmed.

Records this procedure produces — and who keeps them current

RecordWhereUpdated byUpdate triggerRetentionPublic
Engineering logmemory/PRD.md (private) and the SOP change logs (public, /api/trust/sops/changes)ownerevery releaseindefinitechangelog public
Test reportstest_reports/iteration_N.jsontesting agent / ownerevery tested changeindefiniteFalse

Evidence

/api/trust/sops/changes · /api/trust/policies/change-management

Change log

DateChange
2026-10-06Written as SOP.
2026-10-06Front door rule added. Homepage cut from 6,922 px / 2,698 words / 100 links (production, measured 2026-10-06) to one professional screen; consumer tiles and 'also free' list moved under 'More records'; held-file table, 28-tab demonstration, time table and verify block moved under a closed 'How it works, in detail'. Corrected a wrong reference: this SOP cited a /changelog page that does not exist; the public record of changes is the SOP change log at /api/trust/sops/changes.
2026-10-06Descriptor approved by owner: 'An autonomous public-records evidence utility' added under the homepage H1, in the page title, and on /trust; one sentence each.
2026-10-08Owner: 'Update homepage.' Front door re-pointed to the forms layer: descriptor keeps the approved phrase and adds 'the government's own record, cross-filed to the form you file'; hero names the form lines and the FAC type-I count (6,952 in 2024, linked); a Three Doors block (which forms apply to me → /maps; my own record → /your-record; a dated receipt now → /screening) with a Government Desk line; the chooser gains an RFP/contract door to /clause. Measured before/after at 1920px: height 1,724 → 1,968 px, words 624 → 714, links 72 → 78. Still one screen for the record statement and doors.
2026-10-09Incident 2026-10-09 05:05 UTC: a unique index on a collection name already used by a legacy module (db.opportunities) raised in production bootstrap and left Road Watch, Opportunity Watch and other startup arming undone for 15 minutes while every page answered. Caught by readback of /api/health, fixed by renaming to db.opportunity_notices and guarding the index build; Sentinel now raises 'bootstrap_failed' (SOP-08). Readback step and collection-name check added above.

Quality Manual · All SOPs · Records Register