Audit Log & Security
Audit Log
Every action in Adjudon is recorded in a tamper-proof audit log.
The log uses SHA-256 hash chaining: each entry's hash is computed from its content plus the previous entry's hash. If any entry is modified, every subsequent hash in the chain becomes invalid — making tampering immediately detectable.
What's logged:
- Trace ingestion (input, output, policy decision)
- Policy changes (create, update, delete)
- Review decisions (approve, reject, escalate)
- User logins and auth events
- API key operations (create, rotate, delete)
- Team changes (invite, role change, remove)
- Setting changes
Verifying the chain
GET /api/v1/audit/verify
Authorization: Bearer <jwt>
Returns the integrity status of the entire chain. If any entry has been tampered with, the response identifies the first broken link.
Reading the audit log
GET /api/v1/audit
Authorization: Bearer <jwt>
Supports pagination and filtering by date range, event type, and user.
GDPR Right to Erasure
When a user requests data deletion under GDPR Article 17, Adjudon nullifies the payload (sets it to null) but preserves the audit entry shell. This keeps the hash chain intact while removing personal data.
The entry remains in the log — it shows that a decision was made, but not what the decision contained. The chain does not break.
PII Scrubbing
All trace data is scrubbed for PII before storage. Scrubbing runs at ingestion — data never reaches the database in raw form.
Patterns scrubbed by default:
| Pattern | Example |
|---|---|
| Email addresses | user@example.com → [REDACTED_EMAIL] |
| IBANs | DE89 3704 0044 0532 0130 00 → [REDACTED_IBAN] |
| Credit card numbers | 4111 1111 1111 1111 → [REDACTED_CARD] |
| Social Security Numbers | 123-45-6789 → [REDACTED_SSN] |
Custom patterns: Organizations can configure additional regex patterns to scrub domain-specific sensitive data.
PII scrubbing cannot be disabled — it is a regulatory requirement under GDPR.
Data residency
All data is stored and processed in the EU:
| Service | Location |
|---|---|
| MongoDB Atlas | Frankfurt (eu-central-1) |
| API Server (Fly.io) | Frankfurt |
| Dashboard & Docs (Cloudflare Pages) | EU edge |
| Billing (Stripe) | Ireland |
| Transactional email (Resend) | EU |
Exception: OpenAI embeddings for optional similarity search. Standard Contractual Clauses (SCCs) are in place. No customer data is returned from OpenAI — only embedding vectors.
Fail-open architecture
Adjudon is designed to never block your agent. If Adjudon is unreachable:
- The SDK returns
TraceResponse(status="passthrough")immediately - The trace is queued in memory
- The SDK retries with exponential backoff when connectivity resumes
- No trace data is lost
This means compliance infrastructure failure never causes agent downtime. Configure fail_mode="closed" only if your use case requires hard blocking on Adjudon unavailability.