Governance
Governance is in the query path, not bolted on top. Every read runs through a Cedar-inspired ABAC engine, every write is recorded in a tamper-evident audit hash chain, and classified types are blocked at egress regardless of query success.
Policy evaluation
The policy layer (relata-acl) is a Cedar-inspired attribute-based access-control engine (not the open-source cedar-policy crate — policy semantics are Relata’s own).
| Property | Behaviour |
|---|---|
| Decision rule | Deny-wins — any matching deny rule overrides all allow rules |
| Row filtering | Bitmap row filtering (branch-predicted bitset, ~1.0× raw-scan overhead) |
| Conditional ACL | ~1.32× raw-scan p50 |
| Cell masking | CellFilter::apply_to_row — ~2.6× raw-scan p50 (allocate per-row copy); avoid on hot scan paths |
| Organisation isolation | Planner guard + agency_id keying in store/scan.rs (#220) |
| Multi-tenant | tenant= on every request → X-Organization-Id header |
Purpose tracking
Every query may declare a purpose token registered in the tenant’s PurposeRegistry. When declared, it is recorded in the audit log; enforcement lives in ACL + organisation isolation (ADR-125, ADR-132).
# Strict mode (default in production)
RELATA_PURPOSE_MODE=strict
RELATA_PURPOSES=analytics,audit,compliance,product_research
# Open mode (dev/test only)
RELATA_PURPOSE_MODE=openHierarchical scoping with : separator is supported (analytics:external).
Egress filtering (ADR-057)
Classified types are blocked at egress regardless of query success — they never appear in tool results, query rows, or protocol-door responses:
| Type | What it represents |
|---|---|
SourceTrueIdentity | HUMINT protected true identity (SPECS §5.19) |
SigintIntercept | Signal intelligence intercept records |
AccessScopedIntercept | Restricted access-scoped data (SPECS §5.20) |
LawfulInterceptRecord | Lawful intercept records |
GDPR Art. 17 erasure
ERASE SUBJECT 'person-42' CERTIFY 'governed-tombstone';- Shreds rows + orphaned blobs.
- Destroys the per-subject Data Encryption Key (KMS-wired, fail-closed).
- Returns a signed Art. 17 receipt.
- With no KMS configured it succeeds in
certified_by: "governed-tombstone"mode (#827).
Also reachable as the MCP tool erase_subject or via IdentityClient.erase_subject(...) in the SDK.
Audit hash chain
Every write is recorded in the append-only audit log with principal, timestamp, purpose, cost units, and a tamper-evident hash chain. Verification:
relata doctor # checks chain validity + node health
curl http://localhost:9090/audit/count
# → { "entries": 1248, "chain_valid": true }The Python SDK exposes typed helpers:
from relata import RelataClient, AuditClient
with RelataClient(url, bearer_token=token, purpose="compliance_review") as client:
audit = AuditClient.from_client(client)
print(audit.entries(filter={"purpose": "analytics"})) # paginated
print(audit.signed_receipt(exhibit_id="..."))Governance typed client
The Python SDK’s GovernanceClient wraps the full REST surface:
from relata import RelataClient, GovernanceClient
with RelataClient(url, bearer_token=token, purpose="compliance") as client:
gov = GovernanceClient.from_client(client)
gov.place_legal_hold(case_id="case-7", reason="litigation hold")
gov.set_worm_policy(object_type="AuditEvent", retention_days=2555) # 7 years
gov.import_sigma(open("sigma/rules.yml").read())
gov.request_breakglass(reason="emergency access", approver="ciso")| Surface | Method |
|---|---|
| Rules | list_rules, create_rule, disable_rule, import_sigma |
| Retention | list_retention_policies, list_legal_holds, place_legal_hold, lift_legal_hold |
| WORM | list_worm_policies, set_worm_policy |
| Breakglass | request_breakglass, approve_breakglass, breakglass_status |
| Alerts | list_alerts, update_alert |
| DSAR | submit_dsar |
See also
- Provenance — PROV-O lineage on every row
- Bi-Temporal Model — full history on every write
- SQL Reference —
EXPLAIN POLICY,ERASE SUBJECT