{"id":50454092,"url":"https://github.com/mizcausevic-dev/audit-stream-py","last_synced_at":"2026-06-01T01:05:38.573Z","repository":{"id":358183708,"uuid":"1239341532","full_name":"mizcausevic-dev/audit-stream-py","owner":"mizcausevic-dev","description":"Append-only governance event stream for the Kinetic Gain portfolio. Hash-chained for tamper-evidence, SSE for live tailing, REST for queries. Every portfolio repo is a producer.","archived":false,"fork":false,"pushed_at":"2026-05-16T05:02:53.000Z","size":21,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-16T06:45:22.941Z","etag":null,"topics":["audit-log","event-stream","fastapi","governance","hash-chain","kinetic-gain","python","sse","tamper-evident"],"latest_commit_sha":null,"homepage":"https://kineticgain.com/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mizcausevic-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-15T02:09:44.000Z","updated_at":"2026-05-16T05:02:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mizcausevic-dev/audit-stream-py","commit_stats":null,"previous_names":["mizcausevic-dev/audit-stream-py"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/mizcausevic-dev/audit-stream-py","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizcausevic-dev%2Faudit-stream-py","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizcausevic-dev%2Faudit-stream-py/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizcausevic-dev%2Faudit-stream-py/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizcausevic-dev%2Faudit-stream-py/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mizcausevic-dev","download_url":"https://codeload.github.com/mizcausevic-dev/audit-stream-py/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mizcausevic-dev%2Faudit-stream-py/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33755379,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audit-log","event-stream","fastapi","governance","hash-chain","kinetic-gain","python","sse","tamper-evident"],"created_at":"2026-06-01T01:05:38.481Z","updated_at":"2026-06-01T01:05:38.558Z","avatar_url":"https://github.com/mizcausevic-dev.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# audit-stream\n\n[![CI](https://github.com/mizcausevic-dev/audit-stream-py/actions/workflows/ci.yml/badge.svg)](https://github.com/mizcausevic-dev/audit-stream-py/actions/workflows/ci.yml)\n[![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n**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.\n\n```text\n                                       ┌─────────────────────┐\n                                       │     audit-stream    │\n                                       │                     │\n   procurement-decision-api ──events──▶│   POST /events      │\n   policy-as-code-engine    ──events──▶│   GET  /events?…    │\n   data-contract-registry   ──events──▶│   GET  /stream  ◀──── live tail (SSE)\n   aeo-validator-service    ──events──▶│   GET  /verify       │\n   incident-correlation-rs  ──events──▶│   GET  /stats        │\n   hash-attestation-rs      ──events──▶│                     │\n   feature-flag-rs          ──events──▶│ chain: prev_hash ──▶ hash  ──▶ next.prev_hash ──▶ …\n   request-shadow-rs        ──events──▶│                     │\n                                       └─────────────────────┘\n```\n\n---\n\n## Why\n\nAcross 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.\n\n`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.\n\n---\n\n## Endpoints\n\n| Method | Path | What it does |\n| --- | --- | --- |\n| GET | `/` | Service info + endpoint list. |\n| GET | `/healthz` | Liveness probe. |\n| POST | `/events` | Append one governance event. Returns the assigned `event_id`, `prev_hash`, and `hash`. |\n| GET | `/events?kind=\u0026source=\u0026limit=` | Query. Filters by `kind` or `source`; `limit` caps the most-recent N events. |\n| GET | `/events/{id}` | Fetch one event by id. |\n| GET | `/stream` | Live tail via Server-Sent Events. Receives events appended **after** subscription. |\n| GET | `/verify` | Walk the entire chain and report the first integrity break, if any. |\n| GET | `/stats` | `{ count, last_event_id, latest_hash }`. |\n\n---\n\n## Event envelope\n\n```json\n{\n  \"event_id\": 42,\n  \"timestamp\": \"2026-05-15T03:14:15+00:00\",\n  \"kind\": \"watch_drifted\",\n  \"source\": \"aeo-validator-service\",\n  \"payload\": { \"watch_id\": \"abc123\", \"added_fields\": [\"claims\"] },\n  \"prev_hash\": \"9a3f…\",\n  \"hash\":      \"b7d1…\"\n}\n```\n\n`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.\n\n---\n\n## Event kinds (v0.1)\n\n| Source repo | Kinds |\n| --- | --- |\n| `procurement-decision-api` | `decision_card_drafted`, `decision_card_signed`, `decision_card_status_changed` |\n| `policy-as-code-engine` | `policy_bundle_registered`, `request_allowed`, `request_denied` |\n| `data-contract-registry` | `contract_promoted`, `contract_deprecated`, `contract_compatibility_failed` |\n| `aeo-validator-service` | `watch_created`, `watch_drifted`, `watch_validity_flipped` |\n| `incident-correlation-rs` | `incident_filed`, `remediation_planned` |\n| `hash-attestation-rs` | `attestation_verified`, `attestation_tampered` |\n| `feature-flag-rs` / `request-shadow-rs` | `flag_swapped`, `shadow_divergence_recorded` |\n| `mcp-permission-broker` | `tool_invocation_allowed`, `tool_invocation_denied`, `tool_invocation_required_approval` |\n| extension | `other` |\n\nAdding kinds is a Literal-only change; producers and verifiers stay backwards-compatible if you keep the canonical-hash construction stable.\n\n---\n\n## Tamper-evidence\n\n`/verify` rewalks the chain top-to-bottom and reports:\n\n```json\n{\n  \"valid\": false,\n  \"checked\": 5,\n  \"first_break_at\": 6,\n  \"reason\": \"hash mismatch at event #6\"\n}\n```\n\nOperators 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.\n\n---\n\n## Live tail\n\n`GET /stream` is a Server-Sent Events endpoint. Each event the store appends becomes one SSE message:\n\n```\nevent: watch_drifted\nid: 42\ndata: {\"event_id\":42,\"timestamp\":\"2026-05-15T03:14:15+00:00\", …}\n```\n\nTail 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).\n\n---\n\n## Quick start\n\n```bash\npip install audit-stream\naudit-stream            # binds 0.0.0.0:8093\n\n# in another shell\ncurl -X POST http://localhost:8093/events \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"kind\":\"decision_card_drafted\",\"source\":\"procurement-decision-api\",\"payload\":{\"decision_id\":\"DEC-001\"}}'\n```\n\n---\n\n## Composes with\n\n- **[procurement-decision-api](https://github.com/mizcausevic-dev/procurement-decision-api)** · **[policy-as-code-engine](https://github.com/mizcausevic-dev/policy-as-code-engine)** · **[data-contract-registry](https://github.com/mizcausevic-dev/data-contract-registry)** · **[aeo-validator-service](https://github.com/mizcausevic-dev/aeo-validator-service)** · **[incident-correlation-rs](https://github.com/mizcausevic-dev/incident-correlation-rs)** · **[hash-attestation-rs](https://github.com/mizcausevic-dev/hash-attestation-rs)** · **[feature-flag-rs](https://github.com/mizcausevic-dev/feature-flag-rs)** · **[request-shadow-rs](https://github.com/mizcausevic-dev/request-shadow-rs)** — any of these can `POST /events` to produce a record of their own governance moments.\n\n---\n\n## Tests\n\n```bash\npip install -e \".[dev]\"\nruff check src tests \u0026\u0026 ruff format --check src tests\nmypy src\npytest -v\n```\n\nCI matrix runs Python 3.11 / 3.12 / 3.13.\n\n---\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmizcausevic-dev%2Faudit-stream-py","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmizcausevic-dev%2Faudit-stream-py","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmizcausevic-dev%2Faudit-stream-py/lists"}