An audit log whose tampering leaves a trace.
Two complementary layers: an in-database SHA-256 hash chain that surfaces any post-hoc edit, and an Object Lock COMPLIANCE lock on the cold archive that makes deletion physically impossible — even with root credentials.
01 · Two-layer model
Tamper-evidence + deletion impossibility
The hash chain reports post-hoc edits inside the hot database (13 months). The encrypted cold archive on Scaleway physically blocks deletion for 7 years.
SHA-256 hash chain (in-database)
Every audit row stores prev_hash (hash of the previous row of the same organization) and row_hash = SHA-256(prev_hash || canonical_payload). Computed by a BEFORE INSERT trigger — the application cannot influence the hash.
Any post-hoc edit of a row makes the recomputed hash diverge from the stored value, and the divergence cascades to every downstream row.
Object Lock COMPLIANCE (cold archive)
All rows older than 13 months are monthly dumped to Scaleway Object Storage Paris (fr-par) as gzipped JSONL. Object Lock COMPLIANCE mode + 7-year retention: neither deletion nor overwrite is possible.
COMPLIANCE mode = absolute blocking, even with the Scaleway account's root credentials. The provider exposes no bypass path.
02 · Proof mechanics
Four verifiable steps
From the initial write to the restore from archive, every step produces either a cryptographic trace or an opposable artefact.
- Step 1
Write
A BEFORE INSERT trigger computes prev_hash + row_hash from the canonical payload. Application code has no influence on the chain.
- Step 2
Continuous verification
A weekly cron (Monday 04:00 UTC) recomputes the chain for every active organization and triggers a CRITICAL alert on divergence.
- Step 3
Archive
Monthly cron (1st of the month, 03:00 UTC) moves rows > 13 months to Scaleway with Object Lock COMPLIANCE 7y + traceability metadata.
- Step 4
Restore
Upon DPO request, the archive is rehydrated from Glacier (12h max) then served to the requester as gzipped JSONL with a verifiable SHA-256 hash.
row_hash = SHA-256( prev_hash || "|" || JSON(row) ) prev_hash = row_hash of the previous audit row of the SAME org_id
03 · Regulatory framework
Multi-standard alignment
CNIL Decision 2021-122
Security logs retained for 12 months minimum. Scope retains 13 months in hot database (12 months + 1 month buffer for the annual audit).
SOC 2 Type II
Audit trail integrity and immutability over a 12-month rolling window. The hash chain provides the integrity proof required by criterion CC7.2.
ISO 27001 §8.15
Logs with integrity, retained, and tamper-resistant. Object Lock COMPLIANCE satisfies the irreversibility requirement.
DORA art. 28-29
Financial operational resilience. 7-year archive aligned with the historical traceability requirement for critical ICT.
French Commercial Code L123-22
10-year retention of accounting records. Rows tagged metadata.source = 'comptable' stay in hot database for 10 years, outside the archive cycle.
04 · DPO restore procedure
Opposable retrieval in less than 14 days
The procedure is tooled by a dedicated endpoint authenticated with a Bearer token. Every restore is itself logged in the audit trail.
1 · Request
The DPO issues POST /api/admin/audit/restore { objectKey, action: 'restore' } with the SCOPE_DPO_TOKEN Bearer token.
2 · Scaleway rehydration
Scaleway Glacier rehydrates the object to the Standard tier within 12 hours max. No manual Scope action required.
3 · Retrieval
The DPO calls the endpoint again with action: 'fetch' and receives the gzipped JSONL inline (Content-Type application/x-ndjson, Content-Encoding gzip).
4 · Traceability
The restore request is itself logged in audit_logs with the gdpr.export_requested verb + DPO metadata.
Full runbook
/legal/audit-log-immutability-proof — version 1.0 dated 2026-06-10.