Skip to content

Decision records

Each page here records one decision: what was decided, when, why, and what it cost. They are short on purpose. The full reasoning lives in the design specification, and each record links to the section that argues its case.

The records were written while PyFr's reference service — the service this project was generated from — was being built, and records 1 to 12 were backfilled after the work they describe. The "Decided" column names the PyFr milestone (M0, M1, …) that made each decision — PyFr's roadmap says what each milestone built — and a record is dated to that milestone rather than to the day it was written.

Why they are never edited

An accepted record is history. It says what was decided on a date, given what was known then. Changing your mind means writing a new record and marking the old one superseded — never rewriting the old one, which destroys the only account of why the software is the way it is.

For the same reason, records are exempt from the review-date warning that covers every other page on this site. A decision does not go stale.

Adding one

Copy template.md, take the next number, and add it to the nav in mkdocs.yml. Write it when the decision is made, while the alternatives are still fresh — a record written six months later is a reconstruction, and it shows.

The records

Three decisions belong to PyFr, the template this project was generated from, and are recorded on its site: cookiecutter over Copier and cruft (0002), uv over pip and Poetry (0003), and the template is the source of truth (0017).

Record Decided
0001 The four-layer dependency rule M0
0002 cookiecutter over Copier and cruft M0
0003 uv, not pip or Poetry M0
0004 golang-migrate owns the schema M1
0005 In-memory adapters are a supported configuration M0
0006 The cache is fail-open, always M4
0007 Emit OpenTelemetry and stop there M2
0008 Standard output is the source of truth for logs M2
0009 RFC 9457 Problem Details for every error M0
0010 The OpenAPI document is committed and drift-gated M3
0011 /readyz reports optional dependencies without gating M4
0012 mypy is strict on the inner layers only M0
0013 Redact by key name, in the shared processor chain M6
0014 Dependabot, and one pin per tool M6
0015 Images are published on release, under the repository's version M6
0016 Image scanning fails on fixed findings, and exemptions expire M6
0017 The template is the source of truth, and a golden diff proves it M7