Implement GH-DEC-2026-003 consume-before-OpenBao PEP gate
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Every live privileged production handler CAS-consumes through
approval-engine before OpenBao. Conflict, unavailability, or a missing
binding fail closed. Live production remains disabled until the durable
decision record is served.

Record kings-guard assent on the secret-use evidence contract.

Assistant: grok
Assistant-Session: 01a05f07-ae72-7781-9fcb-19efd61add00
This commit is contained in:
tegwick 2026-09-02 01:06:50 +02:00
parent 465c0d7049
commit 4b4d556d62
14 changed files with 724 additions and 20 deletions

View file

@ -27,6 +27,10 @@ from pathlib import Path
from secrets_engine import __version__
from secrets_engine.apply import apply_plan
from secrets_engine.approval_consume import (
require_production_consume,
resolve_consume_binding,
)
from secrets_engine.catalog import get_entry, load_catalog
from secrets_engine.config import Config, repo_root
from secrets_engine.decisions import require_approved, resolve_decision
@ -91,27 +95,35 @@ def _require_lane_approval(
action: str = "",
evidence: PrivilegedActionEvidence | None = None,
):
"""Apply published PEP stance, then resolve lane approval.
"""Apply published PEP stance, resolve lane approval, then CAS-consume.
Production ``fail_closed`` is read from ``pep-stance.yaml``. The durable
access-engine decision record is not served yet, so that row refuses live
production work. The three-factor unsafe-demo exception is not a stance
row. Build/test ``fail_open`` still requires the existing lane-approval
check a tracked gap until SECRETS-WP-0008-T02.
production work. If that residue is ever bypassed, GH-DEC-2026-003 still
requires a successful approval-engine consume before any OpenBao call.
The three-factor unsafe-demo exception is not a stance row and is not a
consume path. Build/test ``fail_open`` still requires the existing
lane-approval check a tracked gap until SECRETS-WP-0008-T02.
"""
stance = apply_unreachable_engine_stance(cfg, entry, action or "unknown")
if evidence is not None:
evidence.mark_stance(stance)
if not entry.approval_required():
return None
decision = resolve_decision(
hub_url=cfg.hub_url,
repo_root=repo_root(),
decision_ref=entry.approval.get("decision_ref", entry.id),
decision = None
if entry.approval_required():
decision = resolve_decision(
hub_url=cfg.hub_url,
repo_root=repo_root(),
decision_ref=entry.approval.get("decision_ref", entry.id),
)
require_approved(entry, decision)
if evidence is not None:
evidence.mark_stance(with_decision(stance, decision))
require_production_consume(
cfg,
entry,
binding=resolve_consume_binding(cfg, entry, action or "unknown", decision),
evidence=evidence,
)
require_approved(entry, decision)
if evidence is not None:
evidence.mark_stance(with_decision(stance, decision))
return decision