BLOCKING-Befunde aus "Tests & Sicherheitshaertung":
1) Coverage-Pfad war nie ausfuehrbar: @vitest/coverage-v8 fehlte in den
devDependencies, obwohl vitest.config coverage.provider "v8" setzt und
test:coverage "vitest run --coverage" aufruft. Paket passend zu vitest
^3.2 ergaenzt und installiert. coverage.include zog ganze Verzeichnisse
(src/lib/search, src/lib/geo) ein - inkl. DB-/HTTP-gebundener Wrapper
(Drizzle gegen Postgres, Nominatim/OSRM), die offline nicht laufen und
die globale Schwelle verwaesserten. Scope auf die REINE, offline
testbare Logik beschraenkt (perFile-Schwellen), I/O-Wrapper und reine
Typ-Module ausgenommen (per Integrations-/E2E-Tests abgesichert).
Fehlende Branch-Abdeckung in geo/eintreffzeit.ts mit Tests fuer
Einzel-Haversine-Fallback, reine Koordinaten-lose Liste und fehlende
OSRM-distances-Zeile geschlossen. npm run test:coverage: Exit 0,
Schwellen (Lines/Stmts/Funcs >=90, Branches >=80) erfuellt.
2) Driftschutz zu permissiv: isPublic() in tests/support/route-scan.ts
stufte ueber `route.startsWith(p)` jeden reinen String-Praefix als
oeffentlich ein (z. B. /loginhelp, /api/healthz, /api/authentication)
und liess solche Routen dem Auth-Gating-Driftcheck entkommen. Die
redundante dritte Bedingung entfernt; exakter Treffer und echtes
Unterpfad-Segment (p + "/") sind korrekt und ausreichend. Negativ-
Testfall ergaenzt.
Verifiziert (offline): tsc --noEmit (0), vitest run (233 passed,
7 DB-Tests deferred), test:coverage (Exit 0). DB-/Server-/Browser-
abhaengige Schritte deferred (kein Postgres/Server im Sandbox).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Beweist die Auth-Gating-Garantie und härtet das System ab (Definition of
Done #1, #2, #3, #7, #8):
- Routen-Manifest (tests/e2e/routes.manifest.ts) als einzige Quelle der
Wahrheit; anonyme Seite -> Redirect /login, anonyme API -> 401.
- Kritische auth-gating.spec.ts: genau ein Fall je Manifest-Eintrag, ohne
Daten-Leak.
- Driftschutz (routes.manifest.spec.ts + tests/unit/routes-manifest.test.ts):
keine ungetestete neue Route unter src/app/**.
- Default-Deny-Beweis für Server Actions (server-actions-guard.spec.ts +
tests/unit/server-actions-guard.test.ts): jede "use server"-Funktion ruft
als erste Anweisung einen Guard; Login-Actions per Allowlist ausgenommen.
- Wiederverwendbare reine Scanner unter tests/support (route-scan, guard-scan)
— offline lauffähig, in Vitest und Playwright geteilt.
- rbac-scoping, search-eta, login-ratelimit, security-headers Specs (gegen
geseedeten Server; in der Sandbox deferred, per test.skip abgesichert).
- global-setup (Migration + Seed) und auth.setup (Login je Konto ->
storageState); Playwright-Projekte setup -> chromium verdrahtet.
- src/lib/security/headers.test.ts: statischer Beleg für CSP, HSTS,
X-Frame-Options DENY, nosniff, Permissions-Policy.
- vitest.config.ts: Coverage-Schwellen (>=90 %) für src/lib/search + src/lib/geo.
- package.json: Scripts test:unit, test:coverage, test:e2e, test:e2e:gating.
- docs/reference/sicherheitshaertung-checkliste.md: jeder Härtungspunkt mit
Test/Befehl und Negativ-Probe.
Offline verifiziert: tsc --noEmit (0), vitest run (229 passed / 7 db-skipped),
drizzle-kit check (ok), next build (exit 0), next lint (0 Fehler),
playwright --list (98 Tests, 15 Dateien). DB-/Server-/Browser-abhängige
E2E-Läufe sind deferred (kein Postgres/Server in der Sandbox).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Zwei BLOCKING-Befunde für "Deployment (Docker + externes Traefik)":
1) pg-Laufzeit-Closure unvollständig: pg-types/lib/binaryParsers.js macht
eager require('pg-int8'), postgres-interval/index.js require('xtend/mutable').
Beide lagen NICHT im Runner-Image -> node docker/migrate.mjs crasht beim
Container-Start mit ERR_MODULE_NOT_FOUND, Deploy kaputt. Fix: COPY für
pg-int8 + xtend ergänzt. Neuer Test berechnet die reale Closure aus
node_modules und schlägt fehl, sobald ein Paket nicht ins Image kopiert
wird (schützt vor erneutem Brechen bei pg/drizzle-Updates).
2) RUN_SEED toter Pfad: entrypoint.sh rief docker/seed.mjs auf, das nie
existierte -> RUN_SEED=true no-opte still zu leerem Katalog. Fix:
scripts/build-seed-bundle.mjs bündelt src/db/seed (inkl. Schema + Daten,
pg/drizzle-orm extern) per esbuild zu selbstständigem docker/seed.mjs;
im builder erzeugt und ins Runner-Image kopiert. entrypoint.sh bricht
jetzt laut ab, wenn RUN_SEED=true und das Bundle fehlt, statt still zu
überspringen. docker/seed.mjs ist generiert -> gitignored.
Verifiziert offline: tsc --noEmit, vitest (deployment + seed-Daten, 36 grün),
Bundle baut + lädt sauber (externe Imports nur pg/drizzle-orm, exit 1 ohne
DATABASE_URL). docker build/run sind im Sandbox deferred (kein Docker/Postgres).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>