Closed (fixed)
Project:
MCP Sentinel
Version:
2.3.0
Component:
Code
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Reporter:
Created:
13 Aug 2026 at 14:52 UTC
Updated:
29 Aug 2026 at 05:15 UTC
Jump to comment: Most recent
High-assurance governed actions require durable evidence. Treating logging as best-effort permits a mutation to succeed without the decision/execution record needed to prove or reconcile it.
Define an evidence-required assurance class and make the governed action fail closed when the required evidence precommit or durable commit cannot be completed. Consume Audit Chain through a versioned evidence contract without transferring product ownership.
digest, decision, target, and request identifiers.
uncertain state; it never reports an unproven success.
Governed action results gain explicit evidence-required failure and uncertain-execution states.
Comments
Comment #2
jmcerdaPublic working mirror: GitHub #110.
Drupal.org remains the authority for this work item; implementation discussion and pull-request linkage may occur in the mirror.
Comment #3
jmcerdaImplemented; working PR on the public mirror: https://github.com/Wilkes-Liberty/mcp_sentinel/pull/132 (TDD; every acceptance criterion has a both-directions kernel test).
What it does:
- Policy profiles gain evidence_required_actions (opt-in, empty by default; entity_write, entity_delete; update 10020 backfills empty on existing profiles so an upgrade changes no behavior and exported configuration round-trips without drift).
- Veto before mutation: a new evidence guard refuses an evidence-required governed action — with a rollback-surviving evidence_veto row and stable reason codes evidence_chain_missing / evidence_audit_disabled / evidence_unkeyed — whenever the keyed chain cannot take the evidence. No fallback to unkeyed integrity or best-effort logging satisfies the class. The signing key is re-checked after the append, so signing that degrades mid-request aborts the transaction; the residual race and its complete fix (a strict keyed-append + signing-status API on audit_chain) are filed upstream.
- Atomic co-commit: the evidence_precommit row (correlation id, principal, validated OAuth consumer client id, caller X-Request-Id, policy digest, decision, target) is appended inside the mutation's own transaction — both become durable together or neither does. Proven in both directions: an evidence-store outage or append timeout aborts the save; a save that fails after its precommit takes the precommit down with it, leaving no orphaned evidence. This is a deliberate, documented reading of "durable precommit": there is no reachable state where the mutation persists without its evidence, which is the invariant the criterion exists for.
- Receipts and explicit uncertainty: the post-save entity_save / entity_delete row completes the correlation (via logAlways, so a mid-flight audit_enabled flip cannot silently drop a receipt). A receipt that fails once the mutation is already durable is recorded once per correlation id in a reconciliation ledger, refused to the caller as evidence_uncertain — never reported as a proven success — retried on cron, appended marked reconciled on recovery, and surfaced as a status-report error that stays visible even with governance disabled.
Scope, stated rather than implied: the gate covers governed content-entity mutations (create/update/delete; bulk and workflow tools flow through entity save and are covered transitively). The config-write plane has its own governance seam and gets its evidence-required leg as a separate slice. Failure states surface as stable reason codes in the refusal message on every channel; a structured code field on Tool results is a candidate follow-up rather than part of this change.
Gates: 447 kernel / 92 unit / 57 submodule tests green, module PHPCS exit 0, PHPStan clean. Moving to Needs review.
Comment #5
jmcerdaMerged to 1.x (merge f740375, working PR #132 on the public mirror). The review round adopted two automated-review findings before merge: refusal rows for the audit-disabled veto now write through the always path (a refusal suppressed by the very flag it reports on would be best-effort logging by another name), and the uncertain-receipt ledger moved to per-correlation key-value entries so concurrent failures cannot overwrite each other. Final coverage: 11 kernel tests, both-directions proofs; full matrix green including the Drupal 10.6 leg.
Ships in the next release; the upstream contract improvement that removes the guard's remaining check-then-append window (a strict keyed-append / signing-status API on audit_chain) is tracked separately. Marking Fixed.