Pure Python Integration Guide¶
This guide walks through a complete Aevum integration for a Python application.
It uses the production path (no AEVUM_DEV=1) to show what a real deployment
looks like: explicit consent grants, real provenance, and sigchain verification.
If you are just getting started, read the Quickstart first.
What we are building¶
A Python function that:
- Grants a support agent consent to read a user's ticket data
- Ingests a ticket through the governed membrane (signed, chained)
- Queries the data with consent verification
- Replays the exact state at ingest time
- Verifies the sigchain is intact
Install¶
For Cedar-based policy enforcement (recommended for production):
Complete example¶
"""
Pure Python integration — no AEVUM_DEV=1.
Demonstrates: consent grants → ingest → query → replay → verify.
"""
from aevum.core import Engine
from aevum.core.consent.models import ConsentGrant
# ── 1. Create the engine ──────────────────────────────────────────────────────
# No AEVUM_DEV=1. Engine uses InMemoryLedger (dev/demo) and attempts to load
# CedarPolicyEngine. Falls back to NullPolicyEngine with a warning if Cedar is
# not installed.
engine = Engine()
# ── 2. Grant consent ──────────────────────────────────────────────────────────
# In production: load grants from your database, not hardcoded here.
# Grant is per-subject, per-purpose, time-bounded.
engine.add_consent_grant(ConsentGrant(
grant_id="grant-alice-support-2026",
subject_id="alice",
grantee_id="support-agent",
operations=["ingest", "query"],
purpose="support-ticket-resolution",
classification_max=0,
granted_at="2026-01-01T00:00:00Z",
expires_at="2027-01-01T00:00:00Z",
))
# ── 3. Ingest — write through the governed membrane ───────────────────────────
# Every ingest call:
# - Checks Barrier 3 (consent) — fails with consent_required if not granted
# - Checks Barrier 5 (provenance) — requires source_id
# - Signs the event with Ed25519
# - Chains it with SHA3-256 (SHA3-256(prev_event_signing_fields))
result = engine.ingest(
data={"ticket": "T-001", "description": "Cannot log in to the portal"},
provenance={
"source_id": "support-portal",
"chain_of_custody": ["support-portal"],
"classification": 0,
},
purpose="support-ticket-resolution",
subject_id="alice",
actor="support-agent",
)
print("status: ", result.status) # ok
print("audit_id:", result.audit_id) # urn:aevum:audit:0196...
# ── 4. Query — read with consent verification ─────────────────────────────────
# query() checks Barrier 3 again: returns results only if consent is active.
q = engine.query(
purpose="support-ticket-resolution",
subject_ids=["alice"],
actor="support-agent",
)
print("subjects:", list(q.data["results"].keys())) # ['alice']
# ── 5. Replay — reconstruct exact past state ──────────────────────────────────
# replay() returns the exact payload from the ingested event, unchanged.
# No summarisation. No inference. Deterministic reconstruction.
r = engine.replay(audit_id=result.audit_id, actor="support-agent")
assert r.data["replayed_payload"]["ticket"] == "T-001"
print("replayed:", r.data["replayed_payload"]["description"])
# ── 6. Verify sigchain ────────────────────────────────────────────────────────
# verify_sigchain() walks every event from genesis, checking both the SHA3-256
# chain (prior_hash) and the Ed25519 signature on each event.
ok = engine.verify_sigchain()
print("chain intact:", ok) # True
Consent errors¶
Try removing the add_consent_grant() call:
# engine.add_consent_grant(...) # commented out
result = engine.ingest(...)
print(result.status) # error
print(result.data["error_code"]) # consent_required
print(result.data["error_detail"]) # No active consent grant for ...
Barrier 3 fires before any data is written. Nothing reaches the sigchain.
Provenance errors¶
Try removing source_id from provenance:
result = engine.ingest(
data={"ticket": "T-002", ...},
provenance={}, # no source_id
...
)
print(result.status) # error
print(result.data["error_code"]) # provenance_required
Barrier 5 fires. No data written.
Persistent storage (production)¶
For real deployments, replace the in-memory store:
from aevum.store.oxigraph import OxigraphStore
engine = Engine(
graph_store=OxigraphStore(path="/var/lib/aevum/graph"),
)
The sigchain persists across process restarts. The session.start event
links to the previous session's last event via causation_id.
Episode grouping¶
Group related operations into a named episode for forensic replay:
import uuid
episode = str(uuid.uuid4())
result = engine.ingest(..., episode_id=episode, ...)
q = engine.query(..., episode_id=episode, ...)
All events with the same episode_id are queryable as a unit for replay
and compliance reporting.