API-16: persistente modul-signaturschluessel und rotation #109

Closed
patrick wants to merge 0 commits from feature/api-16-persistente-modul-signaturschluessel into integration/gesamtprojekt
pull from: feature/api-16-persistente-modul-signaturschluessel
Owner

Persistente, verschluesselte Modul-Signaturschluessel mit Rotation und Ueberlappung (Ticket API-16, core-kanban/tickets/API-16.md). Basis integration/gesamtprojekt, kein Merge vorgesehen.

Umsetzung: Tabelle module_signing_keys in der Mandanten-DB (Tenant-Migration 0008), private Schluessel nur verpackt (kek.EncryptWithTenantKEK, Schluessel aus NEXARCH_ACCOUNT_MODULE_KEY_ENCRYPTION_KEY), Instanzen teilen die Schluessel unter Advisory-Lock, Rotation mit Aktivierungsverzoegerung und Ablauf nach TTL+30 s, nicht lesbarer Speicher ergibt 503 (fail closed). Rotation nach Alter oder per account-api -rotate-module-key. Bruch: Kontodienst startet ohne Verschluesselungsschluessel nicht mehr (oder ausdruecklich ..._KEYS_EPHEMERAL=true).

Durchgefuehrte Pruefungen (Host 204, Wegwerf-Cluster, seriell):

  • Neustart am echten Kontodienst (alter Prozess beendet, neuer Prozess): dieselbe KID, Token vor dem Neustart gueltig - bestanden
  • Zwei Instanzen, eine Datenbank: gleiche Schluessel, Token gegenseitig verifizierbar, genau eine Zeile - bestanden
  • Rotation: 2 Schluessel in beiden JWKS, Signatur erst nach Aktivierung mit dem neuen, alter nach TTL+Toleranz aus JWKS und Datenbank entfernt - bestanden
  • Ausfall des Schluesselspeichers: 503 fuer JWKS und Token, danach 200; falscher/fehlender Verschluesselungsschluessel: Dienst startet nicht - bestanden
  • Klartext-, Manipulations- und Parallelstart-Tests (Unit und gegen echte Postgres-DB): 12 neue Tests bestanden
  • scripts/e2e-core-dms.sh gruen, Migration 0008 up/down/up gruen, migrations-fresh-check.sh gruen (88 Tabellen), 12 betroffene Core-Pakete gruen, vet und Port-/Routenskripte sauber

Iterationen: Produktivcode 0. Testaufbau 1: Das erste e2e-Skript meldete den Neustart faelschlich als bestanden (Zwischenprozess), korrigiert, das Skript belegt den echten Neustart jetzt.

Offen (Details in docs/API-16-PRUEFPROTOKOLL.md): Neuverpackung bei Wechsel des Verschluesselungsschluessels, Token-Widerruf, Reverse-Proxy-Regel und Smoke mit dem laufenden dms-app im Token-Modus, Schluessel liegen je Mandanten-DB (Abweichung vom Auftragstext "Registry", begruendet).

Generated with Claude Code

Persistente, verschluesselte Modul-Signaturschluessel mit Rotation und Ueberlappung (Ticket API-16, `core-kanban/tickets/API-16.md`). Basis `integration/gesamtprojekt`, kein Merge vorgesehen. **Umsetzung:** Tabelle `module_signing_keys` in der Mandanten-DB (Tenant-Migration 0008), private Schluessel nur verpackt (`kek.EncryptWithTenantKEK`, Schluessel aus `NEXARCH_ACCOUNT_MODULE_KEY_ENCRYPTION_KEY`), Instanzen teilen die Schluessel unter Advisory-Lock, Rotation mit Aktivierungsverzoegerung und Ablauf nach TTL+30 s, nicht lesbarer Speicher ergibt 503 (fail closed). Rotation nach Alter oder per `account-api -rotate-module-key`. Bruch: Kontodienst startet ohne Verschluesselungsschluessel nicht mehr (oder ausdruecklich `..._KEYS_EPHEMERAL=true`). **Durchgefuehrte Pruefungen (Host 204, Wegwerf-Cluster, seriell):** - Neustart am echten Kontodienst (alter Prozess beendet, neuer Prozess): dieselbe KID, Token vor dem Neustart gueltig - bestanden - Zwei Instanzen, eine Datenbank: gleiche Schluessel, Token gegenseitig verifizierbar, genau eine Zeile - bestanden - Rotation: 2 Schluessel in beiden JWKS, Signatur erst nach Aktivierung mit dem neuen, alter nach TTL+Toleranz aus JWKS und Datenbank entfernt - bestanden - Ausfall des Schluesselspeichers: 503 fuer JWKS und Token, danach 200; falscher/fehlender Verschluesselungsschluessel: Dienst startet nicht - bestanden - Klartext-, Manipulations- und Parallelstart-Tests (Unit und gegen echte Postgres-DB): 12 neue Tests bestanden - `scripts/e2e-core-dms.sh` gruen, Migration 0008 up/down/up gruen, `migrations-fresh-check.sh` gruen (88 Tabellen), 12 betroffene Core-Pakete gruen, vet und Port-/Routenskripte sauber **Iterationen:** Produktivcode 0. Testaufbau 1: Das erste e2e-Skript meldete den Neustart faelschlich als bestanden (Zwischenprozess), korrigiert, das Skript belegt den echten Neustart jetzt. **Offen (Details in `docs/API-16-PRUEFPROTOKOLL.md`):** Neuverpackung bei Wechsel des Verschluesselungsschluessels, Token-Widerruf, Reverse-Proxy-Regel und Smoke mit dem laufenden dms-app im Token-Modus, Schluessel liegen je Mandanten-DB (Abweichung vom Auftragstext "Registry", begruendet). Generated with [Claude Code](https://claude.com/claude-code)
patrick added 4 commits 2026-09-21 23:55:09 +02:00
API-16: persistente modul-signaturschlüssel und rotation
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (push) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (push) Canceled after 0s
e57b0d23b6
Signaturschluessel der Modul-JWTs liegen verschluesselt in der Mandanten-Datenbank
(module_signing_keys), werden von mehreren Instanzen geteilt und rotieren mit
Ueberlappung; nicht lesbarer Speicher ergibt 503 statt Token/JWKS.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
API-16: gofmt
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (push) Canceled after 0s
db55716f72
API-16: e2e-skript startet Kontodienst ohne Zwischenprozess und belegt den echten Neustart
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
8059cf8cd3
API-16: Pruefprotokoll
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (pull_request) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (pull_request) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (pull_request) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (pull_request) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (pull_request) Canceled after 0s
CI / Web (dms-browser) (pull_request) Canceled after 0s
CI / Web (pdf-viewer) (pull_request) Canceled after 0s
CI / Web (shl) (pull_request) Canceled after 0s
Core-Schnittstellen-Vertragstests / contract-tests (pull_request) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (pull_request) Canceled after 0s
Supply-Chain-Scan (npm) / npm-audit (pull_request) Canceled after 0s
Core-Pflichttest-Gate / pflichttest-gate (pull_request) Canceled after 0s
RBAC-Rollenhierarchie-Pflichtgate / rbac-policy-invariant (pull_request) Canceled after 0s
9fb2b25cbb
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
patrick closed this pull request 2026-09-25 23:30:50 +02:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: scripte/nexarch#109