v0.29.0
Added
-
A process past its rehearsal cadence is reported.
stalenessnow runs.kac validatewarns on a process whose
last-rehearsedis"never", and on aquarterlyorannualone more than 92 or 366 days past that date. The rule
was declared and ran on nothing, so a corpus could say every procedure was rehearsed on a cycle and be asked for no
evidence.on-changeandper-releasestate an event, which no window measures, so a process using either is
reported only whilelast-rehearsedis"never". -
days_since('field')measures a date field against the day of the run. An expression could already compare two
dates a record states, and ask whether one had gone by. Neither asks how old a record is. The fact answers zero where
a field is absent, is not a date, or names a day the run has not reached, so a rule comparing it against a threshold
leaves an absent value torequired-field. -
Every rule in a standard is held to a keyword in bold capitals.
part-modalreads the bullets under each rule
heading and reports one that names none ofMUST,MUST NOT,SHOULD,SHOULD NOTorMAY, one that leaves a
keyword in plain text, and a heading gathering no bullet at all. BCP 14 gives a keyword its meaning only in capitals,
and this corpus makes bold the thing a reader skims, so a keyword carrying one of the two bound nobody and nothing
said so. A type declares its own set inparts.binding:andparts.advisory:, which a heading source may now carry:
a glossary declares none and is asked nothing. -
A standard names the standards it rests on.
depends-ontakes standard ids, andkac validatechecks each one
resolves. ISO/IEC Directives Part 2 makes normative references a clause of every document, and a folder cannot say
thatplatform/dotnet/testing.mdis no use withoutcommon/testing.md. The field travels in the export. -
A superseded standard names its replacement.
superseded-bytakes a standard id and is required wherestatus
issuperseded, withsupersedesthe same edge read the other way. Both travel in the export, so a reader arriving
from an old citation is sent to the standard that replaced it. -
A policy in force says the day it came into force.
active-fromtakes the day, quoted, andkac validate
requires it wherestatusisactive. NIST SP 800-53 Rev. 5's-1controls and ISO/IEC 27001 clause 5.2 both ask a
policy to record its approval, andownersays who without saying when.review-not-before-activefails a
review-byearlier than it. The date stays out of the export, andpolicy-lookuplists it among what stayed
behind.kac newsends a_template.mdcarrying the field, and a corpus already holding anactivepolicy owes
the date at its nextkac update. -
An integration says how the estate would leave it.
Exitis a section, andexit-requiredwarns where a
criticalorimportantintegration still in use has none. Article 30(3)(f) of DORA asks an ICT contract for an
exit strategy, and the section travels in the export.kac newsends a_template.mdnaming it. -
A retired integration names what took over.
successortakes an integration id,replacesis the same edge
read the other way, andkac validatechecks both ends.retired-has-successorwarns where aretiredintegration
names none. Both fields travel in the export. -
An integration on trial says what would end the trial.
Trial criteriais a section, and
trial-criteria-requiredwarns where atrialintegration has none. The section stays out of the export, because
a consumer readsstatus. -
A control that never stops says so.
frequencytakescontinuous. A control whosemechanismis
runtime-alerthas to carry a frequency, and none ofper-prthroughannualis true of an alert rule that
evaluates without stopping. -
A manual control says when it last ran.
last-verifiedtakes the day, quoted, or"never", andkac validate
requires it wheremechanismismanual. An automated check leaves a run in its own logs, and a periodic human
check leaves nothing otherwise. It travels in the export, andkac newsends a_template.mdnaming it. -
A data document says whether it holds personal data.
personal-datatakesnone,personalor
special-category, andkac validaterequires it.retentionis now required from this field rather than from
classification, so data that is confidential and personal is asked for a retention period. -
A data document says who the data is about.
data-subjectstakes the categories of people, in the corpus's own
words, andkac validaterequires it wherepersonal-datais anything butnone. GDPR Article 30(1)(c) asks for
the categories of data subjects, and the NIST Privacy Framework asks the same as ID.IM-P3. -
A data document says where the data is kept.
regiontakes a cloud region or a place, andkac validate
requires it. TheWhere it livestable asked for it and nothing read the answer. -
A data document says what the data is for.
Purposeis a required section. GDPR Article 30(1)(b) asks for the
purposes of the processing, and the NIST Privacy Framework asks the same as ID.IM-P5. -
The
Flowstable says where each recipient processes the data.kac newsends a_template.mdwith the
column.regioncovers the owning service, so a transfer out of the country is recorded beside the recipient that
makes it, which is what GDPR Article 30(1)(e) asks about. -
A data document says when someone checks it again.
review-bytakes the day, quoted, andkac validate
requires it. It travels in the export, which movesdata's shape to version 2.classification,personal-data,
retentionandregionare claims about a store that nothing in a corpus checks, and no field asked anybody to
confirm them. The ICO asks you to review retained personal data regularly and to justify how often, and NIST SP
800-53r5 RA-2 asks that a categorisation be revisited.classification-in-datewarns once the date has passed. -
A deviation rates the risk it leaves.
risktakeshigh,mediumorlow, andkac validaterequires it.
The rating is the risk left once what compensates is working, andhigh-risk-review-windowwarns where ahigh
rating setsreview-bymore than six months afteraccepted-on. -
A deviation says what can still go wrong.
What the risk isis a required section, and it travels in the
export. The sections beside it said what limits the risk and never what remains of it. -
A deviation can name who does the work.
assigned-totakes a person or a post, and stays out of the export.
owneraccepts the risk and this field closes it, which are one person in a small estate and two in a large one. -
A rule can measure a gap in days.
days('a', 'b')counts whole days between two date fields, wherespan()
answers in hours between two timestamps.docs/design/expressions.mdis the reference. -
An explanation says what it covers.
What this coversis a required section, and it travels in the export. It
states what the record covers and what it leaves to another record, which is what keeps the residual type bounded.
kac validatereportssectionsagainst an explanation without it, andkac newsends a_template.mdcarrying
it. -
A fix says what you were running.
Environmentis a required section, and it travels in the export. It states
the tool, the operating system and the versions, which is how a reader tells whether the fix is theirs.
applies-totakes service ids alone, and a fix about a laptop or a pinned tool version has no service to name.
kac validatereportssectionsagainst a fix without it, andkac newsends a_template.mdcarrying it. -
A rule can ask whether a key is written once.
entries_unique('field', 'key')reads one key across the objects
a field holds and answers false where two of them state the same value. True where the field is absent.
docs/design/expressions.mdis the reference. -
An NFR says which quality it commits to.
characteristicis required, and takesaccuracy,availability,
capacity,latency,recovery,scalabilityorthroughput. The values sit at ISO/IEC 25010's
subcharacteristic level, so a corpus can list the qualities it has promised nothing about. It travels in the export,
indexes beside the target, andkac newsends a_template.mdnaming it. -
An NFR states the period its figure is read over.
windowtakes the period, such asmonthlyor
rolling 4 weeks.kac validaterequires it wherecharacteristicisavailability,capacity,latencyor
throughput, because 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. It travels in the export. -
An NFR says why the figure is that one.
Why this numberis a required section, and it travels in the export.
It states what fixes the figure and what the target leaves out, which the three records inexamples/paymentswere
each stating insideTarget.kac validatereportssectionsagainst an NFR without it. -
An agreed NFR says when it was agreed.
agreed-ontakes the day, quoted, andkac validaterequires it where
statusisagreed. An agreed target is a commitment somebody accepted, and nothing recorded when. It travels in
the export. -
A process says when it is rehearsed again.
rehearsal-frequencyis required, and it takes a newon-change
besideper-release,quarterlyandannual. ComplianceForge HCGF reviews a procedure when its technology, its
steps or its people change. NIST SP 800-53 Rev. 5's-1controls ask for a frequency and the events beside it.
Nothing running on a schedule can measureon-change, soprocess-lookuptells a reader to ask what has moved.
kac newsends a_template.mdcarrying the field. A corpus already holding a process writes a value into every
one of them, becausekac updatereaches the schema and never a record. -
A process says how to back out.
If it goes wrongis a required section, where it was optional. The type page
already promised a rollback, and the section stays out of the export, because a reader who has to back out is
holding the record.kac newsends a_template.mdnaming it. -
A runbook says who is affected.
Impactis a required section, and it travels in the export besideSymptoms.
The Google SRE workbook asks a playbook to explain the severity and the impact of the alert it answers, and
severitysaid only how urgent.kac newsends a_template.mdnaming it. -
A runbook says who to tell.
Communicationis a required section. AWS Well-Architected OPS07-BP04 puts
stakeholders and a communication plan on a playbook, and PagerDuty asks a responder for status updates throughout.
Escalationsays who to wake, and this says who is waiting. The section stays out of the export, because a reader
telling anybody is holding the record.kac newsends a_template.mdnaming it. -
A runbook lists its tools apart from its permissions.
requires-toolstakes what the reader installs. AWS
Well-Architected OPS07-BP03 gives a runbook a column for each, and two of the three runbooks inexamples/dog-fooding
were writing a tool intorequires-access. It travels in the export, andkac newsends a_template.mdnaming it. -
A service says what sort of component it is.
component-typeis required, and takes its range from the corpus as
platformdoes. Backstage, OpsLevel and Cortex each require this word of a catalogue entry. It travels in the export,
and a corpus adoptingserviceswritesenums.component-typein.corpus.yamlbefore its first record validates. -
A tool entry names the packages it approves.
packagestakes one entry per package, each a
package URL with the version range approved for it. CycloneDX 1.6 and
SPDX 2.3 both identify a component that way, anddrift-against-manifestshad nothing to match a manifest entry
against.Spectre.ConsoleandSpectre.Console.Cliare one decision at two ranges, which the singleversions
string could not state. It travels in the export. -
A tool entry links the project it names.
homepageis required and takes anhttps://address. SPDX gives
every package a home page, and the OpenSSF guide to evaluating open source software opens by asking whether you have
the project you think you have. No entry inexamples/dog-foodinglinked its own project. -
A tool entry carries two dates.
decided-onsays when the current status was settled, andreview-bysays when
somebody checks the entry again. Both are required and both travel in the export. Every entry in
examples/dog-foodingwas writing the first into the body as prose, and nothing stated the second, so an approval
taken once governed new work for ever.review-in-datewarns oncereview-byhas passed. -
A deprecated or rejected tool says what went wrong with it.
exit-states-a-reasonwarns where## Statusis
absent, so somebody proposing the same package in two years finds the evaluation rather than repeating it. -
A tool entry may record an accessibility assessment.
Accessibilityis a declared section and travels in the
export.std-A11Yinexamples/dog-foodingrequires an assessment in the tool record of any component rendering a
governed surface, and two entries were carrying one under a heading the type did not declare, which the export
dropped. -
datarecords travel in the export..schema/data.yamldeclares anexport:block at version 1, so
kac exportwrites one file per data document andkac bundleships them with the plugin.classification,
personal-data,data-subjects,retention,regionandflows-totravel as frontmatter, andPurpose,
Entities,Where it lives,Classification,RetentionandFlowstravel whole. A service'sdata-stores
cited records no consumer could read. Every type in the taxonomy now declares a block.
Changed
-
An NFR says whether anybody is held to its target.
statustakes a fourth value,aspirational, for a figure
somebody settled that the estate is not measured against. The Google SRE workbook keeps such an objective measured
and tracked, and exempts it from the error budget policy a miss otherwise triggers;What we do about a breachis
where that exemption is written.nfrspublishes atexport.version4, because a reader that tookagreedand
draftto be the only live values would now read an aspirational target as binding. -
An NFR records what it is achieving now.
Current actualwas optional and is now required, so the reading sits
beside the target in every record. It stays out of the export, because an export has no way to say how old a
measurement has since become. -
An NFR states what a breach costs and what the response to one is, in two sections.
If it is breachedwas one
required section, and a record could answer with either half.What a breach costsandWhat we do about a breach
are both required, sorequired-sectionreports the one a record left out. The Google SRE workbook keeps an error
budget apart from the error budget policy that spends it.nfrspublishes atexport.version3, because a reader
taking the consequence out ofIf it is breachedwould now find no section under that name. -
An integration id starts
itg-, notint-.kac validaterejectsint-sendgrid, andref-resolvesreports
each citation still pointing at one.intis a reserved word in C# and in most languages a maintainer reads, and
int-also matchesconstraint-andprint-, so a search for an integration id returns mostly lines that are not
one.integrationspublishes atexport.version2, because a reader matching^int-on an exported id would now
match nothing. Rename the id in every integration record, and in every citation of it.kac generatethen rewrites
integrations/_index.md, whose heading readsIntegration Index (ITG). -
policiesstates what it takes from current practice.lineagewas measured against ComplianceForge HCGF's
policy layer, NIST SP 800-12 Rev. 1 and NIST SP 800-53 Rev. 5.alignmentsaid a policy pushes its mandatory
language down to the standard beneath it, and 206 of the 243 clauses inexamples/engineeringare MUST or
MUST NOT.alignment,divergenceandcollisionnow describe a policy that binds in its own right, and
kac generatewrites all three into every adopting corpus'sknowledge-as-code/lineage.md. -
versionson a tool is gone, and a version range sits on the package instead.packagesstates the range for
each package it approves, so a family chosen together can be pinned apart.toolspublishes atexport.version2,
because a reader that took a range out ofversionswould now find none there. The tool index listsreview-by
where it listedversions. -
Statuson a tool is optional, and says why the tool sits where it is. It was required, and carried the status
and the date the status was set, which the frontmatter already states.exit-states-a-reasonasks for it of a
deprecatedor arejectedentry, which are the two stances that owe a reader an explanation. -
toolsstates what it takes from current practice.lineagewas measured against the Thoughtworks Technology
Radar, CycloneDX 1.6, SPDX 2.3 and the OpenSSF guide to evaluating open source software.alignmentclaimed named
technologies sorted by stance, and the index sorts by category.divergenceclaimed binding version ranges, and the
field was optional, unchecked and empty on three of 13 entries. Both now describe the schema as it stands, and
divergencerecords theassessring this register does not have. -
targeton an NFR no longer carries the measurement window. The window iswindow, so a consumer reads the
figure and the period apart.nfrspublishes atexport.version2, because a reader that took the period out of
targetwould now find none there. -
requires-accesson a runbook takes a permission and no longer a tool. A tool isrequires-tools, so a reader
sees what to install apart from what somebody has to grant them.runbookspublishes atexport.version2, because
a reader that took a tool out ofrequires-accesswould now find none there. -
A runbook says how urgent it is.
severityis required, where it was optional. The Google SRE workbook asks a
playbook to explain the severity of the alert it answers, andImpactstates the other half. -
A runbook says when it is rehearsed again.
rehearsal-frequencyis required, where it was optional. No runbook
anywhere set it, so the declaredstaleness-loudrule could only ever fire on alast-rehearsedof"never".
Nothing running on a schedule can measureon-change, which the field accepts. A corpus that already has a runbook
writes a value into every one of them, becausekac updatecopies the schema and never a record. -
runbooksstates what it takes from current practice.lineagewas measured against the Google SRE book, the
Google SRE workbook's On-Call chapter and AWS Well-Architected OPS07-BP03 and BP04.alignmentnamed a statistic
and no field or section, and now names the five it is true of.divergencerecords that AWS writes a playbook to
find the cause and a runbook to resolve it, where this type is both on one page.collisionsaid the industry uses
runbook and playbook interchangeably, which is true of Google and not of AWS.kac generatewrites all three
into every adopting corpus'sknowledge-as-code/lineage.md. -
nfrsstates what it takes from current practice.lineagewas measured against ISO/IEC 25010:2023 and the
Google SRE workbook's Implementing SLOs.alignmentnames the four things the workbook asks an objective for, and
divergencenames the error budget it keeps and this type does not take.kac generatewrites both into every
adopting corpus'sknowledge-as-code/lineage.md. -
A glossary term carries the other names it answers to.
**Also:**gives a second name for the same thing, an
acronym or an abbreviation, and**Avoid:**gives a name the glossary has dropped. Both travel in the export as
alsoandavoid, so a search reaches a term by a name its heading does not carry. SKOS calls the first an
altLabeland DITAglossentrycalls it aglossAlt, and neither had anywhere to go here before. -
parts.asides:replacesparts.aside:, and takes a list. A type declares every bold label its parts may open a
block with, andexport.parts.line:addresses one aspart.aside.<Label>.part.asideon its own is gone.
Against a schema still naming either,kac validatereportsschema-unknown-keyfor the block key and
schema-dispatchfor the line source. It reportsschema-shapeagainst a label the type'sparts.asides:does not
declare. -
glossarystates what it takes from current practice.lineagewas measured against Evans, Domain-Driven
Design, SKOS and DITAglossentry.prior-artnow names all three, andalignmentanddivergencesay what the
type takes from each and where it parts from them.kac generatewrites both into every adopting corpus's
knowledge-as-code/lineage.md. -
manual-periodicis nowmanual. The value held a cadence inside a method name, wherefrequencystates the
cadence beside it.kac validatereportsenumagainst a control still carrying the old value, and a corpus
rewrites it by hand. -
classificationgrades confidentiality alone. The field takespublic,internalandconfidential.
personalandspecial-categorymove topersonal-data, because a category of data is not a grade of sensitivity.
kac validatereportsenumagainst a data document still carrying either value inclassification, and a corpus
rewrites it by hand. -
datastates what it takes from current practice.lineagewas measured against GDPR Article 30, the NIST
Privacy Framework v1.0 and ISO/IEC 27002:2022.alignmentclaimed transfers and security measures, which the type
asks for nowhere. Both now name what the type takes and where it parts from them.kac generatewrites both into
every adopting corpus'sknowledge-as-code/lineage.md. -
controlsstates what it takes from current practice.lineagewas measured against NIST SP 800-53A Rev. 5,
the OSCAL assessment models and the CIS Controls Assessment Specification.alignmentanddivergencenow name
what the type took from each and where it parts from them.kac generatewrites both into every adopting corpus's
knowledge-as-code/lineage.md. -
A deviation's
owneris a person, never a post. The field takeshuman:alex.doealone, where every other type
also admitsrole:. One individual accepts a risk and a post cannot.kac validatereportsfield-pattern
against a deviation still naming a role, andassigned-tois where a post belongs. -
deviationsstates what it takes from current practice.lineagewas measured against NIST SP 800-37 Rev. 2,
the PCI DSS v4.0 compensating controls worksheet and the FedRAMP POA&M template.alignmentclaimed a bounded
period and tracked remediation, which the type asks for nowhere. Both now name what the type takes and where it
parts from them.kac generatewrites both into every adopting corpus'sknowledge-as-code/lineage.md. -
An explanation can explain a standard, a process or an ADR.
explainstook a service or an offering alone, and
a subject is not always a deployable thing. The export'sshapeVersionfor the type moves from 1 to 2, because a
reader that resolved every id in the services or offerings folder would now be wrong. -
explanationsstates what it takes from current practice.lineagewas measured against Diátaxis, the Good
Docs Project's concept template and arc42.alignmentclaimed discursive prose and weighed alternatives, which the
type asks for nowhere. Both now name what the type takes and where it parts from them.kac generatewrites both
into every adopting corpus'sknowledge-as-code/lineage.md. -
fixesstates what it takes from current practice.lineagewas measured against the KCS v6 article, the
ServiceNow known error form and ITIL Problem Management.alignmentnames the four sections KCS asks for, and
divergencenames the workaround ITIL expects and this type does not take.kac generatewrites both into every
adopting corpus'sknowledge-as-code/lineage.md. -
verifiedsays who has checked a record, not how often. An actor is written once, and a check they make again
moves theaton the entry they have. The Open Knowledge Format keeps the list for independent checks, a human
sign-off beside a nightly process, and git already keeps when each actor checked before.kac validatereports
one-verification-per-actoragainst afixor areportnaming one actor twice, and a corpus trims each list by
hand. The trust tier reads the actors and never the count, so no tier moves. -
processesstates its lineage against EPA QA/G-6. The type declared ComplianceForge HCGF and the Diátaxis
how-to guide.prior-artadds Guidance for Preparing Standard Operating Procedures.alignmentanddivergence
state what the comparison found: the review frequency and date EPA QA/G-6 asks for, the experience a procedure does
not state, and what git andowneranswer for instead of a revision number and a signature. The row no longer
claims the rehearsal date has no precedent. Acollision:entry names what ITIL and BPMN mean by process. All
three render intoknowledge-as-code/lineage.md. -
reportsstates what it takes from current practice.lineagewas measured against the Open Knowledge Format
v0.2, SARIF 2.1.0 and NIST OSCAL Assessment Results 1.1.3.alignmentnow names the OKF keys and the actor forms
the schema declares.divergenceadds the three verification rules OKF has no equivalent for, thestatusvalues
activeandstale, and the staleness read from each source'scontent-versioninstead of OKF'sstale_after.
Both render intoknowledge-as-code/lineage.md. -
repoon a service is nowrepos, and takes a list. OpsLevel lets one component name several repositories,
and an asset surface is defined in one repository and filled from another. Each entry matches
^[a-z0-9-]+$, whererepowas held to no pattern, so a corpus spelling one asorg/nameor a URL owes a second
edit.servicespublishes atexport.version2, because a reader that took a string out ofrepowould now find
nothing there.feature-file-reporeads every entry of the list. -
servicesstates what it takes from current practice.lineagewas measured against the Backstage software
catalog, OpsLevel and Cortex.alignmentsaid the type states the APIs a component consumes, and no field does.
alignmentanddivergencenow describe the type as it stands, andkac generatewrites both into every adopting
corpus'sknowledge-as-code/lineage.md.
Fixed
meta/type.schema.jsonofferspart.citations.<Label>. The editor's copy of the line-source vocabulary never
had a pattern for it, so it markedstandards.yaml'scovers: part.citations.Coversas invalid while the build
stayed green.MetaSchemaTestsnow holds that enum to the list the exporter fills.