feat(privacy): WP-41 — persisted, queryable authz/PII-reveal audit

Persist the security-relevant events (authz denials + BIG-nummer reveal/step-up) into a
data-minimised EF table (AuthzAuditEntry: At/Action/Resource/Decision/Role/CorrelationId —
never a name/BSN/value), extending the DocumentStore AuditEntry pattern (migration AuthzAudit).
AuditAuthz now persists via AuthzAuditStore.Record alongside its log line. GET /admin/audit
(admin-gated by the existing CasesAdmin) returns the trail newest-first. +3 backend tests incl.
a schema-carries-no-PII reflection test. Typed client regenerated (audit() + AuthzAuditDto);
no FE consumer yet (a future audit view must add the ROLE_AWARE prefix). Finishes WP-42's audit half.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
eho
2026-07-23 15:53:33 +02:00
co-authored by Claude Opus 4.8
parent 8c54ede6eb
commit 0f30143c5d
12 changed files with 590 additions and 5 deletions
+62
View File
@@ -801,6 +801,38 @@
}
}
},
"/api/v1/admin/audit": {
"get": {
"tags": [
"BigRegister.Api, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AuthzAuditDto"
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/problem+json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
}
},
"/api/v1/me": {
"get": {
"tags": [
@@ -1445,6 +1477,36 @@
},
"additionalProperties": false
},
"AuthzAuditDto": {
"type": "object",
"properties": {
"at": {
"type": "string",
"nullable": true
},
"action": {
"type": "string",
"nullable": true
},
"resource": {
"type": "string",
"nullable": true
},
"decision": {
"type": "string",
"nullable": true
},
"role": {
"type": "string",
"nullable": true
},
"correlationId": {
"type": "string",
"nullable": true
}
},
"additionalProperties": false
},
"BriefDecisionsDto": {
"type": "object",
"properties": {