# Doctrine documentation (docs/architecture/doctrine/{concern}.md)

Truth document. Use for **one concern the platform handles everywhere**: authentication, authorization, storage, the API protocol, credentials, telemetry. One file per concern, named for the concern. A doctrine document speaks for no code: no source header names it, and it carries no `owns:`. The surfaces bound by it are the documents that design or touch the objects it governs, computed through those objects, and each names it in its Scope.

**A doctrine document states the design and nothing beneath it** (`references/style-guide.md` § Shape — the model first, the detail after). It is the most stable document in the tree, because it says why the platform is shaped the way it is, and that changes far less often than the code. It explains no mechanism: no function, file, column, cookie attribute, header value or per-route error code, since each of those fails the stability test. The code graph answers what the code does. This document answers why, and which principles any new code in the concern keeps.

**A doctrine document is a specification, not a description.** It states how every product handles the concern, so a product whose code differs has a gap to plan and build, and the document never records which product has built what: no `UNBUILT` marker, no "today the product…", no product's name, setting value or code root. When one product's posture against the doctrine matters, it is that product's own security overview, plan or backlog.

**A doctrine document is written in general form, never linked to the project that holds it.** It reads correctly when copied verbatim into any other product's repository. So it names nothing only that repository has: the product, its domain entities (a hiring product's candidates), its vendors and stack (a hosting platform, a database engine), its people, or its own documents by path (a feature document, a plan, a decision record). An example uses an object every product has (a member, an invoice, an uploaded file); where a domain object is unavoidable, it comes from a kind of product other than the repository's own. Its links reach only sibling doctrine documents and published standards. The project's own facts belong to its feature documents, system overview and decision records, which name this document in their Scope.

**Earn the document before writing it.** List the decisions only this document would own, each checked against the documents that exist: a decision another document already states is a citation, not an owned decision. Fewer than about six owned decisions means the concern is a section of a neighbour, not a document (`references/document-sets.md` § Usefulness test).

**Required:**

- the frontmatter
- the opening: the definition sentence, the scope bullets, and the specification sentence
- **Principles**: numbered, each a noun-phrase label and its rule, with its reason as a separate sentence wherever the rule meets a trigger of `references/style-guide.md` § Sentences
- **Terms**: one row per term the document uses, covering every name in `objects:`
- **Related documents**

**Optional, each only with something the principles do not already say:**

- **A participant section** (e.g. "Callers") before Principles: who or what takes part, as a table where they share attributes
- **A parts section** (e.g. "Credential families"): one table placing the parts, where there are enough parts that a reader needs them placed, then its relations where two parts meet in a way no principle states
- **One section per part** that carries decisions of its own (e.g. "Capability links")

Sections run in that order: opening, participants, Principles, the parts, each part, Terms, Related documents. Each is named for its concept, never for its layer ("The model", "In depth"). Links live in the opening's out-of-scope bullets and in Related documents; the body names a neighbour in plain words (`references/style-guide.md` § Self-contained documents and the link surface). Expect eighty to two hundred and fifty lines; past that, mechanism or restatement has usually crept in.

```yaml
---
type: doctrine                                   # required tooling key
description: "{at most 300 characters: what this document settles and where its boundary sits}" # required — the per-file account a folder is browsed by (references/frontmatter.md)
status: active                                   # required — active | draft
objects: [principal, credential, device grant]   # required — the concepts this document governs, by their graph names
---
```

```
# {Concern}

This document defines {what, for every product}: {the specifics it covers, in parallel form}.

- **In scope:** {each item a noun phrase}
- **Out of scope:** {each item a noun phrase, then a colon and the linked document that owns it}

{Optional: one sentence of rationale, where the boundary with a neighbour needs justifying.}

{The specification sentence, with the scope named: "Every product on {the scope, e.g. the enterprise plane} implements this document; a product whose code differs from it has a gap to plan and build."}

## {The participants, as a noun phrase — e.g. "Callers"} (optional)

{One row or bullet per participant: its name, its definition, and the attribute the parts are placed on. A table where the participants share attributes.}

## Principles

{Numbered rules that hold across every part. Each item: a bold noun-phrase label and a colon, then the rule as one sentence, then its reason as a separate sentence wherever the rule meets a trigger of the style guide's § Sentences: a tempting alternative, a cost, an arbitrary value, an invisible failure. Later sections cite them by number. A rule another document owns is cited — "(auth service, principle 5)" — never restated here.}

## {The parts, as a noun phrase — e.g. "Credential families"} (optional)

{One table: each part placed on the model's axes. A row whose only content is "see principle N" is not placing anything; drop the table when every row would be one. Then the relations, as bullets: only where two parts meet in a way no principle states — what they share, what keeps them apart, the order in which they are tried. A role-level diagram (mermaid) where the relationships are a flow.}

## {One part, as a noun phrase — e.g. "Capability links", "Trusted systems"} (optional, one per part)

{The part's definition in one sentence, where its name does not already give it. Then the decisions this part rests on that no principle states, as bullets — a bold noun-phrase label, the rule, then its reason where earned — citing principles by number. A part with nothing beyond its principles gets no section. A sequence diagram at role level where the part is a flow.}

## Terms

| Term | Definition |
| --- | --- |
| {every name in `objects:`, and every other term a reader could misread} | {one line} |

## Related documents

- [{Neighbour}]({neighbour}.md): {what it settles that this document does not}
```

### Reason check

Doctrine is written once in a while and read for years, so every reason in it earns its line against a reader who has not seen the writing. The writer cannot judge that: it already knows why every rule holds. So whether a reason stays is decided by a cold reader, never by the writer.

1. **Collect the candidates:** every reason sentence the document carries, and every reason the writer would add for a rule that meets a trigger of `references/style-guide.md` § Sentences. Each candidate is the rule it explains plus the reason sentence, quoted verbatim.
2. **Dispatch the judge:** one fresh sub-agent per document, at the standard tier, briefed with the document's path and the candidate list and nothing from the session. It reads the whole document first, because a reason another line already makes plain is obvious. For each candidate it returns `obvious` or `non-obvious` and one line of why.
3. **Apply the verdicts:** a non-obvious reason stays, or is added as the sentence after its rule. An obvious reason is cut, and its rule stays. A reason the document cites from a sibling is judged like any other, and an obvious one loses its citation with it.

- **The test:** a reason is obvious when a competent engineer holding this document would supply it unprompted. It is non-obvious when that engineer would reach for the alternative, would not know the failure, or would read the value as arbitrary.
- **Sources still bind:** the judge decides whether a reason stays, never what it says. A non-obvious reason with no source (an owner's ruling, a sibling, the code) is a question for the owner, as in `references/document-sets.md` § 3.
- **Batching:** the judge reads each document once and returns a verdict for each candidate in it. A set gets one judge per document, run in parallel. No dispatch mechanism ⇒ the writer judges with the brief's test, and the cold read rechecks every reason (`references/document-sets.md` § Rubric).
- **Brief:** "Read `<path>` in full. For each candidate below (a rule, then its reason), answer `obvious` or `non-obvious`, with one line of why. A reason is obvious when a competent engineer holding this document would supply it unprompted. Quote each candidate back verbatim. Edit nothing."

### Citations

Principles are cited by number, sections by heading, always in parentheses: "(principle 4)" in the document itself, "(auth, principle 3)" or "(API protocol § Rate limits)" for a sibling, by its title. `doc-lint` resolves each against the folder and blocks a number or heading that does not exist, so a renumbering is caught at the next lint, not by a reader.

### What a doctrine document is not

| It is not | That is |
| --- | --- |
| A tour of the code that implements the concern | The code graph |
| The catalog of routes, error codes or variables | An API reference or environment registry |
| The one feature that happens to use the concern most | That feature's own document, which names this document in its Scope |
| The story of how the concern got this way | The subject's architecture decision (`decisions/`), whose Decision Changelog tail carries how it moved, and the changelog for the when |
| A record of which product has built which part | That product's plan, backlog, or security overview |
| A description of the repository it sits in: its product, domain, stack or documents | That product's feature documents, system overview and decision records |
| A restatement of a sibling's rule for completeness | A citation of the sibling's principle, with the one clause of context the sentence needs |
