The 13-step request lifecycle
- Parse request body.
- Per-IP global rate limit (pre-auth).
- Authenticate (API key or JWT).
- Per-tenant rate limit.
- PII scan.
- Prompt-injection scan (parallel with 5).
- Policy resolution →
ALLOW/REDACT/BLOCK/ESCALATE. - Enforce.
- Forward to LLM (Groq, Gemini, Mistral, Ollama).
- Response compliance check.
- Write HMAC-signed, hash-chained audit row.
- Nightly Merkle anchor (S3 Object Lock).
- Deliver response with
X-AGCMS-Interaction-ID.
Multi-tenancy
Postgres row-level security partitions every table bytenant_id. The gateway
sets current_setting('app.current_tenant') on each connection. There is no
shared global query path that bypasses RLS — including the audit log.
The audit chain
Each row’s HMAC-SHA256 signature is computed over(payload || previous_log_hash),
and the row’s previous_log_hash equals the prior row’s signature. Per-tenant
sequence numbers are assigned via a Postgres advisory lock so rows are
contiguous within a tenant. Every night a per-tenant Merkle tree is built over
the day’s signatures; the root is signed with a separate anchor key and pushed
to an S3 Object-Lock bucket in Compliance mode (default 7-year retention).
Why this design wins compliance reviews
- Truncation, reordering, or row substitution breaks the chain.
- Substituting a Merkle root requires bypassing S3 Object Lock.
- The bundle exporter ships a self-contained
verify.py— auditors never need AGCMS credentials to validate integrity.