A local-first append-only audit ledger for the Parad0x ecosystem. Records stay immutable, exports stay deterministic, and every entry links to actors, targets, and scope (workspace/run/entity/release) metadata for easy downstream querying.
python -m venv .venv
.\.venv\Scripts\activate
pip install -e .
uvicorn audit_ledger.api.app:app --reload- The FastAPI server seeds approval, install, moderation, simulation, publication, reputation, and device events plus a retention policy when
NULL_AUDIT_LEDGER_DEMO=true; keep the variable unset for production-like runs. - The ledger writes to
data/audit_ledger.db, creates the required tables (audit_records,exports,retention_policy), and can be reset simply by deleting that file.
- API layer (
audit_ledger/api): FastAPI routes translate payloads into domain models and delegate to the services; handlers never touch SQLite directly. - Services (
audit_ledger/services):AuditAppendService,AuditQueryService,AuditExportService, andAuditRetentionServiceencapsulate append-only writes, filtered retrieval, deterministic exports, and retention window storage. - Repository (
audit_ledger/repositories/sqlite_store.py): A single SQLite implementation stores canonical JSON (model_dump+json.dumps(sort_keys=True)), enforces immutability through primary keys, and provides a deterministic export table.
| Method | Path | Description |
|---|---|---|
POST /api/audit |
Append an audit record (actor/target/category/linkage/message). | |
GET /api/audit |
List recent events (default limit 50). | |
GET /api/audit/{record_id} |
Retrieve a single immutable record. | |
POST /api/audit/query |
Filter events by scope/category/limit. | |
GET /api/audit/export/{scope_type}/{scope_id} |
Build deterministic export bundle for an entity/run/workspace/release. | |
GET /api/retention |
Read the configured retention policy (days kept). | |
POST /api/retention |
Update the local retention window (does not delete past records). |
- Append-only writes:
/api/auditonly performsINSERT; duplicate IDs fail because the SQLite schema’s PK enforces uniqueness so existing rows cannot be mutated. - Deterministic exports: Bundles sort records by
(created_at, id), so even identical timestamps resolve predictably and repeated exports for a scope yield the same JSON bytes. - Linkage clarity:
AuditLinkagestores workspace/run/entity/release scope plusrecord_ids, letting downstream consumers trace related events such as policy decisions referencing approvals. - Retention policy:
/api/retentionpersists a single row describing the window (id=1) but never purges ledger rows; enforcement is left to external tooling or future automation. - Demo gating: set
NULL_AUDIT_LEDGER_DEMO=trueonly when inspecting seeded data; leave it unset otherwise so the ledger starts empty. - Storage footprint: The ledger writes only to
data/audit_ledger.db; deleting that file resets the data.
py -3 -m pytestTests cover append/query/export/retention services, export determinism including tie-breaking, linkage persistence, restart persistence, and the append-only constraint.
- null-policy-engine can append policy decision records with provenance tags for regulatory review.
- null-event-bus can subscribe to select categories and feed them into the ledger for traceability.
- null-observatory can collect audit exports for correlation with logs/metrics.
- null-marketplace and null-device-bridge can reference ledger record IDs when generating install/approval statuses.
- null-sim-lab can use replayable audit exports to seed simulation runs with trusted event history.