--- id: security-compliance title: Secrets, Audit Logs and Compliance code: AU subtitle: Vault-backed keys, PII scrubbing, audit logs, signed webhooks, framework controls and AI law dates. hue: 140 sources: phases/17-infrastructure-and-production/25-security-secrets-audit, phases/17-infrastructure-and-production/26-compliance-frameworks, phases/18-ethics-safety-alignment/24-regulatory-frameworks-eu-us-uk-korea, projects/signed-webhook-inbox source_hash: 67e98f82b081e529 --- ## Run the labs type: task-table from: phases/17-infrastructure-and-production/25-security-secrets-audit/docs/en.md, phases/17-infrastructure-and-production/26-compliance-frameworks/docs/en.md, phases/18-ethics-safety-alignment/24-regulatory-frameworks-eu-us-uk-korea/code/main.py, projects/signed-webhook-inbox/README.md | Task | Code | |---|---| | PII scrubber and audit log, lesson 25 | `code/main.py` | | Control and profile map, lesson 26 | `code/main.py` | | AI regulation timeline, phase 18 | `python3 code/main.py` | | Webhook demo: 202, 200, 401 | `go run . --mode demo` | | Build the webhook inbox | `go build -o /tmp/webhook-inbox .` | ## Gateway pulls keys from vault type: architecture from: phases/17-infrastructure-and-production/25-security-secrets-audit/docs/en.md ```arch node | app | 1,1 | App | no provider key | client node | gw | 2,1 | AI gateway | IAM role, guardrails | process node | vault | 2,2 | Vault | OPENAI_API_KEY | store node | egress | 3,1 | Egress whitelist | allowlist-only DNS | process node | prov | 4,1 | Model provider | api.openai.com | model node | audit | 3,2 | Audit log | immutable, per call | store edge | app | gw | request edge | gw | vault | pull at request time edge | gw | egress | scrubbed prompt edge | egress | prov | allowed host only edge | gw | audit | append ``` ## Security numbers type: defaults from: phases/17-infrastructure-and-production/25-security-secrets-audit/docs/en.md, projects/signed-webhook-inbox/solution/main.go, projects/signed-webhook-inbox/README.md | Setting | Default | Note | |---|---|---| | Key rotation | ≤ 90 days | Keys, vault root tokens, CI/CD credentials | | Token lifetime | hours | Short-lived tokens, not days | | Audit retention, SOC 2 | 1 year | Retain per regulation | | Audit retention, HIPAA | 6 years | Retain per regulation | | Webhook clock skew | `5*time.Minute` | Both sides of now | | Webhook body size | 1..65536 bytes | Read before any decoding | | Webhook secret | WEBHOOK_SECRET | At least 16 bytes | | `--seconds` | 60 | Receiver lifetime, 1..600 | ## Audit log entry type: annotated-code lang: python from: phases/17-infrastructure-and-production/25-security-secrets-audit/code/main.py ```python entry = AuditEntry( timestamp=datetime.utcnow().isoformat() + "Z", user=f"user_{i:03}", tenant="tenant_01", model="anthropic/claude-3.7-sonnet", # model plus version prompt_hash=hash_short(scrubbed), # hash, not the raw prompt response_hash=hash_short(response), input_tokens=len(scrubbed.split()), output_tokens=len(response.split()), cost_usd=0.0012, guardrail_trips=[], # any guardrail trips ) print(audit_log_call(entry)) # one JSON line per call ``` ## PII scrubbing type: concepts from: phases/17-infrastructure-and-production/25-security-secrets-audit/docs/en.md, phases/17-infrastructure-and-production/25-security-secrets-audit/code/main.py, phases/17-infrastructure-and-production/26-compliance-frameworks/docs/en.md - **Order**: entity recognition, mask, consistent tokenization, optional reverse mapping. - **Lab patterns**: `SSN`, `EMAIL` and `PHONE` regexes in `scrubber.scrub`. - **Consistent tokens**: the same value maps to the same placeholder every time. - **Regex and NER**: regex catches basic patterns. NER catches more. Use both. - **When**: before the LLM call. Post-processing cleanup is not defensible. - **Storage**: only redacted prompts plus consented opt-in raw. - **Output guardrail**: regex scrub for leaked API key patterns. ## Webhook receiver path type: flow from: projects/signed-webhook-inbox/solution/main.go, projects/signed-webhook-inbox/README.md 1. **ReadDelivery**: needs POST, a valid `X-Delivery-ID` and an integer `X-Timestamp`. Else 400. 2. **Verify**: rejects a timestamp outside the 5 minute window with 401. 3. **Verify**: compares the `v1=` HMAC-SHA256 of timestamp, ID and body with `hmac.Equal`. Else 401. 4. **Accept**: writes with fsync and an atomic hard link. A new delivery returns 202. 5. **Retry**: the same ID with the same body returns 200. 6. **Conflict**: the same ID with a different body returns 409. 7. **Replay**: an explicit `--run` ID writes one processing receipt. A second replay reuses it. ## Webhook inbox commands type: command-table span: 2 from: projects/signed-webhook-inbox/README.md | Command | What it does | |---|---| | `/tmp/webhook-inbox --mode serve --dir