Skip to main content

Doctrine · Doctrine as a file

Doctrine you can review

Your ruleset and every constant it reads, as one file you can diff, approve and hand to another site.

Doctrine changes rarely and matters enormously, which makes it the wrong thing to edit only through a screen. Export it and you get a single YAML document you can put in a repository, review in a pull request, and use to stand up a second site identically.

What the file contains

Three parts, and the third is the one that makes it portable.

doctrine.yaml
schema: doctrine.v1

constants:
engage.assign_below_tti_s:
kind: number
value: 20.0
engage.max_effectors_per_target:
kind: number
value: 1.0
fusion.cluster_gate_m:
kind: number
value: 85.0

rules:
- id: self_defence
template: custom
order: 0
enabled: true
category: engagement
stage: act
when:
all:
- test:
fact: asset_under_attack
op: eq
rhs:
operand: bool
value: true
then:
- effect: emit
verb: alert
target: subject
priority: critical

schema names the format, so an import can refuse a file that is not one. rules is the set in force, in evaluation order. constants carries the value of every constant those rules reference.

Export it

curl -H "X-API-Key: $DOME_API_KEY" \
https://your-deployment/api/doctrine/export > doctrine.yaml

The response is application/yaml, not a JSON envelope, so it can be redirected straight to a file and committed.

Import it

curl -X POST --data-binary @doctrine.yaml \
-H "Content-Type: application/yaml" \
-H "X-API-Key: $DOME_API_KEY" \
https://your-deployment/api/doctrine/import

Three checks run before anything is stored, and each is a refusal rather than a silent correction.

The constants have to travel with the rules. A rule that reads a constant the file does not carry is refused. A rule reading a missing constant would never fire, and a rule that silently never fires is worse than an error at import time.

A locked rule may only arrive exactly as shipped. self_defence can be present in the file, byte for byte as exported, but it cannot be altered and a new locked rule cannot be invented. No import can forge the right of self-defence.

Only doctrine.v1 is accepted. A file whose schema says anything else is rejected naming what it found.

A rejection tells you the rule and the reason. rule keep_out_breach references constant identify.never_below_confidence, which the document does not carry is the shape of the message.

Export, import, export gives you the same bytes

Round-tripping is byte-identical. Constants are sorted and every field has a fixed order, so a re-export of an imported file matches the original exactly.

That is what makes the file reviewable. A diff between two exports contains only what someone actually changed, with no reordering noise to read past.

Standing up a second site

Export from the site you have tuned, import into the new one, and the second site is running the same doctrine including the numbers the rules depend on.

What does not travel: sites, zones, assets and credentials. Those are specific to a place. Doctrine is the part that should be identical across places, which is why it is the part that is a file.

Where to go next