Append-only governance event stream for the Kinetic Gain portfolio. Hash-chained for tamper-evidence, Server-Sent Events for live tailing, REST for queries. The cross-cutting telemetry layer every other portfolio repo can produce into.
┌─────────────────────┐
│ audit-stream │
│ │
procurement-decision-api ──events──▶│ POST /events │
policy-as-code-engine ──events──▶│ GET /events?… │
data-contract-registry ──events──▶│ GET /stream ◀──── live tail (SSE)
aeo-validator-service ──events──▶│ GET /verify │
incident-correlation-rs ──events──▶│ GET /stats │
hash-attestation-rs ──events──▶│ │
feature-flag-rs ──events──▶│ chain: prev_hash ──▶ hash ──▶ next.prev_hash ──▶ …
request-shadow-rs ──events──▶│ │
└─────────────────────┘
Across the portfolio, "something governance-shaped happened" is the recurring event: a Decision Card was drafted, a policy bundle denied a request, a data contract was promoted, a watch detected drift, an attestation failed. Each repo already logs these — but to its own logs, in its own shape, with its own retention.
audit-stream is the shared event spine. One schema, one chain, one SSE socket, one REST query interface. Operators see the whole portfolio's behavior in a single place; auditors get a tamper-evident record by construction.
| Method | Path | What it does |
|---|---|---|
| GET | / |
Service info + endpoint list. |
| GET | /healthz |
Liveness probe. |
| POST | /events |
Append one governance event. Returns the assigned event_id, prev_hash, and hash. |
| GET | /events?kind=&source=&limit= |
Query. Filters by kind or source; limit caps the most-recent N events. |
| GET | /events/{id} |
Fetch one event by id. |
| GET | /stream |
Live tail via Server-Sent Events. Receives events appended after subscription. |
| GET | /verify |
Walk the entire chain and report the first integrity break, if any. |
| GET | /stats |
{ count, last_event_id, latest_hash }. |
{
"event_id": 42,
"timestamp": "2026-05-15T03:14:15+00:00",
"kind": "watch_drifted",
"source": "aeo-validator-service",
"payload": { "watch_id": "abc123", "added_fields": ["claims"] },
"prev_hash": "9a3f…",
"hash": "b7d1…"
}event_id is monotonic; the store assigns it. prev_hash is the previous event's hash (or 64 zeros for event #1). hash is SHA-256 over the canonical JSON of every other field — sorted keys, no whitespace.
| Source repo | Kinds |
|---|---|
procurement-decision-api |
decision_card_drafted, decision_card_signed, decision_card_status_changed |
policy-as-code-engine |
policy_bundle_registered, request_allowed, request_denied |
data-contract-registry |
contract_promoted, contract_deprecated, contract_compatibility_failed |
aeo-validator-service |
watch_created, watch_drifted, watch_validity_flipped |
incident-correlation-rs |
incident_filed, remediation_planned |
hash-attestation-rs |
attestation_verified, attestation_tampered |
feature-flag-rs / request-shadow-rs |
flag_swapped, shadow_divergence_recorded |
mcp-permission-broker |
tool_invocation_allowed, tool_invocation_denied, tool_invocation_required_approval |
| extension | other |
Adding kinds is a Literal-only change; producers and verifiers stay backwards-compatible if you keep the canonical-hash construction stable.
/verify rewalks the chain top-to-bottom and reports:
{
"valid": false,
"checked": 5,
"first_break_at": 6,
"reason": "hash mismatch at event #6"
}Operators can wire a periodic verify into their on-call alerting; a valid: false result is one of the most useful red lights a governance stack can produce.
GET /stream is a Server-Sent Events endpoint. Each event the store appends becomes one SSE message:
event: watch_drifted
id: 42
data: {"event_id":42,"timestamp":"2026-05-15T03:14:15+00:00", …}
Tail it with curl -N http://localhost:8093/stream, or wire it into a dashboard (e.g. a EventSource in browser JS, or httpx-sse in Python).
pip install audit-stream
audit-stream # binds 0.0.0.0:8093
# in another shell
curl -X POST http://localhost:8093/events \
-H 'Content-Type: application/json' \
-d '{"kind":"decision_card_drafted","source":"procurement-decision-api","payload":{"decision_id":"DEC-001"}}'- procurement-decision-api · policy-as-code-engine · data-contract-registry · aeo-validator-service · incident-correlation-rs · hash-attestation-rs · feature-flag-rs · request-shadow-rs — any of these can
POST /eventsto produce a record of their own governance moments.
pip install -e ".[dev]"
ruff check src tests && ruff format --check src tests
mypy src
pytest -vCI matrix runs Python 3.11 / 3.12 / 3.13.
MIT. See LICENSE.