NK-WP-0056-T11 done: bounded executor core runner
Consumes one admission once through the approval-engine carrier after an effect-free preflight (validity, source pins, trust, window vs budget, binding digest, actor, human aal2 approvers), emits run.started, runs steps with settle-timed checks, reverts on failure with per-revert checks, retries within attempts, stops on unknown outcomes, honours budget and kill switch, and emits one value-free receipt (PDP not-evaluated). 22 tests with fakes. BEA-9 extended to revert steps; examples regenerated. 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:
parent
3b1abc4054
commit
d1cf754222
14 changed files with 834 additions and 23 deletions
372
bounded-executor/tests/test_executor.py
Normal file
372
bounded-executor/tests/test_executor.py
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
"""Core runner tests (NK-WP-0056-T11). Fakes only: carrier, operations, checks, trust, audit, clocks."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import datetime as dt
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
HERE = pathlib.Path(__file__).resolve().parent
|
||||
spec = importlib.util.spec_from_file_location("executor", HERE.parent / "executor.py")
|
||||
X = importlib.util.module_from_spec(spec)
|
||||
sys.modules["executor"] = X # dataclasses resolve deferred annotations through sys.modules
|
||||
spec.loader.exec_module(X)
|
||||
bea = X.bea
|
||||
|
||||
PILOT = bea.load(X.REPO / "examples/bounded-execution-admission/bind-rotation-svc-authelia.yaml")
|
||||
ADMIN_SUB = "kc-sub-0f3a" # opaque KeyCape subject of the human approver `admin`
|
||||
NOW = dt.datetime(2026, 11, 3, 9, 30, tzinfo=dt.UTC)
|
||||
SECRET = "synthetic-bind-value-never-emitted"
|
||||
|
||||
|
||||
class Clock:
|
||||
def __init__(self):
|
||||
self.t = 0.0
|
||||
self.sleeps = []
|
||||
|
||||
def monotonic(self):
|
||||
return self.t
|
||||
|
||||
def sleep(self, s):
|
||||
self.sleeps.append(s)
|
||||
self.t += s
|
||||
|
||||
|
||||
class FakeCarrier:
|
||||
"""approval-engine's object and consume semantics (store.Approval.as_dict, Engine.consume)."""
|
||||
|
||||
def __init__(self, admission, **over):
|
||||
self.approval = {
|
||||
"id": "apr-1", "status": "approved",
|
||||
"binding": {"action": "bounded-execution", "actor": admission["spec"]["executor"]["identity"],
|
||||
"principal": "admin", "purpose": admission["spec"]["purpose"],
|
||||
"target": {"admission_id": admission["spec"]["id"],
|
||||
"admission_digest": bea.admission_digest(admission)},
|
||||
"human_control": True, "pdp_path": False},
|
||||
"validity": {"not_before": admission["spec"]["window"]["not_before"],
|
||||
"expires_at": admission["spec"]["window"]["not_after"]},
|
||||
"entries": [{"subject_id": ADMIN_SUB, "assurance": "aal2", "principal_type": "human",
|
||||
"approved_at": "2026-11-03T08:55:00Z"}],
|
||||
}
|
||||
for k, v in over.items():
|
||||
self.approval[k] = v
|
||||
self.consumes = 0
|
||||
self.raise_on_consume = False
|
||||
self.consume_lands = True
|
||||
|
||||
def get(self, approval_id):
|
||||
return copy.deepcopy(self.approval)
|
||||
|
||||
def consume(self, approval_id, request_digest, decision_id):
|
||||
self.consumes += 1
|
||||
if self.consume_lands:
|
||||
if self.approval["status"] == "consumed":
|
||||
same = self.approval["consumption"]["request_digest"] == request_digest
|
||||
if not same:
|
||||
raise RuntimeError("409")
|
||||
return {"approval_id": approval_id, "status": "consumed", "request_digest": request_digest,
|
||||
"decision_id": self.approval["consumption"].get("decision_id"),
|
||||
"consumed_at": "x", "idempotent": True}
|
||||
self.approval["status"] = "consumed"
|
||||
self.approval["consumption"] = {"request_digest": request_digest, "decision_id": decision_id,
|
||||
"consumed_at": "2026-11-03T09:30:00Z"}
|
||||
if self.raise_on_consume:
|
||||
raise TimeoutError("connection reset")
|
||||
return {"approval_id": approval_id, "status": "consumed", "request_digest": request_digest,
|
||||
"decision_id": decision_id, "consumed_at": "2026-11-03T09:30:00Z", "idempotent": False}
|
||||
|
||||
|
||||
class World:
|
||||
def __init__(self, admission, clock):
|
||||
self.calls = []
|
||||
self.fail_check = {} # check id -> number of times to fail
|
||||
self.raise_op = set() # operation names that raise
|
||||
self.unknown_op = set()
|
||||
self.slow_op = 0.0
|
||||
self.events = []
|
||||
self.alerts = []
|
||||
self.audit_down = False
|
||||
self.stop_after = None
|
||||
self.clock = clock
|
||||
self.carrier = FakeCarrier(admission)
|
||||
self.trust_ok = True
|
||||
|
||||
def op(self, step, ctx):
|
||||
if step["operation"] in self.unknown_op:
|
||||
raise X.Unknown()
|
||||
if step["id"] in self.raise_op:
|
||||
raise RuntimeError("boom")
|
||||
ctx.data["value"] = SECRET # operations may hold values; the runner must never emit them
|
||||
self.calls.append(step["id"])
|
||||
self.clock.t += self.slow_op
|
||||
|
||||
def check(self, check, ctx):
|
||||
self.calls.append("check:" + check["id"])
|
||||
left = self.fail_check.get(check["id"], 0)
|
||||
if left:
|
||||
self.fail_check[check["id"]] = left - 1
|
||||
return False
|
||||
return True
|
||||
|
||||
def emit(self, event):
|
||||
if self.audit_down:
|
||||
raise ConnectionError()
|
||||
self.events.append(event)
|
||||
|
||||
def should_stop(self):
|
||||
return self.stop_after is not None and len([c for c in self.calls if not c.startswith("check:")]) >= self.stop_after
|
||||
|
||||
def deps(self, admission):
|
||||
ops = {s["operation"]: self.op for s in admission["spec"]["plan"]["steps"] + admission["spec"]["plan"]["revert_steps"]}
|
||||
checks = {c["id"]: self.check for c in admission["spec"]["checks"]}
|
||||
audit = type("A", (), {"emit": lambda _s, e: self.emit(e)})()
|
||||
return X.Deps(carrier=self.carrier, operations=ops, checks=checks, trust=lambda s: self.trust_ok,
|
||||
audit=audit, alert=lambda kind, info: self.alerts.append(kind),
|
||||
should_stop=self.should_stop, wall=lambda: NOW,
|
||||
monotonic=self.clock.monotonic, sleep=self.clock.sleep)
|
||||
|
||||
|
||||
def synthetic_admission(root: pathlib.Path, mutate=None) -> dict:
|
||||
"""The pilot example, with its pinned files replaced by temporary ones and the digest recomputed."""
|
||||
doc = copy.deepcopy(PILOT)
|
||||
files = []
|
||||
for f in doc["spec"]["plan"]["source"]["files"]:
|
||||
path = root / f["path"]
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text("synthetic " + f["path"])
|
||||
files.append({"path": f["path"], "sha256": hashlib.sha256(path.read_bytes()).hexdigest()})
|
||||
doc["spec"]["plan"]["source"]["files"] = files
|
||||
by_path = {f["path"]: f["sha256"] for f in files}
|
||||
for c in doc["spec"]["checks"]:
|
||||
c["sha256"] = by_path[c["ref"]]
|
||||
if mutate:
|
||||
mutate(doc["spec"])
|
||||
doc["spec"]["plan_digest"] = bea.plan_digest(doc)
|
||||
return doc
|
||||
|
||||
|
||||
class Base(unittest.TestCase):
|
||||
mutate = None
|
||||
|
||||
def setUp(self):
|
||||
tmp = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(tmp.cleanup)
|
||||
self.root = pathlib.Path(tmp.name)
|
||||
self.doc = synthetic_admission(self.root, self.mutate)
|
||||
self.clock = Clock()
|
||||
self.w = World(self.doc, self.clock)
|
||||
self.cfg = X.Config(executor_identity="service:nk-bind-executor",
|
||||
runtime_principal="system:serviceaccount:sso:nk-bind-executor",
|
||||
tenant="tenant:platform", environment="PRODUCTION",
|
||||
approver_subjects={"admin": ADMIN_SUB}, source_root=self.root)
|
||||
|
||||
def run_it(self, doc=None):
|
||||
doc = doc or self.doc
|
||||
return X.Run(doc, "apr-1", self.cfg, self.w.deps(doc)).execute()
|
||||
|
||||
def ops(self):
|
||||
return [c for c in self.w.calls if not c.startswith("check:")]
|
||||
|
||||
def assert_no_effect(self, result, reason):
|
||||
self.assertEqual((result["outcome"], result["reason"]), ("refused", reason))
|
||||
self.assertEqual(self.w.carrier.consumes, 0)
|
||||
self.assertEqual(self.w.calls, [])
|
||||
self.assertEqual(self.w.events, [])
|
||||
|
||||
|
||||
class HappyPathTests(Base):
|
||||
def test_completes_with_started_and_receipt(self):
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["outcome"], "completed", result)
|
||||
self.assertEqual(self.w.carrier.consumes, 1)
|
||||
self.assertEqual(self.ops(), ["generate", "set-directory", "deliver", "restart"])
|
||||
self.assertEqual([e["type"] for e in self.w.events], [X.STARTED, X.RECEIPT])
|
||||
started, receipt = self.w.events
|
||||
self.assertEqual(started["id"], f"run:{result['run_id']}:started")
|
||||
data = receipt["data"]
|
||||
self.assertEqual(data["pdp"], "not-evaluated")
|
||||
self.assertEqual({r["label"] for r in data["decision_refs"]}, {"admission", "admission_digest", "approval"})
|
||||
self.assertEqual(data["initiator"]["sub"], ADMIN_SUB)
|
||||
self.assertEqual(data["artifact_digest"], self.doc["spec"]["plan_digest"])
|
||||
self.assertFalse(data["reverted"])
|
||||
self.assertNotIn(SECRET, json.dumps(self.w.events))
|
||||
|
||||
def test_consumed_with_admission_digest_and_run_id(self):
|
||||
result = self.run_it()
|
||||
consumption = self.w.carrier.approval["consumption"]
|
||||
self.assertEqual(consumption["request_digest"], bea.admission_digest(self.doc))
|
||||
self.assertEqual(consumption["decision_id"], result["run_id"])
|
||||
|
||||
|
||||
class RefusalTests(Base):
|
||||
def test_invalid_admission(self):
|
||||
doc = copy.deepcopy(self.doc)
|
||||
doc["spec"]["plan"]["steps"][0]["operation"] = "tampered"
|
||||
self.w = World(doc, self.clock)
|
||||
self.assertEqual(self.run_it(doc)["reason"], "admission_invalid:BEA-2")
|
||||
self.assertEqual(self.w.carrier.consumes, 0)
|
||||
|
||||
def test_refusals_before_any_effect(self):
|
||||
cases = {
|
||||
"not_this_executor": lambda: setattr(self.cfg, "executor_identity", "service:other"),
|
||||
"source_drift": lambda: (self.root / "tools/service-binds/bind-lane.py").write_text("changed"),
|
||||
"trust_not_satisfied:runtime_secret_trust": lambda: setattr(self.w, "trust_ok", False),
|
||||
"approval_binding": lambda: self.w.carrier.approval["binding"]["target"].update(admission_digest="sha256:" + "0" * 64),
|
||||
"approval_status": lambda: self.w.carrier.approval.update(status="requested"),
|
||||
"approval_entry": lambda: self.w.carrier.approval["entries"][0].update(assurance="aal1"),
|
||||
"approval_expires_before_window_end": lambda: self.w.carrier.approval["validity"].update(expires_at="2026-11-03T10:00:00Z"),
|
||||
}
|
||||
for reason, mutate in cases.items():
|
||||
with self.subTest(reason=reason):
|
||||
self.setUp()
|
||||
mutate()
|
||||
self.assert_no_effect(self.run_it(), reason)
|
||||
|
||||
def test_approval_by_someone_not_listed_or_not_human(self):
|
||||
for entry in ({"subject_id": "kc-sub-other", "assurance": "aal2", "principal_type": "human"},
|
||||
{"subject_id": ADMIN_SUB, "assurance": "aal2", "principal_type": "service"}):
|
||||
with self.subTest(entry=entry):
|
||||
self.setUp()
|
||||
self.w.carrier.approval["entries"] = [entry]
|
||||
self.assert_no_effect(self.run_it(), "approval_entry")
|
||||
|
||||
def test_actor_must_be_this_executor(self):
|
||||
self.w.carrier.approval["binding"]["actor"] = "service:someone-else"
|
||||
self.assert_no_effect(self.run_it(), "approval_binding")
|
||||
|
||||
def test_outside_window(self):
|
||||
self.w.deps = (lambda orig: (lambda doc: (lambda d: (setattr(d, "wall", lambda: NOW + dt.timedelta(hours=3)), d)[1])(orig(doc))))(self.w.deps)
|
||||
self.assert_no_effect(self.run_it(), "outside_window")
|
||||
|
||||
def test_window_too_short_for_the_budget(self):
|
||||
late = dt.datetime(2026, 11, 3, 10, 50, tzinfo=dt.UTC) # 10 min left, budget 20 min
|
||||
orig = self.w.deps
|
||||
self.w.deps = lambda doc: (lambda d: (setattr(d, "wall", lambda: late), d)[1])(orig(doc))
|
||||
self.assert_no_effect(self.run_it(), "window_shorter_than_budget")
|
||||
|
||||
def test_already_consumed_is_never_reused(self):
|
||||
self.w.carrier.approval["status"] = "consumed"
|
||||
self.w.carrier.approval["consumption"] = {"request_digest": bea.admission_digest(self.doc), "decision_id": "earlier-run"}
|
||||
self.assert_no_effect(self.run_it(), "approval_status")
|
||||
|
||||
def test_unknown_operation(self):
|
||||
d = self.w.deps(self.doc)
|
||||
d.operations.pop("eso.force-sync")
|
||||
result = X.Run(self.doc, "apr-1", self.cfg, d).execute()
|
||||
self.assert_no_effect(result, "unknown_operation")
|
||||
|
||||
|
||||
class ConsumeTests(Base):
|
||||
def test_unclear_consume_resolved_by_reading_back(self):
|
||||
self.w.carrier.raise_on_consume = True # consume landed, response lost
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["outcome"], "completed")
|
||||
self.assertEqual(self.w.carrier.consumes, 1) # never consumed twice
|
||||
|
||||
def test_unclear_consume_that_did_not_land_stops(self):
|
||||
self.w.carrier.raise_on_consume = True
|
||||
self.w.carrier.consume_lands = False
|
||||
result = self.run_it()
|
||||
self.assertEqual((result["outcome"], result["reason"]), ("refused", "consume_not_confirmed"))
|
||||
self.assertEqual((self.w.calls, self.w.events), ([], []))
|
||||
self.assertIn("consume_unconfirmed", self.w.alerts)
|
||||
|
||||
def test_idempotent_consume_is_not_a_fresh_run(self):
|
||||
original = self.w.carrier.consume
|
||||
self.w.carrier.consume = lambda a, d, r: dict(original(a, d, r), idempotent=True)
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["reason"], "consume_response")
|
||||
self.assertEqual(self.w.calls, [])
|
||||
|
||||
def test_no_custody_no_run(self):
|
||||
self.w.audit_down = True
|
||||
result = self.run_it()
|
||||
self.assertEqual((result["outcome"], result["reason"]), ("stopped", "audit_unavailable"))
|
||||
self.assertEqual(self.w.calls, [])
|
||||
self.assertIn("started_not_in_custody", self.w.alerts)
|
||||
|
||||
|
||||
class FailureTests(Base):
|
||||
def test_failed_check_reverts_in_reverse_and_verifies(self):
|
||||
self.doc = synthetic_admission(self.root, lambda s: s["budget"].update(attempts=1))
|
||||
self.w = World(self.doc, self.clock)
|
||||
self.w.fail_check["eso-synced"] = 1
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["outcome"], "reverted", result)
|
||||
self.assertEqual(self.ops(), ["generate", "set-directory", "deliver", "redeliver", "restore-directory", "restore-kv"])
|
||||
data = result["receipt"]["data"]
|
||||
self.assertTrue(data["reverted"])
|
||||
reverts = [x for x in data["steps"] if x["kind"] == "revert"]
|
||||
self.assertEqual([x["checks"][0]["id"] for x in reverts], ["eso-synced", "bind-signs-in", "kv-advanced"])
|
||||
self.assertTrue(all(x["outcome"] == "done" for x in reverts))
|
||||
self.assertEqual(data["attempts"], 1)
|
||||
|
||||
def test_clean_revert_may_retry_within_attempts(self):
|
||||
self.doc = synthetic_admission(self.root, lambda s: s["budget"].update(attempts=2))
|
||||
self.w = World(self.doc, self.clock)
|
||||
self.w.fail_check["synthetic-journey"] = 1
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["outcome"], "completed")
|
||||
self.assertEqual(result["receipt"]["data"]["attempts"], 2)
|
||||
self.assertTrue(result["receipt"]["data"]["reverted"])
|
||||
|
||||
def test_revert_whose_check_fails_counts_as_failed(self):
|
||||
self.doc = synthetic_admission(self.root, lambda s: s["budget"].update(attempts=1))
|
||||
self.w = World(self.doc, self.clock)
|
||||
self.w.fail_check["eso-synced"] = 2 # the forward check and the revert's own check
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["outcome"], "revert_failed")
|
||||
self.assertNotIn("restore-directory", self.ops())
|
||||
|
||||
def test_failed_revert_stops_and_alerts(self):
|
||||
self.w.fail_check["eso-synced"] = 1
|
||||
self.w.raise_op = {"restore-directory"}
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["outcome"], "revert_failed")
|
||||
self.assertIn("revert_failed", self.w.alerts)
|
||||
self.assertNotIn("restore-kv", self.ops()) # stop at the failed revert, do not continue blindly
|
||||
|
||||
def test_unknown_outcome_stops_without_revert(self):
|
||||
self.w.unknown_op = {"eso.force-sync"}
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["outcome"], "unknown")
|
||||
self.assertEqual(self.ops(), ["generate", "set-directory"])
|
||||
self.assertFalse(result["receipt"]["data"]["reverted"])
|
||||
self.assertIn("unknown", self.w.alerts)
|
||||
|
||||
def test_budget_exhausted_reverts(self):
|
||||
self.w.slow_op = 700.0 # wall_time_seconds is 1200
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["outcome"], "budget")
|
||||
self.assertTrue(result["receipt"]["data"]["reverted"])
|
||||
|
||||
def test_kill_switch_reverts(self):
|
||||
self.w.stop_after = 2
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["outcome"], "stopped")
|
||||
self.assertIn("restore-kv", self.ops())
|
||||
self.assertNotIn("deliver", self.ops())
|
||||
|
||||
def test_settle_time_is_waited_and_counted(self):
|
||||
self.doc = synthetic_admission(self.root, lambda s: s["checks"][3].update(settle_seconds=125))
|
||||
self.w = World(self.doc, self.clock)
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["outcome"], "completed")
|
||||
self.assertIn(125, self.clock.sleeps)
|
||||
|
||||
def test_receipt_custody_failure_is_reported(self):
|
||||
original = self.w.emit
|
||||
self.w.emit = lambda e: (original(e) if e["type"] == X.STARTED else (_ for _ in ()).throw(ConnectionError()))
|
||||
result = self.run_it()
|
||||
self.assertEqual(result["reason"], "receipt_not_in_custody")
|
||||
self.assertIn("receipt_not_in_custody", self.w.alerts)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue