mirror of
https://github.com/ruvnet/RuView
synced 2026-08-11 20:41:44 +00:00
139 lines
7.7 KiB
Markdown
139 lines
7.7 KiB
Markdown
# ADR-318: Capability certificates — validated-for-this-environment claims
|
||
|
||
- **Status**: Accepted — initial implementation planned (ADR-300 phase 1)
|
||
- **Date**: 2026-08-11
|
||
- **Deciders**: ruv
|
||
- **Tags**: capability, certificate, evidence, provenance, signature, honesty, substrate
|
||
|
||
## Context
|
||
|
||
This ADR is primitive 18 of the perception-substrate program (ADR-300) and,
|
||
per the strategic assessment, among the strongest ideas in the program: it is
|
||
where the whole certificate spine becomes a consumable contract. In the ADR-300
|
||
dependency DAG it **consumes the evidence engine (ADR-304)** — a capability
|
||
certificate is a signed attestation minted over a slice of that ledger — the
|
||
**calibration certificate (ADR-301)** for the environment it is validated
|
||
against, and the **RuField signature types (ADR-305 / ADR-260/262/277/279)** to
|
||
sign it. It reports domain state via ADR-302 and is anchored in the witness
|
||
chain (ADR-319).
|
||
|
||
RuView must stop making unconditional capability claims. "Supports presence" is
|
||
not a true statement — presence detection works in some rooms, on some hardware,
|
||
for some subject dynamics, and fails on a stationary subject at range in an
|
||
uncalibrated room. A capability is only ever *validated for a specific
|
||
environment*, and the honest unit of that claim is a signed, expiring
|
||
certificate, not a feature flag in a README.
|
||
|
||
The ingredients now exist across the phase-1 spine: ADR-304 accumulates
|
||
per-`(room, device, subject)` accuracy, false-positive rate, drift, and domain
|
||
state; ADR-301 produces the signed room fingerprint the environment is keyed to;
|
||
ADR-305 provides the authenticated device identity and `CapabilityAttestation`
|
||
(BFLD, ADR-141) that bounds *what a device is even attested to sense*; ADR-282
|
||
provides the mandatory `EvidenceLevel`. What is missing is the artifact that
|
||
binds them into a single, verifiable "validated here, until then" claim and the
|
||
consumer-side rule that refuses capabilities lacking one.
|
||
|
||
## Options considered
|
||
|
||
1. **Static capability flags / a `supports_presence` boolean.** Rejected: it is
|
||
the exact dishonest claim — environment-independent, unsigned, non-expiring,
|
||
and false the moment the room, device, or subject dynamics differ.
|
||
2. **Report raw ledger accuracy to consumers directly.** Rejected: the ledger
|
||
(ADR-304) is the source of truth but not a portable, signed, bounded contract;
|
||
handing consumers raw records pushes evidence-weighting and expiry logic into
|
||
every consumer and drops the single verifiable object.
|
||
3. **Mint a signed, expiring `CapabilityCertificate` over an ADR-304 ledger
|
||
slice, and make consumers refuse capabilities without a valid one.** Chosen.
|
||
|
||
## Decision
|
||
|
||
Introduce a signed **`CapabilityCertificate`**: a bounded attestation that a
|
||
specific capability has been validated for a specific environment, for a bounded
|
||
time.
|
||
|
||
### 1. The certificate
|
||
|
||
A serializable `CapabilityCertificate` binding:
|
||
|
||
- `capability` — the phenomenon (e.g. `presence`, `pose`), which must be within
|
||
the device's ADR-305/ADR-141 `CapabilityAttestation` (a device cannot be
|
||
certified for something it is not even attested to sense).
|
||
- `room` — the ADR-306 space identifier, tied to the ADR-301 calibration
|
||
certificate version the validation was performed against.
|
||
- `hardware` — the ADR-305 authenticated `DeviceId` (and, in phase 2, the
|
||
ADR-320 HAL descriptor of the sensor).
|
||
- `model` — the model version scored.
|
||
- `calibrated_date` — the calibration certificate age at validation time.
|
||
- `moving_recall`, `stationary_recall`, `false_presence_per_24h` — the measured
|
||
operating metrics, sliced from the ADR-304 ledger for this exact context (not
|
||
a global average), each honestly labelled. These are per-capability; a pose
|
||
certificate carries pose metrics with the mean-pose baseline and a
|
||
leakage-free split (CLAUDE.md) or it is not issued.
|
||
- `valid_until` — an explicit expiry; a certificate is never open-ended.
|
||
- `evidence_level` — exactly one L0–L5 (ADR-282). A certificate minted from a
|
||
synthetic ledger slice is L0/`Synthetic`; a MEASURED metric requires an
|
||
ADR-303 reference and a reproducer. The certificate cannot upgrade the level
|
||
of the ledger it is minted from (ADR-304 honesty rule).
|
||
- `signature` — a RuField `SignatureBlock` (ADR-305 / ADR-260/262/277/279) over
|
||
the canonical serialization; an unsigned certificate is not a valid
|
||
certificate. The certificate is anchored in the witness chain (ADR-319).
|
||
|
||
### 2. Minting
|
||
|
||
- A certificate is minted from a slice of the ADR-304 evidence ledger for one
|
||
`(room, device, subject-class, model)` context. If the ledger reports "no
|
||
evidence" for that context, **no certificate is issued** — absence of evidence
|
||
is never a capability. Minting is a pure function over the append-only ledger
|
||
at mint time; the metrics are frozen into the signed object.
|
||
- Expiry (`valid_until`) is derived from calibration validity (ADR-301) and an
|
||
evidence-freshness policy: a certificate cannot outlive the calibration it was
|
||
validated against, and drift beyond the ADR-301 envelope invalidates both.
|
||
|
||
### 3. Consumer refusal rule
|
||
|
||
- Applications and surfaces **refuse to consume a capability that lacks a valid
|
||
certificate for the current environment**. "Valid" means: signature verifies,
|
||
`room`/`hardware`/`model` match the running context, `valid_until` is in the
|
||
future, and the referenced calibration certificate is itself still valid
|
||
(ADR-301 not invalidated). A failed check yields UNKNOWN via ADR-302, not a
|
||
best-effort guess.
|
||
- This makes the ADR-300 acceptance clause "quantify whether it can reliably
|
||
sense the requested phenomenon → generate a signed capability certificate"
|
||
a hard gate rather than a hope.
|
||
|
||
## Consequences
|
||
|
||
- RuView can no longer claim a capability it has not validated for the caller's
|
||
environment; the honest failure — "not certified here" → UNKNOWN — is
|
||
surfaced by construction rather than by discipline.
|
||
- OEM/integrator diligence gets a single verifiable artifact ("presence,
|
||
validated in *this* room, on *this* device, with *these* recall/false-alarm
|
||
numbers, until *this* date, at *this* evidence level, signed") — the strongest
|
||
commercial output of the spine.
|
||
- Certificates expire and get refused; some environments will have no
|
||
certificate and therefore no capability until validated. That refusal is the
|
||
intended honest behavior, not a regression.
|
||
- Key management and expiry policy are operational responsibilities, reusing the
|
||
ADR-305 enrollment/rotation and ADR-301 validity machinery rather than new
|
||
infrastructure; fleet distribution of certificates is owned by ADR-316.
|
||
- No capability number is invented here; every metric on a certificate is sliced
|
||
from the ADR-304 ledger at its honest evidence level.
|
||
|
||
## Validation
|
||
|
||
- `cargo test` on the certificate crate — mint from a ledger slice produces the
|
||
frozen metrics; "no evidence" context yields no certificate; signature
|
||
round-trip and tamper rejection; `valid_until` and calibration-linked expiry
|
||
enforced; consumer refusal on room/hardware/model mismatch, expiry, or
|
||
invalidated calibration resolves to UNKNOWN (ADR-302), not a guess; evidence
|
||
level is inherited from the ledger and cannot be upgraded; a certificate
|
||
cannot be issued for a capability outside the device's ADR-305/ADR-141
|
||
attestation.
|
||
- Cross-ADR: an ADR-304 ledger fixture mints a certificate; an ADR-302 test
|
||
asserts an expired/mismatched certificate gates to UNKNOWN; the ADR-300
|
||
acceptance test consumes a minted certificate end-to-end.
|
||
- Real-deployment certificates (minted from a populated ledger with ADR-303
|
||
references on live ESP32 captures) are the maturity milestone and require
|
||
hardware evidence per CLAUDE.md; a certificate minted from a synthetic ledger
|
||
is L0 by construction.
|