net-kingdom/canon/schemas/execution-attribution-receipt_v0.1.schema.json
tegwick d7133e3a04 NK-WP-0056-T15: receipt schema v0.1, validator and executor fixtures; audit sender exercise
- canon/schemas/execution-attribution-receipt_v0.1.schema.json: the bounded-executor profile
  of the PCC v0.2 receipt, both audit-core events (started, receipt), every object closed.
- tools/execution-attribution-receipt: EAR-1..EAR-10 validator, fixtures generated from the
  real executor (completed, reverted, completed-on-retry) with a drift check.
- executor: started carries receipt_version, digests, steps_planned and data.window.not_after
  (audit-core AUDIT-WP-0018-T03 request); receipt carries receipt_version and initiator.iss
  (configured approver_issuer, else unknown).
- bounded-executor/exercise_audit_sender.py: real executor and client against audit-core's
  real ingestion and the Git scope overlay: 202, duplicate 200, conflict 409 as a defect,
  wrong source/tenant/token refused and not stored, a receipt-less start flagged by its own
  window.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 523928@bnt-lap001
Assistant-Session: 6c737afb-9c14-4152-9f02-477214b9c350
2026-11-04 01:39:57 +01:00

152 lines
7.8 KiB
JSON

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://netkingdom.io/schemas/execution-attribution-receipt_v0.1.schema.json",
"title": "NetKingdom Execution Attribution Receipt v0.1 (bounded-executor profile)",
"description": "The two audit-core events of one bounded-executor run: execution.run.started and execution.attribution.receipt, in audit-core's eight-field ingest envelope (audit-core docs/event-envelope.md, docs/bounded-executor-receipts.md). Fields follow Playbook Capability Contract v0.2 'Execution Attribution Receipt' and BEA v0.1 section 6. Structure only; the cross-field rules (EAR-1..EAR-10) are in tools/execution-attribution-receipt/validate.py. Values handled by operations never appear: steps carry identifiers, outcomes, check results and error types only.",
"oneOf": [
{"$ref": "#/$defs/started_event"},
{"$ref": "#/$defs/receipt_event"}
],
"$defs": {
"run_id": {"type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"},
"digest": {"type": "string", "pattern": "^sha256:[0-9a-f]{64}$"},
"admission_id": {"type": "string", "pattern": "^BEA-[0-9]{4}-[0-9]{4}$"},
"time": {"type": "string", "format": "date-time", "pattern": "(Z|[+-][0-9]{2}:[0-9]{2})$"},
"identifier": {"type": "string", "minLength": 1, "maxLength": 200, "pattern": "^[A-Za-z0-9][A-Za-z0-9:._/@=,+-]*$"},
"envelope": {
"type": "object",
"required": ["id", "type", "correlation_id", "subject", "source", "tenant", "occurred_at", "data"],
"properties": {
"id": {"type": "string", "pattern": "^run:[0-9a-f-]{36}:(started|receipt)$"},
"correlation_id": {"$ref": "#/$defs/run_id"},
"subject": {"type": "string", "pattern": "^admission:BEA-[0-9]{4}-[0-9]{4}$"},
"source": {"const": "net-kingdom.bounded-executor"},
"tenant": {"$ref": "#/$defs/identifier"},
"occurred_at": {"$ref": "#/$defs/time"}
}
},
"started_event": {
"allOf": [{"$ref": "#/$defs/envelope"}],
"type": "object",
"additionalProperties": false,
"properties": {
"id": true, "correlation_id": true, "subject": true, "source": true, "tenant": true, "occurred_at": true,
"type": {"const": "execution.run.started"},
"data": {
"type": "object",
"additionalProperties": false,
"required": ["receipt_version", "run_id", "admission", "admission_digest", "plan_digest", "approval",
"consumed_at", "executing_workload", "runtime_principal", "steps_planned", "window"],
"properties": {
"receipt_version": {"const": "0.1"},
"run_id": {"$ref": "#/$defs/run_id"},
"admission": {"$ref": "#/$defs/admission_id"},
"admission_digest": {"$ref": "#/$defs/digest"},
"plan_digest": {"$ref": "#/$defs/digest"},
"approval": {"$ref": "#/$defs/identifier"},
"consumed_at": {"anyOf": [{"$ref": "#/$defs/time"}, {"type": "null"}]},
"executing_workload": {"$ref": "#/$defs/identifier"},
"runtime_principal": {"$ref": "#/$defs/identifier"},
"steps_planned": {"type": "integer", "minimum": 1},
"window": {
"type": "object", "additionalProperties": false, "required": ["not_after"],
"properties": {"not_after": {"$ref": "#/$defs/time"}}
}
}
}
}
},
"check_result": {
"type": "object", "additionalProperties": false, "required": ["id", "result"],
"properties": {
"id": {"$ref": "#/$defs/identifier"},
"result": {"enum": ["pass", "fail", "budget"]}
}
},
"step": {
"type": "object",
"additionalProperties": false,
"required": ["id", "kind", "operation", "target", "consumer", "outcome", "checks"],
"properties": {
"id": {"$ref": "#/$defs/identifier"},
"kind": {"enum": ["step", "revert"]},
"operation": {"$ref": "#/$defs/identifier"},
"target": {"$ref": "#/$defs/identifier"},
"consumer": {"$ref": "#/$defs/identifier"},
"outcome": {"enum": ["done", "check_failed", "failed", "unknown", "error"]},
"checks": {"type": "array", "items": {"$ref": "#/$defs/check_result"}},
"error_type": {"type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,79}$"}
}
},
"decision_ref": {
"type": "object", "additionalProperties": false, "required": ["label", "ref"],
"properties": {
"label": {"enum": ["admission", "admission_digest", "approval"]},
"ref": {"$ref": "#/$defs/identifier"}
}
},
"budget_values": {
"type": "object", "additionalProperties": false, "required": ["wall_time_seconds", "attempts"],
"properties": {
"wall_time_seconds": {"type": "number", "minimum": 0},
"attempts": {"type": "integer", "minimum": 0}
}
},
"receipt_event": {
"allOf": [{"$ref": "#/$defs/envelope"}],
"type": "object",
"additionalProperties": false,
"properties": {
"id": true, "correlation_id": true, "subject": true, "source": true, "tenant": true, "occurred_at": true,
"type": {"const": "execution.attribution.receipt"},
"data": {
"type": "object",
"additionalProperties": false,
"required": ["receipt_version", "run_id", "initiator", "executing_workload", "runtime_principal", "tenant",
"environment", "source_commit", "artifact_digest", "target", "action", "decision_refs", "pdp",
"time_interval", "outcome", "reverted", "attempts", "budget", "steps"],
"properties": {
"receipt_version": {"const": "0.1"},
"run_id": {"$ref": "#/$defs/run_id"},
"initiator": {
"type": "object", "additionalProperties": false, "required": ["iss", "sub", "role"],
"properties": {
"iss": {"anyOf": [{"const": "unknown"}, {"type": "string", "pattern": "^https://[^\\s]+$"}]},
"sub": {"$ref": "#/$defs/identifier"},
"role": {"const": "approver"}
}
},
"delegation": {"$ref": "#/$defs/identifier"},
"executing_workload": {"$ref": "#/$defs/identifier"},
"runtime_principal": {"$ref": "#/$defs/identifier"},
"tenant": {"$ref": "#/$defs/identifier"},
"environment": {"$ref": "#/$defs/identifier"},
"source_commit": {"type": "string", "pattern": "^[0-9a-f]{7,40}$"},
"artifact_digest": {"$ref": "#/$defs/digest"},
"target": {"type": "string", "pattern": "^admission:BEA-[0-9]{4}-[0-9]{4}$"},
"action": {"const": "bounded-execution"},
"decision_refs": {"type": "array", "minItems": 3, "maxItems": 3, "items": {"$ref": "#/$defs/decision_ref"}},
"pdp": {"enum": ["not-evaluated", "allow"]},
"time_interval": {
"type": "object", "additionalProperties": false, "required": ["start", "end", "clock_source"],
"properties": {
"start": {"$ref": "#/$defs/time"},
"end": {"$ref": "#/$defs/time"},
"clock_source": {"$ref": "#/$defs/identifier"},
"bound": {"type": "number", "exclusiveMinimum": 0}
}
},
"outcome": {"enum": ["completed", "reverted", "revert_failed", "stopped", "unknown", "budget"]},
"reverted": {"type": "boolean"},
"attempts": {"type": "integer", "minimum": 1},
"budget": {
"type": "object", "additionalProperties": false, "required": ["limit", "used"],
"properties": {"limit": {"$ref": "#/$defs/budget_values"}, "used": {"$ref": "#/$defs/budget_values"}}
},
"steps": {"type": "array", "items": {"$ref": "#/$defs/step"}}
}
}
}
}
}
}