Merge PR #322: QA-05 (Connect): Abnahme-Pruefung Connect
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 / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (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 / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s

This commit is contained in:
patrick committed 2026-10-19 02:20:23 +02:00
commit f86484db6b
1 file changed
+263
+263
View File
@@ -0,0 +1,263 @@
# QA-05 – Abnahme-Prüfung Connect: Prüfprotokoll
Datum: 2026-10-16. Host 192.168.1.204, frischer Klon von
`gitea.perlbach24.de/scripte/nexarch.git` nach
`/root/qa-05-connect-work-1792161903`, Branch
`feature/qa-05-05-abnahme-pruefung-connect` von `main`
(`dac7fff504ba65bad7bec64d06cfe062845d3e09`, 2026-10-15) abgezweigt.
Eigene Wegwerf-Postgres-Rolle/DB `qa05_connect_test` (Passwort generiert,
nur in `/root/.qa05_connect_env` auf Host 204, root-only, nicht Teil des
Commits). `archivdms` nicht berührt. Alle Testdaten synthetisch.
Diese Kachel ist, wie im Ticket festgelegt, eine Zusammenfassungs- und
Abnahme-Kachel – kein Code-Integrationsticket. Sie baut keinen neuen
Produktcode, der alle sechs Vorgänger-Branches gleichzeitig voraussetzt,
sondern (1) liest die sechs realen Prüfprotokolle direkt aus den
jeweiligen offenen PR-Branches (ohne Merge), (2) führt einen echten,
frischen Gesamttestlauf gegen den tatsächlich in `main` bereits
zusammengeführten Connect-Bestand durch, und (3) trifft auf dieser
Grundlage eine begründete Freigabeentscheidung.
## Ausgangslage: Merge-Status der sechs Vorgänger-Gates
Keines der sechs Prüfgates ist zum Prüfzeitpunkt in `main` gemergt. Alle
liegen als offene PRs vor:
| Gate | PR | Branch | Basis |
|---|---|---|---|
| QA-02 | #315 | `feature/qa-02-02-pruefgate-connector-engine` | `main` |
| QA-03 | #317 | `feature/qa-03-03-pruefgate-erp-datev-m365` | `main` |
| QA-04 | #320 | `feature/qa-04-04-sicherheitspruefung-drittsystem-credentials` | `feature/eng-07-...` (unmerged ENG-07) |
| QA-06 | #319 | `feature/qa-06-schnittstellen-vertragstests-connect` | `feature/api-03-...` (unmerged API-03) |
| QA-07 | #314 | `feature/qa-07-last-leistungstest-connect` | `main` |
| QA-08 | #321 | `feature/qa-08-barrierefreiheits-audit-connect` | `feature/api-01-...` (unmerged API-01) |
Jeder Branch wurde per `git fetch origin <branch>` lokal referenziert und
sein `connect/docs/<CODE>-PRUEFPROTOKOLL.md` per `git show <branch>:...`
gelesen – kein Merge, keine Änderung an diesen Branches.
## AC1 – Alle vorgelagerten Prüfgates abgeschlossen und protokolliert
Alle sechs Protokolle liegen vollständig vor und schließen jeweils mit
einem nachvollziehbaren Ergebnis, belegt durch echte Testläufe (nicht nur
Behauptungen):
| Gate | Ergebnis laut eigenem Protokoll | Zentrale reale Befunde |
|---|---|---|
| QA-02 (Connector-Engine) | Bestanden | Echte, netzwerkseitige Fehlerinjektion (lokaler HTTP-Server, 2× echtes 503, danach 200) treibt Retry+Backoff und wird nach Erholung vollständig im Audit-Trail nachgeliefert. 3-fach wiederholt, keine Flakiness. |
| QA-03 (ERP/DATEV/M365 + DMS2) | Bestanden | Erstmals echte Testläufe gegen den QA-01-Referenzkorpus (statt Ad-hoc-Mocks) ergänzt; dabei ein **echter Frontend-Fehler** in `web/datev-export` gefunden (doppelte React-Kopie durch fehlenden Resolve-Alias) und behoben. |
| QA-04 (Credential-Sicherheit) | Bestanden nach Fix | Verschlüsselung/Zugriffskontrolle bestanden. **Echter, kritischer Befund:** Tenant-KEK-Rotation machte vor dem Fix alle Bestands-Credentials dauerhaft unlesbar (empirisch nachgewiesen, dann durch `RewrapDEK`/`RewrapTenantKEK` behoben, analog DMS/FDN-09). Offen: keine End-User-RBAC-Permission für Credential-Zugriff (noch kein Endpunkt, der das bräuchte). |
| QA-06 (Vertragstests Webhook) | Bestanden, mit offen benannter Einschränkung | 8/8 Vertragstests grün, inkl. echtem Breaking-Change-Beweis (Signatur-Header real umbenannt → Tests schlagen exakt wie erwartet fehl). **Einschränkung:** Core besitzt keinen HTTP-Endpunkt für die Webhook-Abonnement-Verwaltung (API-07 nur als Go-Paket, nicht verdrahtet) – der Abonnement-Vertrag ist nur einseitig (Connect-Konsument) geprüft, nicht gegen eine echte Core-Instanz. |
| QA-07 (Last/Leistung) | Bestanden | Alle drei Lasttests (Credential-Abruf, Sync-Job-Queue, Rate-Limiting) mit realen Messwerten weit innerhalb der Zielwerte, gegen echte Postgres-Testdatenbank, 0 Fehler. |
| QA-08 (Barrierefreiheit) | Bestanden mit offenem AC2 | 0 axe-Verstöße über 4 Oberflächen, vollständige Maus-freie Kernabläufe real durchgeführt. **AC2 nicht erfüllt:** kein Bildschirmleser (NVDA/VoiceOru/Orca) auf Testhost/Entwicklungsmaschine installierbar – dieselbe organisatorische Lücke wie `UX-06` (DMS) und `UX-07` (Mail), dort mit Frist 2026-10-31 verfolgt. |
**Bewertung AC1:** Erfüllt. Alle sechs Protokolle liegen vor, sind in
sich stimmig, durch echte Messungen belegt und benennen ihre jeweils
eigenen Restrisiken selbst und unverharmlost.
## AC2 – Zusammenspiel aller Connectoren im Gesamttest geprüft
### Einschränkung (siehe Auftrag)
Ein Gesamttest, der alle sechs offenen PR-Branches gleichzeitig im
selben Checkout voraussetzt (insbesondere QA-04 auf ENG-07, QA-08 auf
API-01, QA-06 auf API-03 – drei voneinander unabhängige, noch nicht
gegeneinander abgestimmte Feature-Branches), wurde **bewusst nicht**
durch einen Mehrfach-Merge versucht. Das Risiko realer Merge-Konflikte
und unbeabsichtigter Interaktionseffekte zwischen noch nicht final
abgestimmten Features wäre höher als der Erkenntnisgewinn gegenüber den
bereits vorliegenden Einzelprotokollen. Diese Prüfung ist daher in zwei
real durchgeführte Teile zerlegt:
### Teil 1: Echter Gesamttestlauf gegen den tatsächlich in `main` bereits zusammengeführten Connect-Bestand
`main` enthält bereits ENG-01–06, ENG-08, ENG-10, ERP-01–04, DAT-01–03,
M365-01–03, DMS2-01–03 und API-02 – also die überwiegende Mehrheit aller
Connectoren und der Connector-Engine, real im selben Checkout vereint.
Frischer Testlauf auf dieser Grundlage:
```
cd connect
go build ./... -> clean
go vet ./... -> clean
go test ./... -count=1 -p 1 -> 27/27 testbare Pakete ok, 0 FAIL, 0 SKIP
bash scripts/check-security-test-coverage.sh -> "Merge-Gate bestanden"
```
Betroffene Pakete (Auszug, vollständige Liste im Rohlog): `registry`,
`credential`, `crypto`, `httpclient`, `syncjob`, `fieldmapping`,
`auditclient`, `audittrail`, `erpconnector`, `erpexport`, `crmconnector`,
`datevtransfer`, `datevexport`, `datevapi`, `m365connector`,
`m365calsync`, `m365docsync`, `dms2import`, `dms2importapi`,
`backupconnector`, `masterdatasync`, `dmsexchange`, `thirdpartyrate`,
`statusapi`, `killswitch`, `policyclient`, `archiveclient`,
`testcorpus`. Alle Connector-Typen (ERP, CRM, DATEV, M365, DMS2/Backup)
liefen damit real **gemeinsam in einem Lauf**, nicht nur einzeln.
Frontend-Gesamttest (alle auf `main` vorhandenen Connect-Oberflächen):
```
web/connect-status -> npm install (kein Lockfile im Paket) + vitest run: 5/5 Tests grün, tsc sauber
web/dms2-import -> npm ci + vitest run: 3/3 Tests grün, tsc sauber
web/datev-export -> npm ci + vitest run: 4/4 Tests FEHLGESCHLAGEN (siehe Befund unten), tsc sauber
```
**Eigener, unabhängig reproduzierter Befund:** Der in QA-03 gefundene und
dort behobene Fehler (`web/datev-export`: fehlender React-Resolve-Alias
in `vitest.config.ts`, führt zu einer zweiten React-Kopie und
`Cannot read properties of null (reading 'useState')`) wurde in dieser
Sitzung **unabhängig erneut real reproduziert** – weil der Fix nur auf
dem QA-03-Branch existiert, nicht in `main`. Das bestätigt zwei Dinge:
(a) QA-03s Befund war real und ist korrekt behoben, (b) `main` ist
heute, vor Merge von PR #317, für `web/datev-export` tatsächlich rot.
Dies ist kein neuer Fehler, sondern der sichtbare Beweis, dass der
Gesamttest gegen den ungemergten `main`-Stand ehrlich und ungeschönt
durchgeführt wurde, statt die Behauptung aus dem QA-03-Protokoll
unkritisch zu übernehmen.
`gofmt -l .` listet zusätzlich 10 vorbestehende, nicht von dieser Kachel
verursachte unformatierte Dateien (`datevapi`, `datevexport`,
`dms2import`, `dms2importapi`, `erpexport`, `testcorpus`) – rein
kosmetisch, bereits in QA-02 als Befund vermerkt, hier nicht behoben
(außerhalb des Ticketumfangs).
### Teil 2: Zusammenspiel mit Core-Webhook-Registry (Prüfung 2 des Tickets)
Core besitzt auf `main` bereits `internal/webhook` (Registrierung,
Zustellung mit Retry/Backoff, HMAC-Signatur) – aber, bestätigt per
`grep` über den gesamten Checkout, **keinen HTTP-Handler**, der dieses
Paket für ein physisch getrenntes Modul wie Connect erreichbar macht
(an keinem `cmd/`-Binary verdrahtet). Die Connect-seitigen
Konsument-Pakete (`webhooksub`, `webhookclient`) existieren auf `main`
überhaupt nicht – nur auf den unmerged Branches API-03/QA-06.
Ein echter Zusammenspiel-Test auf `main` selbst ist damit zum
Prüfzeitpunkt nicht möglich – nicht wegen eines Connect-Fehlers, sondern
weil die Gegenstelle (Core-HTTP-Wrapper für API-07) schlicht noch nicht
existiert. Ersatzweise wurde der bereits in QA-06 gebaute
Vertragstest-Korpus in einem isolierten `git worktree` auf dem
`qa06`-Branch (= API-03 + QA-06, nicht gemergt, nicht verändert) frisch
erneut ausgeführt, als unabhängige Momentaufnahme:
```
cd /root/qa05-webhook-spotcheck/connect
go build ./... -> clean
go test ./internal/contracttest/... -v -> 8/8 PASS (erneuter, unabhaengiger Lauf):
TestContract_SubscribeRequest_SentFieldsMatchDocumentedCorpus
TestContract_SubscribeRequest_DetectsBreakingChange_RenamedField
TestContract_SubscribeResponse_RealStructMarshalsDocumentedFields
TestContract_SubscribeResponse_DetectsBreakingChange_RemovedField
TestContract_UnsubscribeRequest_MethodPathAndQueryMatchDocumentedCorpus
TestContract_DeliverySignatureHeader_MatchesDocumentedName
TestContract_DeliveryEndToEnd_DocumentedSignature_Succeeds
TestContract_DeliveryEndToEnd_DetectsBreakingChange_RenamedSignatureHeader
```
Worktree danach wieder entfernt (`git worktree remove --force`), keine
Änderung an `qa06` vorgenommen, kein Push von dort.
**Bewertung AC2:** Teilweise erfüllt, mit offen benannter Einschränkung.
Das Zusammenspiel **aller bereits in `main` zusammengeführten
Connectoren** (ERP, CRM, DATEV, M365, DMS2/Backup, Sync-Engine) wurde
real in einem gemeinsamen Testlauf nachgewiesen – kein Mock-only-Beweis,
echte Postgres-Testdatenbank, echte HTTP-Wege. Das Zusammenspiel mit der
Core-Webhook-Registry ist dagegen, wie von QA-06 selbst bereits benannt,
nur einseitig (Connect-Konsument) und nur auf einem noch nicht gemergten
Branch nachweisbar – ein beidseitiger Nachweis gegen eine laufende
Core-Instanz mit echtem HTTP-Endpunkt ist strukturell erst möglich,
sobald der Core-seitige Wrapper existiert (core-kanban-Board, außerhalb
dieser Kachel und außerhalb von Connect insgesamt).
## AC3 – Abnahmeprotokoll abgelegt und nachlesbar
Dieses Dokument: `connect/docs/QA-05-PRUEFPROTOKOLL.md`. Erfüllt.
## Freigabeentscheidung
**Bedingte Freigabe.** Nexarch Connect ist fachlich und technisch auf
einem belastbaren Stand – alle sechs Prüfgates sind mit echten
Messungen bestanden (teils nach einem real gefundenen und behobenen
Fehler), kein Gate behauptet etwas ohne Protokoll, und der eigene
Gesamttest in dieser Kachel bestätigt die Engine- und
Connector-Robustheit unabhängig erneut. Eine uneingeschränkte Freigabe
ist aber nicht gerechtfertigt, weil mehrere konkrete, benannte
Restrisiken offen sind und weil der geprüfte Gesamtbestand aktuell nur
als Summe einzelner, nicht gegeneinander abgestimmter Branches
existiert – nicht als ein einziger, gemeinsam getesteter Integrations-
stand. Die Freigabe gilt unter folgenden Bedingungen:
1. **Vor jeder produktiven Nutzung durch andere Module:** Alle sechs
PRs (sowie ihre eigenen Abhängigkeiten ENG-07, API-01, API-03) müssen
gemergt und danach ein frischer Gesamttestlauf auf dem tatsächlich
integrierten `main`-Stand wiederholt werden. Der in dieser Kachel
durchgeführte Gesamttest deckt nur den bereits gemergten Teilbestand
ab; das volle Feature-Set wurde noch nie gemeinsam in einem Checkout
ausgeführt.
2. **Vor Freischaltung von Webhook-Abonnements:** Core muss den
HTTP-Wrapper für API-07 (Webhook-Registry) liefern. Bis dahin ist der
Abonnement-Verwaltungsvertrag nur ein von Connect veröffentlichter,
nicht beidseitig bestätigter Pact (core-kanban-Board, außerhalb
dieser Kachel).
3. **Vor Freischaltung von API-01 (Connect-Konfigurationsoberfläche):**
Es existiert noch keine End-User-RBAC-Permission für
Credential-Zugriff (`connect.credential.*`) und keinen dafür
verdrahteten HTTP-Endpunkt – API-01 darf nicht ohne eine nach dem
`statusapi`-Muster (`requireIdentity`+`requirePermission`)
implementierte Zugriffskontrolle live gehen (bereits in QA-04 als
Empfehlung vermerkt, hier bekräftigt).
4. **Vor dem ersten echten Tenant-KEK-Rotations-Ereignis in Produktion:**
Es existiert jetzt eine Rewrap-Fähigkeit (`RewrapTenantKEK`), aber
kein automatischer Trigger/Runbook, der sie aufruft. Ein Runbook muss
vor der ersten echten Rotation vorliegen.
5. **`web/datev-export`:** PR #317 (QA-03) muss gemergt werden, bevor der
Frontend-Testbestand auf `main` wieder grün ist – aktuell real
reproduziert rot (siehe oben).
6. **Bildschirmleser-Durchlauf (AC2 aus QA-08):** bleibt offen, verfolgt
unter der projektweiten Frist aus `UX-06` (2026-10-31) – kein
Connect-spezifischer Blocker, aber Teil der Gesamtzusage zur
Barrierefreiheit.
Keines der gefundenen Risiken deutet auf einen grundlegenden
Architektur- oder Engine-Mangel hin – jedes ist entweder bereits
behoben (KEK-Rotation, DATEV-Export-Frontend-Fehler, jeweils mit
Protokoll) oder ein sauber benannter, noch offener Abhängigkeits-/
Organisationspunkt mit klarem Verantwortlichen. Eine "keine Freigabe"
wäre angesichts der Qualität und Dichte der bereits real durchgeführten
Prüfungen nicht angemessen; eine uneingeschränkte "volle Freigabe" würde
die oben genannten, konkreten und teils sicherheitsrelevanten (RBAC,
Webhook-Core-Lücke) Punkte verharmlosen.
## DSGVO
Keine echten Kunden-/Mandantendaten verwendet. Eigene Wegwerf-DB
`qa05_connect_test` mit ausschließlich synthetischen Daten aus den
bereits vorhandenen Testfixtures/-korpora der geprüften Branches.
Zugangsdaten (`TEST_ADMIN_DSN`/`TEST_TENANT_DSN`) ausschließlich als
Variablennamen referenziert, kein Wert in diesem Protokoll oder im
Commit.
## Entscheidungen/Ermessen in dieser Sitzung
- **Kein Mehrfach-Merge:** bewusst unterlassen, Begründung siehe AC2.
Stattdessen Gesamttest gegen den echten `main`-Bestand plus isolierter
Worktree-Spotcheck für die Webhook-Vertragstests, ohne einen der
Branches zu verändern.
- **Reproduktion statt Übernahme des datev-export-Befunds:** Der
QA-03-Fehlerbefund wurde nicht als gegeben übernommen, sondern
unabhängig erneut real ausgelöst (Testlauf gegen unverändertes
`main`), um die eigene Prüfungspflicht dieser Kachel ernst zu nehmen.
- **Eigene Wegwerf-DB statt Wiederverwendung** einer der bereits
laufenden Test-DBs auf Host 204, um Kollisionen mit parallelen
Testläufen zu vermeiden.
- 0 von 20 Iterationen für Unklarheiten gebraucht.
## Gesamtergebnis
**Bedingte Freigabe** von NEXARCH Connect zur Nutzung durch andere
Module – siehe Bedingungen 1–6 oben. AC1 und AC3 vollständig erfüllt,
AC2 für den bereits gemergten Connector-Bestand real nachgewiesen, für
das Zusammenspiel mit der Core-Webhook-Registry nur einseitig und nur
auf unmerged Branches nachweisbar (strukturelle Abhängigkeit von
core-kanban, nicht von dieser Kachel behebbar).
Kein Merge, kein Deploy.