Files
pi-extensions/docs/adr/0006-enforce-audit-self-sufficiency.md
T

75 lines
3.6 KiB
Markdown

---
status: accepted
---
# Enforce audit self-sufficiency — no upstream host contract
PIEXTENSIO-10 (promotion governance) and PIEXTENSIO-13/15 (host contract
and enforce gates) conditioned the allow-only Enforce authority on a
formal **host contract** in upstream `@gotgenes/pi-permission-system`:
acknowledged review writes, capability versioning, pre-link enrollment,
and a LocalUserAuthorizer-only human-decision marker. We decided to drop
that dependency: every guarantee Enforce needs will be **provided by the
Judge package itself**, and the upstream stays untouched at zero changes.
## Why the original design was wrong
Not "too early" — structurally wrong. Every contract item is complexity
the upstream maintainer must carry **forever**, serving a plugin he does
not use. His own users gain nothing from it. A PR of that shape sits in
the queue forever (observed: upstream has unprocessed PRs already).
Designing our audit needs as host obligations is asking someone else to
pay for our feature.
The "self-recording is untrustworthy" argument also failed scrutiny under
the actual threat model: this Judge runs on the operator's own machine,
single-user. The Judge can be *buggy* but has no motive to *deceive*.
Bugs are covered by in-process self-checks; "independent third-party
audit" is an enterprise-multi-tenant requirement we do not have.
(The original patches were also lost with `~/Projects/.workspace/`
cleanup and were never pushed — the dependency was not just unwanted but
gone.)
## What self-sufficiency means concretely
1. **Judge-owned audit log**, separate file from the permission-system
review log (which also solves an operational pain: that log is ~850KB
of mixed events). Append + fsync per record; a failed write marks the
runtime **unhealthy**, and the Enforce truth table's telemetry gate
refuses authority while unhealthy. This is the self-implemented
version of "acknowledged writes".
2. **Human-decision attribution at the consumption side.** Real-human
decisions are distinguishable by event shape
(`approved`/`denied` from the dialog vs `session_approved`/
`auto_approved`/`infrastructure_auto_allowed`), verified against live
data in the 2026-08-17 TUI cohort (round 5 showed forwarded
`auto_approved` double-writes). The analyzer filters cohort rows on
this shape instead of the upstream marking humans.
3. **Denominator redefined** as "asks the Judge itself received"
(waiting rows in the Judge log), not upstream pre-link enrollment.
Self-consistent bookkeeping; the PIEXTENSIO-10 floor math applies to
this denominator unchanged.
4. The truth-table gate `hostContractPresent` becomes a **local
self-check gate** (audit log healthy). Mechanically identical in
effect: today's production state already defers unconditionally.
## What is explicitly not weakened
- The PIEXTENSIO-10 floor (100 qualified rows, zero false allows,
per-segment) stands, computed on the self-owned log.
- Allow-only semantics stand: the Judge never denies; every uncertain
case defers to the human dialog.
- Fail-closed stands: audit unhealthy → defer; malformed evidence →
defer; unknown state → defer.
## Consequences
- PIEXTENSIO-15 is cancelled (single-consumer upstream feature =
unmaintainable dependency). Its lessons stay here.
- If the upstream ever ships an equivalent contract on its own
initiative, the Judge may adopt it later; nothing in this design
blocks that. Revisit trigger: multi-user / multi-tenant deployments
where the "buggy-but-honest" threat model no longer holds.
- Promotion cohort identity is unaffected (model/prompt/evidence
profile); the audit-log switch is a governance-consumer change.