"""AUDIT-WP-0018-T02. The bounded executor as a registered sender, on fixtures. The envelopes below follow net-kingdom ``bounded-executor/executor.py`` (``Run._event`` / ``Run._receipt``, commit a020758) key for key. Values are synthetic. The registry is built the way production builds it: a Secret-shaped ``AUDIT_CORE_SENDERS`` entry (here deliberately minted with the defaults) plus the Git-declared scope overlay in ``deploy/senders-scope.json``, so these tests also prove that the overlay alone yields the declared posture. Canonical receipt schema validation is AUDIT-WP-0014-T02 and waits on NetKingdom's versioned schema (NK-WP-0040-T02); nothing here validates the receipt beyond the envelope and the secret-shaped-field scan. """ import copy import io import json from pathlib import Path import pytest from audit_core.ingestion import IngestionApplication from audit_core.senders import SenderRegistry from audit_core.sqlite_backend import SQLiteAuditBackend ROOT = Path(__file__).resolve().parents[1] SCOPE_FILE = ROOT / "deploy" / "senders-scope.json" TOKEN = "fixture-only-executor" RUN_ID = "3f0c2a8e-0000-4000-8000-000000000001" ADMISSION = "bea-pilot-0001" def started_event(): return { "id": f"run:{RUN_ID}:started", "type": "execution.run.started", "correlation_id": RUN_ID, "subject": f"admission:{ADMISSION}", "source": "net-kingdom.bounded-executor", "tenant": "platform", "occurred_at": "2026-10-31T10:00:05+00:00", "data": { "run_id": RUN_ID, "admission": ADMISSION, "approval": "apr-0001", "consumed_at": "2026-10-31T10:00:04Z", "executing_workload": "service:nk-bind-executor", }, } def receipt_event(): return { "id": f"run:{RUN_ID}:receipt", "type": "execution.attribution.receipt", "correlation_id": RUN_ID, "subject": f"admission:{ADMISSION}", "source": "net-kingdom.bounded-executor", "tenant": "platform", "occurred_at": "2026-10-31T10:03:00+00:00", "data": { "run_id": RUN_ID, "initiator": {"sub": "approver-subject-1", "role": "approver"}, "executing_workload": "service:nk-bind-executor", "runtime_principal": "system:serviceaccount:sso:nk-bind-executor", "tenant": "platform", "environment": "railiance01", "source_commit": "a020758", "artifact_digest": "sha256:" + "a" * 64, "target": f"admission:{ADMISSION}", "action": "bounded-execution", "decision_refs": [ {"label": "admission", "ref": ADMISSION}, {"label": "admission_digest", "ref": "sha256:" + "b" * 64}, {"label": "approval", "ref": "apr-0001"}, ], "pdp": "not-evaluated", "time_interval": { "start": "2026-10-31T10:00:04Z", "end": "2026-10-31T10:03:00Z", "clock_source": "system-utc", }, "outcome": "completed", "reverted": False, "attempts": 1, "budget": { "limit": {"wall_time_seconds": 600, "attempts": 1}, "used": {"wall_time_seconds": 176.2, "attempts": 1}, }, "steps": [ { "id": "s1", "kind": "step", "operation": "rollout-restart", "target": "deployment/authelia", "consumer": "sso", "outcome": "done", "checks": [{"id": "c1", "result": "pass"}], }, ], }, } def registry(): # Minted with the defaults on purpose (redact, attributive, wildcard # source/tenant): the Git overlay must narrow and tighten it on its own. secret = json.dumps([ {"name": "nk-bounded-executor", "tokens": [TOKEN], "sources": ["*"], "tenants": ["*"]}, {"name": "operator", "tokens": ["operator"], "sources": ["*"], "tenants": ["*"], "may_write": False, "may_read": True}, ]) return SenderRegistry.from_env({ "AUDIT_CORE_SENDERS": secret, "AUDIT_CORE_SENDERS_SCOPE_PATH": str(SCOPE_FILE), }) @pytest.fixture def app(tmp_path): return IngestionApplication(SQLiteAuditBackend(str(tmp_path / "executor.db")), registry()) def post(app, event, *, token=TOKEN): raw = json.dumps(event).encode() environ = { "PATH_INFO": "/v1/events", "REQUEST_METHOD": "POST", "CONTENT_LENGTH": str(len(raw)), "wsgi.input": io.BytesIO(raw), "HTTP_AUTHORIZATION": f"Bearer {token}", # The executor sets Idempotency-Key = envelope id (clients.AuditCore.emit). "HTTP_IDEMPOTENCY_KEY": event["id"], } result = {} out = b"".join(app(environ, lambda status, headers: result.update(status=status))) return int(result["status"].split()[0]), (json.loads(out) if out else {}) # --- registration ----------------------------------------------------------- def test_scope_entry_is_exact_write_only_reject_load_bearing(): entry = next(e for e in json.loads(SCOPE_FILE.read_text()) if e["name"] == "nk-bounded-executor") assert entry == { "name": "nk-bounded-executor", "sources": ["net-kingdom.bounded-executor"], "tenants": ["platform"], "may_write": True, "may_read": False, "secret_policy": "reject", "evidence_kind": "load-bearing", } def test_overlay_narrows_a_default_minted_secret_entry(): identity = registry().authenticate(f"Bearer {TOKEN}") assert identity.name == "nk-bounded-executor" assert identity.sources == frozenset({"net-kingdom.bounded-executor"}) assert identity.tenants == frozenset({"platform"}) assert identity.may_write and not identity.may_read assert identity.secret_policy == "reject" assert identity.is_load_bearing assert identity.completeness_trade is None def test_scope_entry_admits_nothing_without_a_token(): """Safe to land ahead of the founder-run seed.""" reg = SenderRegistry.from_env({ "AUDIT_CORE_SENDERS": json.dumps( [{"name": "user-engine", "tokens": ["live"], "sources": ["user-engine"]}] ), "AUDIT_CORE_SENDERS_SCOPE_PATH": str(SCOPE_FILE), }) assert [i.name for i in reg.identities] == ["user-engine"] def test_overlay_may_not_relax_reject_to_redact(): with pytest.raises(ValueError, match="may not relax"): SenderRegistry.from_env({ "AUDIT_CORE_SENDERS": json.dumps([{ "name": "nk-bounded-executor", "tokens": ["t"], "sources": ["net-kingdom.bounded-executor"], "secret_policy": "reject", }]), "AUDIT_CORE_SENDERS_SCOPE": json.dumps( [{"name": "nk-bounded-executor", "secret_policy": "redact"}] ), }) def test_overlay_rejects_an_unknown_secret_policy(): with pytest.raises(ValueError, match="secret_policy must be one of"): SenderRegistry.from_env({ "AUDIT_CORE_SENDERS": json.dumps([{"name": "x", "tokens": ["t"], "sources": ["x"]}]), "AUDIT_CORE_SENDERS_SCOPE": json.dumps([{"name": "x", "secret_policy": "ignore"}]), }) # --- ingest behaviour on the executor's real envelope shape ----------------- @pytest.mark.parametrize("make", [started_event, receipt_event]) def test_accept_is_202(app, make): status, body = post(app, make()) assert status == 202 assert body["status"] == "accepted" @pytest.mark.parametrize("make", [started_event, receipt_event]) def test_retry_is_a_200_duplicate(app, make): assert post(app, make())[0] == 202 status, body = post(app, make()) assert status == 200 assert body["status"] == "duplicate" def test_started_and_receipt_share_the_run_correlation(app): assert post(app, started_event())[0] == 202 assert post(app, receipt_event())[0] == 202 def test_reused_run_id_with_a_different_body_is_a_409(app): assert post(app, receipt_event())[0] == 202 other = receipt_event() other["data"]["outcome"] = "reverted" other["data"]["reverted"] = True status, body = post(app, other) assert status == 409 assert body["error"] == "event_id_conflict" @pytest.mark.parametrize("source", [ "net-kingdom", "bounded-executor", "net-kingdom.bounded-executor ", "approval-engine", ]) def test_wrong_source_is_refused(app, source): event = receipt_event() event["source"] = source status, body = post(app, event) assert status == 400 assert body["error"] == "source_not_allowed" @pytest.mark.parametrize("tenant", [ "tenant:platform", "Platform", "platform ", "tenant:friendly:binky", "*", ]) def test_wrong_tenant_is_refused(app, tenant): event = receipt_event() event["tenant"] = tenant status, body = post(app, event) assert status == 400 assert body["error"] == "tenant_not_allowed" @pytest.mark.parametrize("field", ["token", "password", "client_secret", "private_key"]) def test_secret_shaped_step_check_is_refused_with_400(app, field): event = receipt_event() event["data"]["steps"][0]["checks"][0][field] = "synthetic-not-a-secret" status, body = post(app, event) assert status == 400 assert body["error"] == "secret_shaped_field" # Not stored: the clean receipt for the same run is still accepted afterwards. assert post(app, receipt_event())[0] == 202 def test_the_real_receipt_shape_carries_no_secret_shaped_key(app): """If the executor ever adds such a key, its receipts start bouncing; this pins that the current shape passes the reject policy unmodified.""" from audit_core.redaction import scan assert scan(started_event()["data"]) == [] assert scan(receipt_event()["data"]) == []