The lifecycle
Every transition is an RPC (transition_rfc) that re-checks the caller’s role and
writes an audit row with actor, action and hash. Saving a new revision on a
reviewed RFC invalidates the review. Changing an RFC’s number/domain after creation
resets it to needing domain-owner approval again.
Documents and revisions
- The editor document is Markdown with a YAML frontmatter block
(
rfc,title,domain,status,owners,created). Live lint covers both RFC 2119 keyword case (lowercasemust/should/mayare flagged; synonyms like SHALL/REQUIRED are normalized to the five canonical keywords at extraction time) and frontmatter validity. - Save stores the whole document into
rfc_versions.body_md— frontmatter block included — and the parsed frontmatter into the JSONB column. A version row whosebody_mdlacks the---block will fail every subsequent save with “fix frontmatter before saving”; the fix is a new, complete revision. - Versions are immutable rows; the revision number only ever grows.

Statement extraction
On approval (and re-approval of new revisions), the SPA invokes theextract-statements Edge Function:
- Input: RFC body + frontmatter + the RFC’s existing statements (slug + text).
- One LLM call returns statements with
slug,level,section,text,sdlc_stage(design/implementation/review/ci/operations). - The prompt requires slug reuse for materially unchanged statements; removed
statements become
status='retired', never deleted. - Output is validated against a Zod schema after normalizing RFC 2119 synonyms (REQUIRED/SHALL/RECOMMENDED/OPTIONAL/FORBIDDEN/PROHIBITED → the five canonical levels) — one off-enum value must not discard the whole batch.
- Approval survives extraction failure (most commonly a free-plan org hitting
the
llm_extractionentitlement gate, HTTP 402) — the RFC is approved, the toast says extraction failed, and re-approving later re-runs it.

Audit trail
Actions recorded per RFC includerfc.revision_saved, rfc.proposed,
rfc.reviewer_assigned, rfc.reviewed, rfc.approved, rfc.enforced, plus member,
API-key, GitHub, scan and violation events at org level. Settings → Audit shows the
full chain with per-row hashes and offers JSON/CSV export; the export can be verified
independently:
sha256(prev_hash || canonical_json(entry)) needs no database access.


