L10b Betrieb & Aufräumen: Audit nach Commit, mergeCustomers atomar, Audit-Aktion read

- Aufräumpunkt h: writeAuditLog puffert innerhalb von inTransaction (AsyncLocalStorage) und
  schreibt nach dem Commit; bei Rollback werden die Einträge verworfen, nur „denied" bleibt.
  Verschachtelte Transaktionen nutzen den äußeren Puffer.
- Aufräumpunkt d: mergeCustomers läuft über inTransaction (sequenziell, geschützter Statuswechsel)
  statt ctx.db.$transaction([...]) und ist damit auch bei RLS_ENFORCED=true atomar und in äußere
  Transaktionen einbettbar.
- Aufräumpunkt e: AuditAction „read" (+ Label im Audit-Viewer de/en); Notdienst-Kunden- und
  Objektsuche protokollieren als „read" statt „export".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 18:19:19 +02:00
co-authored by Claude Opus 5
parent 85bae832d0
commit 8aedc642ca
6 changed files with 129 additions and 57 deletions
+2 -2
View File
@@ -35,7 +35,7 @@ export async function searchCustomersForEmergency(ctx: ServiceCtx, rawQuery: str
await writeAuditLog({
tenantId: ctx.tenantId,
actorId: ctx.userId,
action: "export",
action: "read",
entity: "emergency_customer_search",
after: { query: q, resultCount: rows.length, customerIds: rows.map((r) => r.id) },
});
@@ -64,7 +64,7 @@ export async function listSitesForEmergency(ctx: ServiceCtx, customerId: string)
await writeAuditLog({
tenantId: ctx.tenantId,
actorId: ctx.userId,
action: "export",
action: "read",
entity: "emergency_site_lookup",
entityId: customerId,
after: { resultCount: sites.length, siteIds: sites.map((s) => s.id) },