Shaping a type¶
Each type the framework ships has a shape. A type is one kind of record, and a record is one Markdown document with YAML
frontmatter above its prose. A type's shape is the fields in that frontmatter, the sections in the body, and the rules
kac checks it against. This page takes the types one at a time. Each section says what a record of that type is for,
then why its fields and sections serve that purpose. Read it when you write a record and want to know what a section
asks of you, or why a field is required.
A corpus is one repository of knowledge records kept in git. An export is the machine-readable copy kac export writes
for another corpus to read.
The default types introduces every type in one line, and Lineage says where each one came from. Each section below closes on the one sentence about the export you need as an author: what a reader elsewhere sees of your record without opening it. The export format states the rest, key by key.
What every type decides the same way¶
These decisions repeat across the set, so they are stated here once.
owner names who keeps a record true, and stays in its corpus. It is a fact about this corpus's stewardship, and a
reader holding a copy elsewhere cannot ask that person anything. Every type that exports keeps it out, except
deviations.
A procedure's steps are one sequence. Processes and runbooks are followed whole and in order. Neither declares its steps as parts, the pieces of a record a reader can cite on their own. A step lifted out of its sequence is one a reader can act on alone, and acting on it alone is how an incident gets worse.
last-rehearsed and rehearsal-frequency go together. A walk says nothing about staleness without the cadence you
read it against, so the two travel as a pair.
last-rehearsed records who walked a procedure, and when. Its value is the last walk, as
{ at: "2026-10-20", by: human:alex.doe }, or never. Git keeps the earlier walks. by names a person or an agent
and never a process, because a procedure a process follows is automation. Only a runbook adds method, because only a
runbook can be walked without causing what it is for.
A record in force is retired, never deleted. Something outside the corpus may still cite its id. Under
validate --since, retire-not-delete warns where a record whose status was its type's in-force: value at that
revision has gone. A draft, or a record already retired or superseded, deletes with no finding.
A type page states its level of detail and cadence in prose. The section says what one step, rule or part contains, how often a record changes, and how often new ones arrive. It guides a writer and whoever triages a finding, so no field declares it and no rule reads it.
The types¶
One section per type, in tier order. A tier is the level of authority a type sits at, and Taxonomy lists the four.
adrs¶
An ADR (architecture decision record) records a decision that affects more than one repository, and the reasoning behind
it. Its decision never changes after it is accepted. A later ADR supersedes it instead, and a standard cites the ADR
its authority comes from in derived-from.
Decision states the choice, and that sentence is the record. Consequences is required beside it: a reader who sees
what a decision bought but not what it cost sees a better decision than the one you took. Context opens on the problem
the decision answered. Alternatives Considered argues against the options the estate weighed, and is usually the
longest section.
supersedes and superseded-by are a pair. A superseded decision still binds whatever was built under it, so a reader
meeting one needs the id that replaced it.
A decision states its constraint, and cites a descriptive record only for background. A descriptive record, such as
a service or a glossary, changes as the estate does. An ADR is not rewritten once accepted. decision-cites-descriptive
warns where a link in Decision or Consequences lands on a record of a descriptive type. A link in any other section
passes. The section stands in for why the link is there, so the check is a warning.
A decided ADR is never edited in place. Under validate --since, immutable-after-accepted compares each ADR
that was accepted or rejected at that revision with its state now. It may move status, superseded-by,
review-by and accepts, fix a typo, reflow a line or correct a link target. Anything more is an error, because a
standard citing the ADR in derived-from relies on the words it was decided with.
In the export: Decision and Consequences travel whole and Context as its opening paragraph, while
Alternatives Considered and deciders stay behind.
postmortems¶
A postmortem records what happened during one incident, so that the estate, and anybody facing the same failure, can learn from it. Once published, it changes only to fix a typo or a link, so a reader citing it reads the account the estate stood behind. What was learnt later goes in a new postmortem.
The sections follow the order a reader asks their questions in:
Summarylets a reader decide in fifteen seconds whether the rest is theirs.Impactstates what customers lost in its opening paragraph, and measures that loss against the estate's own non-functional requirements below it.Resolutionsays what ended the impairment, which a reader facing the same one needs first.Root causeandContributing factorsare what a reader can act on, and most of the improvement lives in the factors.TimelineandActionsrecord this estate's own clocks, alerts and work items.
The three lessons each take a heading of their own. What went well, What went wrong and Where we got lucky are
each asked for, and a bare one is refused, so a record states what worked as well as what failed.
Three moments fix the incident, each as a timestamp. occurred-at is when the impairment began, detected-at when
somebody first knew, and restored-at when service was back for users. Each is a timestamp, because the gap between the
first two is usually measured in minutes.
restored-at is recovery, not resolution. It is the span an availability budget counts, and the one the DORA
metrics ask about, so an incident whose actions run for weeks still
has a restored-at on the day. Nothing requires it to follow detected-at, because an incident can recover before
anybody notices.
duration restates the span those moments already fix, so that an index can show it without computing one.
duration-matches-the-moments fails a value the moments refuse, and its message gives the value to write. prompted
lists the ADRs, runbooks, non-functional requirements (NFRs), fixes and standards the incident caused.
A published postmortem is never rewritten. Under validate --since, immutable-after-published compares each
postmortem that was published at that revision with its state now. It may move status, review-by and accepts,
fix a typo, reflow a line or correct a link target. Anything more is an error, for the reason a decided ADR's is: a
reader citing the account relies on the words it was published with.
In the export: the three moments, duration and prompted travel with every section except Timeline, Actions
and Related, because Timeline and Actions name clocks and a tracker a reader elsewhere cannot open.
policies¶
A policy states a commitment the estate makes: what it commits to and why, largely independent of any stack, and changing rarely. Each commitment is a clause, a row with an id of its own, so a standard can cite the one clause it puts into practice.
Purpose says why the commitment exists. Scope and Exceptions bound the clauses beneath them, because a reader
holding a clause without them reads a stricter policy than the one you wrote.
A clause states its level as a modal. MUST and COULD open the same shape of sentence, so a reader has to know
this type's modals to tell an obligation from a suggestion. kac reads the modal into a level key of its own, and an
agent asking what it must do filters on one value.
A clause's Alignment cell maps it to an external framework. The framework register says
how that mapping is checked, and what it claims.
A clause id stays once the policy is active. A standard cites a clause by its id, and the citation outlives any
edit to the policy. Under validate --since, clause-id-kept compares each policy that was active at that
revision with its state now. It fails where a clause id the policy had there has gone. A reworded clause, a new clause
and a new title pass. A clause that has to go takes a new policy, and this one is retired.
Two policies binding one obligation give it one clause id, and each signposts the other. The signpost closes the
clause, as ([pol-ACCS].DUTIES states the general duty). You write both ends, and kac validate checks they agree.
part-ref fails a signpost to a clause that does not exist. pair-one-way fails a clause that a clause of the same
id signposts, where it does not signpost back. shared-id-unsignposted warns on an id two policies use with no
signpost either way, because two authors may pick one word by coincidence. A scoped signpost, such as
[eng:pol-ACCS].DUTIES, reaches a corpus that cannot write the other end, so it forms no pair. A retired policy
forms none either, so the policy that replaces it may keep its clause ids.
In the export: each clause travels as its own entry with its level, beside Scope, Exceptions and the opening
paragraph of Purpose, and no alignment travels: frameworks.jsonl sends
that edge from the framework's end, with the standing beside it.
standards¶
A standard is the rulebook you build to. It puts a policy's clauses into practice as imperative rules, with examples and a conformance checklist.
Rules has one heading per rule, and kac validate requires a bold modal on every bullet beneath it. Each heading
opens with the rule's id, as ### PERMS: A job declares the permission it needs, and a citation names the rule as
std-CI.PERMS. The id survives a reworded heading, where a slug would not, and a link still lands on the slug of the
whole heading. Summary says what the rules govern, because a rule read without it binds more than the standard does.
Conformance checklist tests what the rules require, and nothing else. Examples shows them against one stack, and
Rationale and provenance says why each rule exists.
A rule states MUST, SHOULD or MAY, as BCP 14 does. A MUST is the outcome the standard's owner answers for, and
departing from it takes a deviation. A SHOULD is the usual way to reach it, and whoever departs from it says why in the
change. A bullet may end with one short reason opening "because", so the reason travels in the export with the rule.
Every standard ends with a line saying how to depart from it, which the template writes after the Changelog. The
type's lineage.divergence says why it follows public API rulebooks here, where HCGF keeps a standard to mandatory
requirements.
implements cites the policy clauses this standard puts into practice. The citation points one way, upward. A
policy lists no standards back, and a clause no standard cites is a normal state. Each rule closes on a Covers line
naming the clauses it discharges, and kac validate checks the union of those lines equals the field.
A rule leaning on a rule in another standard cites it, because a standard composes by union. A rule citing a policy
clause writes it as [pol-INTC].HOLDS, and that link ends at the policy.
depends-on composes standards across folders. platform/dotnet/testing.md adds the .NET detail to
common/testing.md, and the two sit in different folders. A reader follows depends-on to know which further standards
they have to apply. superseded-by sends a reader arriving from an old citation to the standard that replaced this one.
A rule id stays once the standard is active. A control's verifies cites a rule by its id, and so does a
consumer's corpus. Under validate --since, rule-id-kept fails where a rule id an active standard had at that
revision has gone, as clause-id-kept does for a policy's clause id. A rule that has to go takes a new standard, which
names this one in supersedes.
In the export: each rule travels as its id, its heading without the id, and one entry per bullet, giving the
bullet's level and its text in your Markdown, beside Summary, Conformance checklist and implements. Examples
and Rationale and provenance stay behind.
controls¶
A control says how a standard's rules are verified: the mechanism, how often it runs, and the evidence it leaves. It exists so a reader can tell a rule somebody checks from a rule that is only written down.
What it checks, How it works and Coverage and gaps are all required. The third is the one a reader needs most: a
check described without what it misses reads as stronger than the one you built.
mechanism: not-enforced records a rule nothing checks. It is a value like any other, so the gap is written down
and counted. mechanism and frequency are the keys an agent filters on.
Three more fields date and place the check:
evidencesays where the proof lives.last-verifiedsays who last ran a manual check and when, so a check that happened reads apart from one that was only planned.verified-by-a-person-or-agentrefuses a process asby, because a check a process runs is acicontrol.check-states-no-methodrefuses amethod.review-bysays when somebody reads the record against the check it describes, which is a different question from how often that check runs.
verifies names the rules a control checks, each as std-CI.PERMS, and never a standard whole. A control checking
every rule of a standard lists every rule, so a coverage report can say which rule each control proves. The standard's
verified-by names the control once, however many of its rules the control cites, because reciprocal folds a rule id
to its standard.
In the export: the fields and the three required sections travel, not-enforced controls included, because
withholding them would publish a coverage figure this corpus cannot show. verifies travels as rule ids, as
std-CI.PERMS, which a reader of the shape before it would have read as standard ids.
deviations¶
A deviation records a knowing departure from a rule, the person who accepted the risk, and the date somebody looks at it again. It is the one type written to be read by somebody else: the people who carry the risk usually sit outside the team that raised it.
Six sections make the argument, and a reader who sees five of them sees a smaller departure than the one you took:
What we are doing insteadWhy we need itWhat the risk isWhat compensates, which limits that riskHow it closes, which ends the departureScope, which says how far it applies
owner names the individual who accepted the risk. A register that says what was excused without saying who
excused it is not a register. This type takes the human: form alone. Accepting a risk is a person putting their name
to a consequence, and a post cannot do that: whoever holds it on the day would be accepting something they never read.
assigned-to names whoever does the work, and admits a post.
risk rates what is left once what compensates is working. It is what a reader sorts a register on, and it decides how
soon review-by may fall.
Three dates say whether a departure is live, overdue or over. accepted-on, review-by and closed-on sit beside
status, so you can check the dates against the status. Nothing moves the status when review-by passes, because a
departure left standing is the state worth seeing. Two checks warn on it instead:
expiryreports anactiverecord past its date, whose acceptance is due for review.draft-expiryreports adraftrecord past its date. Nobody finished accepting that departure, and the code may already be taking it. A draft whose date is still ahead is silent.
A closed record is silent, because the departure is over.
departs-from names a clause that binds. Departing from an advisory modal, such as a policy's COULD or a
standard's MAY, takes a reason in the change, and no deviation. departure-needs-none warns on a draft or active
record naming a clause that states no MUST or MUST NOT, or a rule none of whose bullets does. It reads an imported
clause's level from the export it came in.
Some clauses admit no deviation at all. pol-DEVI lists them in prose, under its Exceptions section. No field states
that list, so no check reads it. Whoever accepts the risk reads that list first.
In the export: every section but Related travels, and owner with them, the only type where it does.
assigned-to stays behind, because a consumer reads who carries the risk.
nfrs¶
An NFR (a non-functional requirement) states one quality a service or an offering must meet, with how it is measured. It exists so that whoever builds or runs the thing has a number to build against, and a stated response when the number is missed. An NFR is normative, so a reader may act on it without opening anything else.
Target, Why this number, How it is measured, What a breach costs and What we do about a breach are all
required. characteristic, target, window, alert-after and measured-by state as fields what those sections
state at length. The fields are what a reader filters and sorts on. The sections are what somebody building against the
number reads.
The cost of a breach and the response to one are two sections. The SRE workbook separates an error budget from the
error budget policy that spends it. Both headings are required, so required-section reports one a record left out.
characteristic takes 25010's subcharacteristic level. An estate commits to availability, latency, throughput,
capacity, recovery, scalability or accuracy. It does not commit to reliability, which sits above availability and
recovery and says nothing about the other five. One record states one quality, so a service needing both a latency
target and a recovery target has two.
window is required of an availability, capacity, latency or throughput target. A rate or a percentile only means
something over a stated period. A recovery, scalability or accuracy target binds each event or each value, so it needs
none.
alert-after states the alert's configured delay, and never a detection time somebody measured. That delay is what
an estate can state before anything breaks, as OpenSLO's alertAfter does. A
recovery target already covers how fast a fault is noticed.
A delay claims an alert exists, and alert-after-needs-an-alert asks the services whether one does. Where
applies-to names an offering, the check follows its implemented-by to the services behind it. A service stating
monitoring-output: alert or ticket satisfies the check. One service not yet obliged to state the field leaves the
whole target unjudged.
Constraints states the limits a target sits under, because a target read without them reads as a stronger promise
than the estate made. It states them in words, because constrained-by resolves only where the corpus adopted
integrations. A corpus that did not still has the cap, and writes it here.
Current actual is required. A target read without the reading beside it says nothing about where the estate
stands.
status: aspirational says nobody is held to the target. The SRE workbook keeps an aspirational objective measured
and tracked, and exempts it from the error budget policy. Here that exemption is What we do about a breach saying
nobody is paged, and status is what a reader sees first.
In the export: the fields and every section travel except Current actual and Related. Current actual is a
reading taken on the day somebody wrote it, and an export cannot say how old it has since become.
fixes¶
A fix records a problem somebody has solved, with a resolution somebody has verified. It exists so the next person to meet the symptom finds the answer before they spend an hour on the cause.
symptom-keywords is what a lookup searches on. The sections follow the order a reader works in. They match on
Symptom, check that the Environment and the Cause are theirs, then act on the Resolution. Why it happens is
optional, and says what class of problem this one belongs to.
Environment is required because applies-to takes service ids alone. A fix about a laptop, an editor or a pinned
tool version has no service to name, and a reader still has to match the versions.
verified says how far a resolution has been taken on trust. It lists who checked the resolution and when, and
kac derives trust from it. status and review-by say whether the answer is still true. fixed-upstream says the
cause is gone, and keeps the record for whoever searches for the symptom.
status: draft is the value an author writes before anybody checks the resolution. verified is required of every
other status and not of a draft, because an agent writing a fix from a filed observation cannot name who will verify
it. A corpus can withhold its drafts from the export, so no unchecked resolution leaves it.
How we found it is optional. The route is often the more reusable half of a fix, to somebody who can run the commands
it lists.
In the export: symptom-keywords, verified and the five sections from Symptom to Why it happens travel, and
How we found it stays behind, because a reader holding a copy can run none of its commands.
services¶
A service record describes one deployable component: what it does, where its code lives, what it calls and what data it keeps. Every other type cites service ids, so the record exists to make each id resolve to something a reader recognises.
What it does and Where it lives are both short, and together they say which deployable this is and where its code
sits. Environments is required, and lists the addresses the service runs at. Operational notes describes running it.
repos lists repository names, and the corpus resolves them. A service whose content is published from one
repository and served from another has two answers to where its code lives, so the field is a list. Every id in this
framework is a bare key, and a repository name follows that design: repos-base in
.corpus.yaml states the host once, and an entry is <repo>, or
<group>/<repo> where the base sits one level above the project or owner. Backstage, OpsLevel and Cortex each do the
same, leaving the value a bare org/repo. Each part is spelt as the host spells it, because a corpus cannot make its
estate rename a repository.
Where it lives keeps its link, so the repository is stated twice: once as a join key and once as a URL a person
follows. mirrors-repo-links resolves each entry against the base, compares the result against the links under the
heading in both directions, and warns where they disagree, since a service can sit outside the estate's usual host.
depends-on is the estate's own graph. A reader walks the edges without opening a record. The edges run one way,
downward: a service records what it calls, and the reverse view is a question asked of the whole graph.
Dependencies states the coupling, and depends-on states the calls. Dependencies may name an id the field
omits, on purpose. It names a coupling a reader expects to find there, and says why that coupling is not an edge: a
message read off a bus, or a build that never calls the service it builds. So depends-on declares no
mirrors-section:, which would report every one of those.
criticality is ranked, and the graph is where the ranking is read. critical sits above important, which sits
above supporting. ordered: true on the enum in .schema/_enums.yaml declares that the first value listed is the
most significant. dependency-criticality then warns where a service outranks a service its depends-on cites. The
edge is often a degradation the estate accepts. The record then says what degrades, and keeps the warning in
accepts:.
data-stores lists the data records this service keeps, and Data says in prose what it does with each.
component-type and platform draw their range from the corpus. An estate lists its own deployables and the runtimes a
contributor has to learn, so one schema above several estates can state no range at all.
interfaces points at a contract, and never copies one. The value is a whole URL, because nothing derives one:
OpenAPI 3.1.1 prescribes no path. The field is optional on every service,
because a command line tool or a web page has no machine-readable contract. Each interface's type draws its range from
the estate. No rule checks that a contract is there, because kac cannot open a source repository.
monitoring-output states a commitment, and never a rota. A paging tool's id tells a reader of a corpus nothing,
so this field says what a live problem raises instead:
| Value | What a live problem raises |
|---|---|
alert |
A person acts now |
ticket |
The system files one, and a person acts later |
log |
A record nobody reads |
none |
Nothing |
The range is shared in .schema/_enums.yaml, so no estate can drop none from a list of its own.
critical-service-is-alerted warns where a live or deprecated service graded critical states none. It has the
same status guard as the field, so stating none on a draft is never worse than leaving the key out.
In the export: the frontmatter travels, depends-on included, which is the reason this type exports at all, with
What it does, Where it lives, Dependencies and Data. Environments and Operational notes stay behind, because
both describe running the service.
data¶
A data record describes one data domain: which service owns it, how sensitive it is, how long it is kept, and where
personal data flows. It exists so a reader following a service's data-stores finds a statement they can act on.
classification, personal-data, data-subjects, retention and region are the keys a reader filters on. Each has
a section that qualifies it. Classification says why the data takes that grade, and what the domain excludes.
Retention says how deletion is carried out, and whether anybody has checked that it runs. A reader taking the
frontmatter value alone gets neither.
flows-to resolves against services and integrations, so a reader can walk from a data domain to the systems that
receive it. Flows states what each recipient gets and where they process it. Purpose states the lawful basis beside
the use it supports. Entities names the domain's objects in the estate's own words.
A record here contains no actual data. no-actual-data fails an email address outside example.com.
data requires review-by, and services, integrations and offerings do not. A data record's
classification, personal-data, retention and region are claims about a store, and nothing in the corpus checks
one. The ICO asks you to review retained personal data regularly, and NIST SP 800-53r5
RA-2 asks that a categorisation be revisited. Neither sets an interval, so each record sets its own date.
In the export: every section travels except Related, which is navigation a reader replaces with the record's own
links.
integrations¶
An integration records an external system the estate depends on: what it does for you, how it fails, what the vendor promises, and how you would leave. It exists so a reader knows what breaks when a vendor is down, and how hard that vendor would be to replace.
What it does, Contract and Failure modes are required. Contract states the endpoint, the authentication and
where the credential is kept. Trial criteria, Commercials and Contacts are optional, and serve whoever owns the
account.
their-sla states the vendor's promise in the vendor's own words. A reader setting a target of their own reads what the
vendor promised, and a paraphrase drops the window and the measurement point. replaces and successor are a pair, so
a reader holding an old citation finds the system that took the traffic.
Exit is required of a critical or important integration still in use. exit-required warns on one that has
none. Article 30(3)(f) of the EU's Digital Operational Resilience Act
asks a contract for such a service to state an exit strategy. A retired integration is excluded, because leaving is
already done, and a supporting one, because nothing a customer feels depends on it. A trial integration is asked
like any other: it is the one most likely to be left.
Data protection belongs to data. Article 30(2) of the same Act puts data location and personal data in the vendor
contract. Here a data record states them, through region, personal-data and flows-to, which resolves against an
integration id. An integration record repeats neither.
In the export: What it does, Failure modes and Exit travel. Contract, Trial criteria, Commercials and
Contacts stay behind, because they describe owning the account.
offerings¶
An offering records what the estate offers a customer and why, as a hub linking to what implements, tests and
constrains it. It is what a stranger asks about first. hub-not-specification weighs the record against its
outbound links, which keeps it short.
The consumer group decides where one offering ends and the next begins. Who it is for is required, and it names
that group, as ITIL 4 defines a service offering. Two groups served in two different ways are two offerings, however
much they share underneath. spans-more-than-one-service warns where one service delivers the whole of an offering,
because a record that names one service restates the service record beside it.
nfrs is required once an offering is live. A customer already has it, and no other field says how well it has
to work. A corpus that declined nfrs is not asked, and adopting the type starts the obligation with no edit to
.schema/offerings.yaml.
Where the detail lives is the only place the work items are written. The type declares no field for them: a
tracker reference is a link a reader follows, not a value an agent filters on, and one estate's ADO#1150 is another's
gh#2101.
implemented-by and nfrs each declare mirrors-section: against that list. The record states each id twice, in the
frontmatter an agent reads and in the list a person follows, and related-matches-section reports either end naming one
the other does not.
feature-files lists the test files that specify the offering. A path names its repository first, so a reader can tell
which repository a test sits in without resolving the rest. feature-file-repo checks the opening segments, as many as
an entry has, against the repositories the implementing services name.
In the export: every section travels. A reader sees each work item's label in Where the detail lives and not its
address, which would not open outside the estate anyway.
tools¶
A tool record is one entry in the approved-software register: what the estate chose, rejected or deprecated, and the version ranges it stands behind. A register says what an estate builds on, which is the question an inventory exists to answer.
packages is what makes the register an inventory. CycloneDX identifies a component by package URL and SPDX by an
external reference of the same form, so one entry per package is what a manifest can be matched against. The version
range sits on the package, because a family chosen together is often pinned apart: Spectre.Console and
Spectre.Console.Cli are one decision at two version ranges.
licence and licence-declared split what a person concluded from what the package states about itself. SPDX
splits it the same way, at PackageLicenseConcluded and PackageLicenseDeclared.
licence is required and accepts NOASSERTION. A register that can leave the field out hides an entry nobody screened,
and NOASSERTION shows one. licence-declared keeps a string SPDX has no expression for, so npm's
SEE LICENSE IN README.md is recorded as written. That string is the evidence for why the entry needed a conclusion at
all. Licence and obligations says what the licence obliges you to, and conclusion-states-a-reason asks for it where
the two values differ.
homepage is required, so a reader can tell the project from a fork of it, the first question the OpenSSF evaluation
guide puts.
decided-on and review-by are the two dates an approval needs. decided-on says when the current stance was
settled. review-by expires it, and review-in-date warns once the day has passed. Without the second, an approval
taken once governs new work for ever.
Status is optional, and says why the tool sits where it does, which status and decided-on cannot.
exit-states-a-reason asks for it once a tool is deprecated or rejected, because those are the stances that owe the
next person an explanation. replaces and successor are the same move written as ids. replaces is a list, because
one tool can take over from several, and each of them names it as successor. Trial criteria and Alternatives
considered record how the estate reached the decision, and decided-in cites the ADR that argued it.
Accessibility keeps the assessment of a component that renders a surface, which a published accessibility statement
is built from. Where it is used lists the records that use the tool.
In the export: the frontmatter travels with What we use it for, Status, Accessibility,
Licence and obligations and Where it is used. Trial criteria and Alternatives considered stay behind.
glossary¶
A glossary defines the terms whose meaning is specific to the estate, or easily confused. It exists so a reader, or an
agent, takes a word in the sense the estate means. Scope says which context the glossary admits, so a contributor can
decide whether a new word belongs. Each term is an H3 under Terms. narrows names the more general glossary this one
narrows.
A term opens on its definition. A definition on its own is mostly guessable from the word, so up to three labelled lines follow it, each answering a different question:
| Label | What it gives |
|---|---|
**Also:** |
Another name for the same thing |
**Avoid:** |
A name the glossary has dropped |
**Not:** |
A neighbouring thing the term is confused with |
A reader searching an acronym finds the term through Also, which the heading alone could not give them. SKOS calls
that an altLabel and DITA calls it a glossAlt.
A redefinition links the entry it departs from. Where two glossaries in one corpus define the same term,
redefinition-unlinked warns unless one of the entries links to the other at the term's anchor. A glossary every corpus
shares cannot link a record only one corpus has, so the rule asks for one link. It reports against the glossary further
down its narrows chain.
In the export: each term travels whole as its own entry, each labelled line under its own key, with the record's
status and review-by repeated on every term. A copy taken a year ago reads as it did on the day, so the date on each
grepped line is the signal a reader otherwise lacks.
explanations¶
An explanation is narrative that helps you understand how something works, or why it is shaped the way it is. It is the residual type, for prose that fits no other.
explains admits a standard, a process and an ADR as well as a service or an offering. Diátaxis starts an
explanation from a why-question about a subject, and a subject is not always a deployable thing. An account of why the
testing approach is shaped as it is explains a standard. Requiring the field at all is this framework's own, and it is
what stops the residual type filling up with prose attached to nothing.
What this covers says what the record leaves to another record. The Good Docs Project's concept template opens
with a required section that fixes the scope, and Diátaxis asks an explanation to stay closely bounded. The body between
that section and Where the detail lives is free-form, because an explanation's shape follows its subject.
In the export: both declared sections travel, and every record a reader can cite in them arrives as a bare id.
reports¶
A report answers one question about the corpus over the whole of it, with the judgement a person added. kac report
writes the headings the question needs, so the type declares no sections and the body is free-form.
The frontmatter answers the one question a reader asks of a report: whether the answer is still true. sources lists
each corpus the report answers for and the content-version it was true of, so a reader at a later version knows the
answer has moved on. verified lists every verification the report has had, and trust is the tier kac derives from
it.
In the export: the frontmatter alone travels, and a reader opens the record for the body.
processes¶
A process is a planned procedure followed at a desk: releasing, onboarding, provisioning, rotating a secret. It exists so the task is carried out the same way each time, by whoever picks it up.
Five sections are required, in the order a reader uses them: When to use this, Prerequisites, Steps,
Verification and If it goes wrong. A reader decides from the first two whether they may start, before step 1.
Prerequisites states the access, the tooling, the prior process and the skills a reader needs.
No field records the skills. Prerequisites states them in prose, and nothing checks that a process names them.
followed-by-a-person-or-agent refuses a process as the by of last-rehearsed, and rehearsal-states-no-method
refuses a method.
In the export: When to use this, Prerequisites and the last walk-through travel. The steps stay behind, and so
does requires-access, because Prerequisites already states the access in prose.
runbooks¶
A runbook is an incident-time procedure, read under pressure: terse, imperative, and structured as a decision tree. It exists so whoever is paged can restore service without working out the steps.
Symptoms comes first. A reader arrives holding a symptom and no id, and symptoms-first fails a runbook that
opens on anything else. Impact says who is affected, so the reader can tell whether this is worth waking somebody for.
The required sections after them are Immediate actions, Diagnosis, Resolution, Escalation and Communication,
so one page both finds the cause and resolves it. The desired outcome is the last line of Resolution, opening
Confirmed when, so the reader reads it where they stop.
requires-tools and requires-access decide whether a reader may start at all. severity is what an agent sorts on
where several runbooks match. last-rehearsed says who walked the runbook last, when, and with which method: live
caused the fault, and tabletop read the steps against the system. walk-method-stated asks for the method of a
recorded walk. walked-by-a-person-or-agent refuses a process as by, because a fault a process injects with nobody
walking the steps is a control.
In the export: Symptoms, Impact, the tools, the access, the severity and the last walk travel, its method
included. The steps stay behind, because a reader who has found the right runbook fetches it whole.
The framework register¶
A policy states its alignment to an external framework clause by clause. The alignment is a mapping, not a
certification, and four checks keep it true. alignment-unlinked asks whether a cell's citation is a link. The other
three read frameworks.md, the corpus's own register of the frameworks it has taken a standing against.
aligns-with summarises the references a policy's clauses cite, grouped by framework. Grouping is what keeps the
frontmatter short. The framework is named by the label its Alignment cell uses, version included, so
[ISO 27001:2022].A.8.24 in the table is ISO 27001:2022 in the roll-up.
alignment-rollup compares the roll-up against the cells in both directions. A reference in a cell and not in the
roll-up leaves the generated index under-reporting what the policy covers. A reference in the roll-up and not in any
cell is a claim of coverage no clause can show, which reads as evidence, so it is an error.
alignment-unlinked reports a citation Markdown never made into a link. [UK GDPR].Art.5(1)(e) with no definition
behind it stays on the page as text. The cell then states no mapping, and alignment-rollup, framework-posture and
framework-uncited each see a clause that cites nothing. While the definition is missing, alignment-rollup does not
report aligns-with as claiming that framework.
framework-posture and framework-uncited check the register and the clauses against each other. The register says
whether you are obliged to a framework, self-obligated to it, or borrowing from it. alignment-rollup reads that
standing to decide which references it includes. A register entry no clause cites is a standing nothing acts on, and
reads to an auditor as coverage.
Only a binding standing obliges a summary. A clause may cite a framework you took ideas from, and that citation is provenance rather than obligation. Lineage says what the three standings mean.
Where to go next¶
Contributing says how a record you have written is reviewed and merged.