NK-WP-0056-T12 done: pilot operations; synthetic rotation and revert pass
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run

operations.py: OpenBao KV v2 CAS, LLDAP self-rotation (forward and revert),
ExternalSecret force-sync and status, rollout restart (RolloutFailed is a
definite failure), pilot checks. synthetic_pilot.py on the T08 stack plus
OpenBao 2.5.4 with CCR-2026-0058's policy: rotation completed; a one-off wrong
delivery reverted in declared order with the earlier value restored.

Runner: revert steps run in declared order (BEA-10), definite failures revert,
unknown outcomes stop, receipts carry error types. Found and corrected (in
railiance-platform) CCR-2026-0058's required_parameters refusing reads.
Packaging moved to new T13. 29 executor tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 994874@bnt-lap001
Assistant-Session: 6017c416-d619-47eb-bd1a-f670a02d7d87
This commit is contained in:
tegwick 2026-10-31 16:24:17 +01:00
parent 9b7701a32a
commit db56d8468e
11 changed files with 1088 additions and 33 deletions

View file

@ -12,9 +12,10 @@ Runs one Bounded Execution Admission (canon/standards/bounded-execution-admissio
started `execution.run.started` to the audit sink; no custody, no run
steps in plan order, one consumer at a time; checks after each mutating step, after
their settle time; the kill switch and the budget are checked between steps
failure a failed check or an exhausted budget reverts the mutated steps in reverse
order (or stops, as the admission says) and re-runs their checks; an error of
unknown outcome stops without guessing; a failed revert stops and alerts
failure a failed check, an exhausted budget or the kill switch runs the revert steps of
the mutated steps in the admission's declared order (or stops, as it says), each
proving the restored state with its own checks; an error of unknown outcome stops
without guessing; a failed revert stops and alerts
receipt one `execution.attribution.receipt` per run (PDP `not-evaluated` in the pilot)
Every effect goes through an injected interface: Carrier, operation and check callables, TrustOracle,
@ -52,6 +53,12 @@ class Unknown(Exception):
"""An operation's outcome is unknown: stop, do not guess, do not revert blindly."""
class StepFailed(Exception):
"""A definite, known-bad outcome (e.g. a rollout that never became ready): handled like a failed check.
Operations outside this module may instead set `definite_failure = True` on their exception class."""
definite_failure = True
class Carrier(Protocol):
def get(self, approval_id: str) -> dict: ...
def consume(self, approval_id: str, request_digest: str, decision_id: str) -> dict: ...
@ -203,9 +210,13 @@ class Run:
def _budget_left(self) -> float:
return self.spec["budget"]["wall_time_seconds"] - (self.d.monotonic() - self.start_mono)
def _record(self, step: dict, kind: str, outcome: str, checks: list[dict] | None = None) -> None:
self.steps.append({"id": step["id"], "kind": kind, "operation": step["operation"], "target": step["target"],
"consumer": step["consumer"], "outcome": outcome, "checks": checks or []})
def _record(self, step: dict, kind: str, outcome: str, checks: list[dict] | None = None,
error: BaseException | None = None) -> None:
entry = {"id": step["id"], "kind": kind, "operation": step["operation"], "target": step["target"],
"consumer": step["consumer"], "outcome": outcome, "checks": checks or []}
if error is not None:
entry["error_type"] = type(error).__name__ # the type only: messages can carry values
self.steps.append(entry)
def _run_checks(self, ids: list[str], ctx: Context) -> tuple[bool, list[dict]]:
results = []
@ -230,18 +241,20 @@ class Run:
return True, results
def _revert(self, done: list[dict], ctx: Context) -> bool:
"""Undo the mutated steps in reverse order; each revert step must pass its own checks."""
reverts = {s["id"]: s for s in self.spec["plan"].get("revert_steps", [])}
for step in reversed(done):
if not step["mutates"]:
"""Undo the mutated steps. Revert steps run in the order the admission declares them (the author knows
the recovery order: data before delivery before restart), limited to those whose forward step ran.
Each must pass its own checks; an irreversible step that ran makes the revert fail."""
mutated = [s for s in done if s["mutates"]]
if any(s.get("irreversible") for s in mutated):
return False
wanted = {s["revert"] for s in mutated}
for revert in self.spec["plan"].get("revert_steps", []):
if revert["id"] not in wanted:
continue
if step.get("irreversible"):
return False
revert = reverts[step["revert"]]
try:
self.d.operations[revert["operation"]](revert, ctx)
except Exception:
self._record(revert, "revert", "error")
except Exception as error:
self._record(revert, "revert", "error", error=error)
return False
ok, results = self._run_checks(revert.get("checks_after", []), ctx)
self._record(revert, "revert", "done" if ok else "check_failed", results)
@ -262,11 +275,15 @@ class Run:
return reason
try:
self.d.operations[step["operation"]](step, ctx)
except Unknown:
self._record(step, "step", "unknown")
return "unknown"
except Exception:
self._record(step, "step", "unknown")
except Exception as error:
if getattr(error, "definite_failure", False) and step["mutates"]:
# known-bad state: treat like a failed check, the step counts as done for the revert
done.append(step)
self._record(step, "step", "failed", error=error)
if policy["on_check_failure"] == "revert":
return "reverted" if self._revert(done, ctx) else "revert_failed"
return "stopped"
self._record(step, "step", "unknown", error=error) # outcome not established: stop
return "unknown"
done.append(step)
ok, results = self._run_checks(step.get("checks_after", []), ctx) if step["mutates"] else (True, [])