SLA declarations + breach handling
An SLA in Kirimana is a property of a contract, not a spreadsheet
kept alongside it. You declare freshness and quality thresholds
inside the contract’s kiri.sla.* block, and kiri sla check
evaluates each declaration against the observed state of the
workspace. A missed threshold is a breach, and a breach is
surfaced where your team already looks — the CLI report and the
audit trail — with no separate monitoring system to wire up first.
Declaring an SLA on a contract
The SLA lives in the contract’s kiri.sla namespace. Two thresholds
can be declared, independently:
kiri:
sla:
freshness: 4h
quality_threshold: 0.99
kiri.sla.freshness is the maximum acceptable age of the latest
row. Its shape is <integer><unit>, where the unit is one of s,
m, h, d, or w — so 15m, 4h, and 1d are all valid. The
format is validated at load time, not deferred to the first apply:
a malformed value like 4hours is rejected when the contract is
read, so a typo never becomes a silent no-op in production.
kiri.sla.quality_threshold is the minimum data-quality pass-rate,
a number in the range (0.0, 1.0]. A value of 0.99 means “at
least 99% of quality checks must pass”; anything below it is a
breach. A threshold of 1.0 demands a perfect pass rate.
Omitting a field simply leaves that aspect of SLA enforcement off. A contract may declare freshness only, quality only, or both — each is evaluated on its own.
Checking SLAs
kiri sla check walks the project, evaluates every contract that
declares a kiri.sla.* block, and reports the result:
kiri sla check --target prod
By default the command filters to contracts that actually declare
an SLA, so the report is signal rather than a wall of “not
applicable” rows. To check one contract by name — including one that
declares no SLA, so you can see the skipped result explicitly —
pass --contract orders.silver. --dry-run evaluates and prints
what would happen without taking any breach action, which is what
you want the first time you wire an SLA up.
Each check resolves to one of four statuses, and the distinction matters when you read a report:
| Status | Meaning |
|---|---|
ok | The threshold was measured and met. |
breach | The threshold was measured and missed. |
skipped | No threshold declared for this aspect — nothing to evaluate. |
unmeasured | The threshold applies but the observed signal isn’t wired through yet — a real answer is owed, distinct from “passed”. |
The unmeasured status is deliberately not folded into “ok”: it
tells you the SLA is declared but the signal feeding it isn’t
flowing, so you don’t mistake an unwired check for a healthy one.
Freshness is evaluated against the platform manifest that a prior
apply stamps; if no apply has stamped the slot yet, the freshness
check reports skipped with a clear message rather than a false
breach.
Exit codes
kiri sla check is built to gate a CI job or a scheduled run:
0— no breaches; every check wasokorskipped.1— at least one breach detected.2— the project failed to load.
A 1 is your signal to page, open a ticket, or fail the pipeline —
whatever your team’s escalation is. Run it on a schedule against
prod and a non-zero exit is your breach alarm.
Where breaches surface today
When a check breaches, the outcome lands in two places. It is
reported in the CLI — the kiri sla check output names the
contract, the kind of breach (freshness or quality), the declared
threshold, and the observed value that missed it. And it is
recorded in the audit trail: an SLA breach is an audited event
of the form sla:<contract>:<kind> — for example
sla:orders:freshness — so a breach is a first-class entry you can
find after the fact, not just a line that scrolled past in a
terminal.
That combination — a non-zero exit code plus an audited breach event — is the supported way to surface SLA breaches in v1.0.0-beta.1. It is enough to drive a scheduled check, gate a promotion, and answer “what breached, and when?” from the audit record.
Dispatching a breach
Incident dispatch to an external ITSM ships: kiri incident dispatch opens or updates a ticket in Jira, ServiceNow, or Zendesk,
keyed on a stable dedup id (e.g. sla:orders:freshness) so a
recurring breach updates one ticket rather than spawning many. Apply
failures route through the incident router automatically; for an SLA
breach you dispatch explicitly from the check result (or drive
escalation from the check’s exit code in CI). Either way the ticket
carries the trace links — apply id, contract, target env, git SHA —
a regulator or an on-call engineer needs. Wiring an SLA check to
auto-open a ticket with no manual step is the remaining convenience;
the dispatch itself is here today.