Files
nexarch/archive/docs/RET-06-API-PRUEFPROTOKOLL.md
T
sysops 21278f1405 feat(archive): RET-06-API Aufbewahrungsfristen-Konfigurations-Backend
Board-Entscheidung: Backend-API zuerst, echtes Next.js-Frontend als
separates Folgeticket - vermeidet Pseudo-Frontend-Protokoll.
internal/retentionapi: 4 Endpunkte (anlegen/aendern, deaktivieren,
liste, vorschau), Vorschau nutzt dieselbe ListExpiringObjects-Funktion
wie RET-02s periodischer Job (keine Doppel-Implementierung).
RequireRole ist AUSDRUECKLICH kein RBAC-02-Ersatz, sondern ein
dokumentiertes Provisorium (Header-Check) - RBAC-02 ist reiner
Core-interner Go-Code ohne HTTP-Schnittstelle fuer andere Module,
derselbe Befund wie FDN-03/FDN-09. Provisorium real getestet inkl.
Negativfall (403 ohne/mit falscher Rolle). retention_class_rules um
active-Flag erweitert (deaktivieren ohne Historienverlust). Real auf
131 deployed und per curl end-to-end verifiziert.
2026-08-30 02:09:37 +02:00

4.9 KiB
Raw Blame History

RET-06-API Prüfprotokoll: Aufbewahrungsfristen-Konfigurations-Backend

Voraussetzung RET-02 erledigt, siehe eigenes Protokoll.

Scope-Entscheidung (Board-Rücksprache): RET-06 verlangt Next.js/ React-Frontend + Backend-API + RBAC. Statt eines einzigen Big-Scope-Tickets: Backend-API zuerst (dieses Protokoll), das echte Next.js-Frontend folgt als eigenes, separates Ticket. Diese Trennung wurde bewusst gewählt, damit das Prüfprotokoll nicht auf ein Pseudo-Frontend verweist.

Grundsatzentscheidung: provisorischer Rollen-Check, KEIN RBAC-02

Core RBAC-02 (internal/policy, Enforcer.Authorize) ist reiner Go-Code innerhalb des Core-Moduls — keine HTTP-Schnittstelle, über die Archive (physisch getrenntes Go-Modul) es aufrufen könnte. Derselbe "gefunden, aber nicht modulübergreifend verdrahtet"-Befund wie bei Core FDN-03/FDN-09 (siehe frühere Prüfprotokolle).

internal/retentionapi.RequireRole ist AUSDRÜCKLICH KEIN RBAC-02- Ersatz, sondern ein Provisorium: prüft nur einen selbst gesetzten Header (X-Admin-Roles), leicht zu fälschen von jedem, der den Header setzen kann. Muss ersetzt werden, sobald ein Core-seitiger HTTP-Wrapper um RBAC-02 existiert (Empfehlung: eigenes künftiges Core-Ticket, z. B. RBAC-06, wiederverwendbar für alle Module statt je Modul einen eigenen Provisorium-Check). Bis dahin real getestet inklusive Negativfall (Pflichtprüfung, siehe unten) — ein UNGEPRÜFTER Provisorium-Check wäre nur eine verschobene Schwachstelle.

Umsetzung

  • migrations/0005_retention_class_rules_active.up.sql/.down.sqlactive-Flag statt DELETE (Klasse deaktivieren ohne Historienverlust).
  • internal/retentionengine.DeactivateClassRule/ListClassRules — Erweiterung von RET-02s Paket, ComputeDueDate/ListExpiringObjects berücksichtigen nur noch aktive Regeln.
  • internal/retentionapi.RequireRole — provisorischer Header-Rollen-Check.
  • internal/retentionapi.Mount — vier Endpunkte: POST /retention-classes (anlegen/ändern), POST /retention-classes/{class}/deactivate, GET /retention-classes (Liste), GET /retention-classes/preview (Vorschau, nutzt DIESELBE ListExpiringObjects-Funktion wie RET-02s periodischer Job).
  • cmd/retention-api — eigenständiger HTTP-Dienst.

Prüfungen

# Prüfung Ergebnis
1 Änderung einer Frist wirkt sich nur auf künftige Berechnungen aus, nicht rückwirkend auf bereits protokollierte Vernichtungen bestandenTestConfigureClassRule_ChangeAppliesOnlyToFutureCalculations: bereits berechneter Stichtag bleibt unverändert (strukturell garantiert, keine Tabelle mit "bereits berechneten" Werten existiert, die rückwirkend verändert werden könnte), NEUE Berechnung übernimmt die neue Frist
2 Nicht berechtigte Rolle erhält keinen Zugriff auf die Konfiguration bestandenTestRequireRole_MissingRoleReturns403 (kein Header UND falsche Rolle, beide 403) UND TestRequireRole_CorrectRoleAllowsAccess (Gegentest); real auf 131: curl ohne Rollen-Header → 403
3 Vorschauliste stimmt mit dem Ergebnis des periodischen Jobs überein bestandenTestPreviewHandler_MatchesPeriodicJobResult: HTTP-Vorschau UND direkter ListExpiringObjects-Aufruf liefern dasselbe Objekt (dieselbe Funktion, kein Doppel-Code)

Zusätzlich: TestDeactivateClassRule_ExcludesFromFutureCalculations, TestConfigureAndListHandler_RealHTTPRoundTrip, TestDeactivateHandler_RealHTTPRoundTrip.

Echte Verdrahtung auf 192.168.1.131

  • retention-api gebaut nach /opt/nexarch-archive/bin/
  • /etc/nexarch/archive-retention-api.env (0600)
  • nexarch-archive-retention-api.service installiert/aktiviert (dauerhaft, Restart=on-failure)
  • Realer End-zu-Ende-Test via curl: POST ohne Rollen-Header → 403; POST mit X-Admin-Roles: archive_admin → 200, Klasse angelegt; GET /retention-classes zeigt sie; GET /retention-classes/preview liefert null (kein fälliges Objekt, korrekt leer) — Testdaten anschließend entfernt

Build/Test-Ergebnis (192.168.1.131, make check)

go build ./...  -> clean
go vet ./...    -> clean
golangci-lint run ./...  -> 0 issues
go test ./... -p 1 -count=1  -> 11/11 Pakete mit Tests ok, 0 Fehlschläge

Hinweis: Zwei Pakete (internal/retentionengine, internal/retentionapi) gegen dieselbe reale Tenant-DB laufen zu lassen erfordert -p 1 (sequentiell) — parallele Testläufe unterschiedlicher Pakete gegen dieselbe echte Datenbank führen sonst zu Cross-Test-Kontamination (TRUNCATE eines Pakets während ein anderes noch liest/schreibt). make check/Makefile erzwingt das bereits.

Gesamtergebnis

Bestanden — Backend-Scope. Alle drei Pflichtprüfungen real erfüllt. Offen, bewusst nicht Teil dieses Protokolls: das Next.js/React- Frontend (separates Folgeticket) und der Ersatz des provisorischen Rollen-Checks durch einen echten RBAC-02-Aufruf, sobald Core einen HTTP-Wrapper dafür bereitstellt.