Files
HiveGrid-Wireframes/hivegrid-cloud/docs/improvement-plan/02-observability/VERIFICATION.md
T

27 KiB

Phase 02 — Verification Report

Reviewer: Verifier-Subagent Datum: 2026-05-16 Scope: README.md + 8 Detail-MDs (29 → 36) in docs/improvement-plan/02-observability/ Verdict: APPROVED WITH MINOR FIXES — Plan ist ausführungsreif; einige Pfad-/Konsistenz-Fixes vor Phase-Start nötig (siehe §11).


1. Template-Konformität (15 Sections, korrekte Reihenfolge)

Pflicht-Reihenfolge laut DETAIL-MD-TEMPLATE.md:

  1. Frontmatter (Status/Task-ID/Phase/Effort/Owner)
  2. Problem · 3. Depends on · 4. Blocks · 5. Approach · 6. Implementation Steps
  3. Test Requirements · 8. Acceptance Criteria · 9. Rollback Strategy · 10. Security Notes
  4. Subagent Recommendations · 12. Staging-Deployment-Steps · 13. Deviations from Plan
  5. Progress Log · 15. Lessons Learned (optional)
Datei 1-5 6 7 8 9 10 11 12 13 14 15 OK?
sentry-selfhost-setup.md OK OK OK OK OK OK OK OK OK OK OK OK
sentry-wiring-api-worker.md OK OK OK OK OK OK OK OK OK OK OK OK
sentry-wiring-web.md OK OK OK OK OK OK OK OK OK OK OK OK
sentry-ci-integration.md OK OK OK OK OK OK OK OK OK OK OK OK
opentelemetry.md OK OK OK OK OK OK OK OK OK OK OK OK
logging-migration.md OK OK OK OK OK OK OK OK OK OK OK OK
metrics-grafana.md OK OK OK OK OK OK OK OK OK OK OK OK
performance-quickwins.md OK OK OK OK OK OK OK OK OK OK OK OK

Alle 8 Files folgen der Pflicht-Reihenfolge. Keine fehlenden Sections, keine Reihenfolge-Verstöße.


2. Dependencies-Konsistenz (Depends on / Blocks vs. execution-order.md)

2.1 Phase-01-Verweise

Alle Detail-MDs verweisen auf 01-tech-debt-foundation/dep-updates.md. Diese Datei existiert (verifiziert: /docs/improvement-plan/01-tech-debt-foundation/dep-updates.md). OK.

2.2 Intra-Phase-2-Graph (lt. README.md)

#29 sentry-selfhost ──► #30 wiring-api-worker ─┐
                    └─► #31 wiring-web ────────┤
                                               ▼
                                       #32 sentry-ci
                                               │
                                               ▼
                          ┌────────────────────┼────────────────────┐
                          ▼                    ▼                    ▼
                  #33 opentelemetry    #34 logging-migration   #35 metrics-grafana
                                                                    │
                                                                    ▼
                                                          #36 performance-quickwins

Cross-Check der Detail-MDs:

Task Depends on (declared) Blocks (declared) Konsistenz
#29 selfhost dep-updates #30, #31, #32, #33, scaling-*, authentik OK
#30 wiring-api-worker #29, dep-updates #32, #33, scaling-* OK
#31 wiring-web #29, dep-updates #32, capacitor OK
#32 sentry-ci #29, #30, #31 "Keine harten Blocks" OK — konsistent mit "kein harter Block, aber Phase-03+ profitiert"
#33 opentelemetry #29, #30, #31 #35 (kein harter Block) + scaling/read-write-split Abweichung: README ordnet #33 hinter #32 ein, aber #33 deklariert keine Dependency auf #32. Das ist OK weil #32 nur Release-Tagging ist und keine Wiring-Voraussetzung für OTel — der README-Graph ist Workflow-Reihenfolge, nicht harte Dependency. Kein Fix nötig, aber Hinweis an ausführenden Agent: parallel zu #32 startbar wenn #30/#31 grün.
#34 logging-migration #30, #31 "Keine harten Blocks" OK
#35 metrics-grafana #30, #34 shared-store-migration, plugin-system OK
#36 perf-quickwins #35 — OK

Finding F-1 (Minor): Cross-Phase-Block-Referenz in #29.Blocks: 09-authentik-admin-sso/authentik-setup.md — beide existieren laut PROGRESS-Logik. Kein Issue, sondern Plus.

Finding F-2 (Cosmetic): metrics-grafana.md deklariert #36 nicht explizit als blocked-by. Das passt zur Realität (perf-quickwins braucht metrics zum Messen, ist explizit als Depends-on in #36 deklariert).


3. Implementation-Steps-Qualität (Atomic-Commits, Tech-Korrektheit)

3.1 Atomic-Granularität

Task Anzahl Steps Atomic? Hinweis
#29 11 OK Step 7 (Backup-Container) ist groß aber legitim atomar; Step 11 ist Deployment (kein Commit) — sauber gekennzeichnet
#30 11 OK jede Datei einzeln, Sanitize-Refactor vor Wiring (Test-First-Ordnung)
#31 11 OK Step 1 (deps) vor Steps 2-11 — korrekt; Test-Route-Registration nur dev/staging — gut
#32 6 OK Shell-Helper vor Workflow-YAML — korrekt; Step 6 ist reine Operations
#33 13 OK Bootstrap-Module + Entry-Point-Anpassung pro Runtime jeweils 2 Commits — clean
#34 17 OK High-PII einzeln (5 Commits), Bulks in 3-Commit-Buckets — sicherer Ansatz
#35 18 OK Foundation (Packages) zuerst, dann pro Runtime, dann Business-Hooks, dann Infra
#36 9 (8 Items + Wrap-up) OK jeder Item-Fix ein Commit, sauber separierbar

3.2 Tech-Korrektheit Cross-Check

React-Router-v7-Korrektheit (#31, #33):

  • apps/web/app/entry.client.tsx, entry.server.tsx, root.tsx — Pfade verifiziert (existieren). OK.
  • ErrorBoundary in root.tsx mit useEffect(() => Sentry.captureException(error), [error]) — korrekt; aber Hinweis: bei SSR-Errors ist React-Router-v7 die Convention, dass die Server-Integration via requestDataIntegration automatisch captures. Manueller useEffect-Capture ist sinnvoll als Client-Side-Backup. OK.
  • Step 7 (#31): "Falls @sentry/react-router v8 verfügbar" — pragmatischer Decision-Punkt, gut dokumentiert. OK.
  • Finding F-3 (Minor): #33 Step 9 importiert import './otel.server' (mit .server-Suffix), aber die Datei wird in Step 9 als apps/web/app/lib/otel/server.ts angelegt — Pfad-Inkonsistenz. Fix vor Implementation: entweder Import-Pfad als ./lib/otel/server korrigieren oder Datei als entry.server.otel.ts benennen. Kleiner Schönheitsfehler in Step-Beschreibung.

Hono-Korrektheit (#30, #35):

  • apps/api/src/app.ts:86 ruft createErrorHandler({...}) — verifiziert (app.onError(createErrorHandler()) an Z. 86). OK.
  • Hono-Tracing-Middleware-Approach (Step 5) — korrekt, da Sentry kein offizielles Hono-Integrationspaket hat. c.req.routePath für Route-Pattern (#35 Lessons Learned erwähnt) — korrekt.

BullMQ-Korrektheit (#30):

  • Step 9 erwähnt Sentry.bunIntegration als BullMQ-Integration — das ist falsch. bunIntegration ist die Bun-Runtime-Integration, nicht BullMQ. Sentry v8 hat keine offizielle BullMQ-Integration (Stand 2026-05). Der Step relativiert das mit "oder manuelle BullMQ-Hooks falls nicht offiziell" — der manuelle Wrapper-Approach in Step 9 ist der richtige Weg.
  • Finding F-4 (Minor): Falsche API-Namens-Referenz Sentry.bunIntegration muss raus oder als "Platzhalter, prüfen ob bullMQIntegration existiert; sonst manueller Wrapper" gekennzeichnet werden. Empfehlung: Step 9 vor Implementation um Explore-Subagent-Hinweis ergänzen: "Prüfe @sentry/node v8.x changelog auf BullMQ-Integration; falls nicht vorhanden, manuellen Wrapper aus diesem Step nutzen".

Sentry-SDK-Korrektheit (#30, #31):

  • httpIntegration, prismaIntegration({ client: prisma }), requestDataIntegration({ include: { ip: false, ... } }) — alle gültige Sentry-v8-Integrations. OK.
  • replayIntegration({ maskAllText: false, maskAllInputs: true }) — gültig. OK.
  • browserTracingIntegration() — gültig. OK.

Prisma-Korrektheit (#33):

  • Step 2 PII-Scrubber: db.statement Param-Bindings strippen — Prisma's OTel-Integration setzt db.statement ohne Param-Values (Default), aber defense-in-depth-Scrubbing ist korrekt.

4. Test-Requirements-Verifizierbarkeit

Task Unit Integration E2E Coverage-Target Verifizierbar?
#29 N/A (Infra) smoke.sh manual staging N/A OK
#30 sanitize, sentry-bootstrap, hono-mw, runtime In-Memory-Sentry-Transport manual staging ≥90%/≥80% OK
#31 sentry-client/server, routeTracing SSR-render Playwright /__test/client-throw ≥80% OK
#32 sentry-release.sh (bats) test-workflow workflow_dispatch manual CI-run N/A OK
#33 pii-span-processor, otel-bootstrap mock-OTLP-endpoint manual E2E-trace 4-spans ≥85%/≥70% OK
#34 PII-mock-tests pro Service, eslint-rule-test pre-commit-hook staging-log-inspection N/A (Migration) OK
#35 registry/auth/middleware/scheduler in-process API prom-targets + grafana-live ≥80%/≥70% OK
#36 pro Item-Fix regression (existing) oha-load-test nicht senken OK

Spezifisch zu den User-Fragen:

  • Sentry-Tests verifizierbar? Ja — In-Memory-Transport (#30 Test-Reqs erwähnt @sentry/core testkit explizit) plus Staging-Smoke. Korrekt.
  • OTel-Spans testen? Ja — Mock-OTLP-Endpoint in Vitest-Suite (#33 Test-Reqs) + End-to-End-Trace-Verifikation auf Staging (Trace-ID-Korrelation über 4 Services). Korrekt.
  • Pino-Redaction testen? Ja — webLogger-Mock-Spy mit assertNotCalled für PII-Keys (#34 Test-Reqs). Korrekt. Zusatz-Hinweis: ESLint-Rule selbst wird mit synthetischem Source-File + ESLint-API getestet — sauber.

Finding F-5 (Minor): #34 definiert keine konkrete Coverage-%-Zahl ("keine harte %-Zahl") — das ist akzeptabel für eine Migration-Task, aber die "Pflicht: Tests für die 5 High-PII-Services" ist eine implizite Coverage-Zusage und sollte als hartes Akzeptanz-Item bleiben (ist es bereits in Acceptance Criteria). OK.


5. Acceptance-Criteria-Verifizierbarkeit

Alle 8 Files haben Acceptance-Criteria mit:

  • Konkreten Datei-Existenz-Checks (infra/sentry/..., packages/metrics/...)
  • Endpoint-Behaviors (/status → 200/503, /metrics → 401/200)
  • Staging-Verifikation (Test-Event in Sentry-UI, Trace mit N Spans, Dashboard-Live-Daten)
  • Lint+Typecheck+Test-Gates

Objektiv prüfbar: Ja. Alle Criteria sind entweder Datei-Existenz, Endpoint-Response, Lint-Output oder UI-Sichtbarkeit. Kein "schöner Code"-Subjektiv-Kriterium.

Finding F-6 (Minor): #35 AC "Cardinality-Schutz aktiv (tenant_id-Bucketing dokumentiert)" ist etwas weich. Schärfer wäre: "Prom-Query count by (__name__)({__name__=~\"ai_.*\"}) liefert < 1000 Series auf Staging". Aber als Doku-Anforderung mit Verweis auf Approach-Section-Decision-Punkt (top-50 + other ab 1000 tenants) noch akzeptabel.


6. Staging-Deployment-Steps (Sentry-Selfhost auf Hetzner+Coolify)

6.1 Sizing-Empfehlungen — vorhanden?

Ja, in #29 Approach-Section:

  • "16 GB RAM empfohlen (12 GB hartes Minimum, Clickhouse + Kafka sind RAM-hungrig)"
  • "4 vCPU empfohlen"
  • "~50 GB Disk für 90 Tage Event-Retention"
  • "~10 Container" mit Liste

Plus GlitchTip-Alternative für 8-GB-Server in sentry-glitchtip-alternative.md dokumentiert (Step 10).

OK.

6.2 Backup-Restore-Drills — vorhanden?

Backup-Steps vorhanden (#29 Step 7: täglicher Cron-Container, postgres-dump + clickhouse-snapshot → S3, SENTRY_SECRET_KEY notieren).

Restore-Drill: AC enthält "docs/observability/sentry-selfhost.md enthält: Deploy-Schritte, Update-Strategie, Backup/Restore-Drill, Hardening-Checkliste, Ressourcen-Anforderungen". Step 8 dokumentiert Updates aber nicht explizit Restore.

Finding F-7 (Minor — actionable): Im Implementation-Step 8 oder neuem Step 8a sollte ein expliziter Punkt "Restore-Drill dokumentieren + auf Staging einmalig durchspielen" stehen. Aktuell ist es nur in AC erwähnt, ohne Implementation-Step. Fix: Step 8 erweitern um Bullet "Restore-Drill: Postgres-Dump auf parallelem Compose-Stack importieren, Clickhouse-Snapshot wiederherstellen, Login + 1 Test-Issue prüfen — Verfahren in Doku-File ergänzen".

6.3 Vollständigkeit Coolify-Deployment

Step-by-Step für Coolify-UI-Anlegen (#29 Staging-Deployment Step 2) ist konkret: Repo, Compose-Path, Domain, Env-Vars aus Vault. OK.

install.sh-Wrapper läuft beim ersten Deployment automatisch → Admin-User-Setup. OK.

Smoke-Tests sind konkret mit sentry shell -c "...", sentry-cli send-event, curl OTLP-Endpoint — verifizierbar.

OK.


7. Konsistenz mit User-Wünschen

7.1 "Sentry Selfhost und alles einbinden" — alle 3 Runtimes abgedeckt?

Runtime Init-Modul Reporter Tracing E2E-Verifikation
apps/api apps/api/src/sentry.ts (#30 Step 3) apiErrorReporter (Step 4) Hono-MW (Step 5-6) + Prisma-Auto Smoke #30 Step 5
apps/worker apps/worker/src/sentry.ts (#30 Step 7) workerErrorReporter (Step 8) BullMQ-Wrapper (Step 9) + Prisma-Auto Smoke #30 Step 5
apps/web (client) apps/web/app/sentry.client.ts (#31 Step 2) n/a (Sentry-API direkt) Browser-Tracing + Route-Tracing (Step 7) Playwright + manual
apps/web (SSR) apps/web/app/sentry.server.ts (#31 Step 4) webErrorReporter (Step 4) requestDataIntegration Manual SSR-throw

Verdict: Alle 3 Runtimes (4 Wiring-Punkte) abgedeckt. OK.

7.2 "Full Auto-Instrumentation mit Sentry-OTLP-Backend" — korrekt?

  • @opentelemetry/auto-instrumentations-node als Meta-Package (HTTP/fetch/Prisma/BullMQ/Redis/fs/dns/net) — korrekt für Full-Auto-Instrumentation (#33 Step 1).
  • fs-Instrumentation explizit disabled (Step 3: "'@opentelemetry/instrumentation-fs': { enabled: false } /* zu noisy */") — sinnvoller Default.
  • Sentry-Relay als OTLP-Ingestor: konfiguriert in infra/sentry/relay/config.yml mit relay.ingest.otlp.enabled: true, max_payload_size: 5MiB (#33 Step 10).
  • Cross-Verifikation mit #29 Step 6: "OTLP-Ingest aktivieren — relay/config.yml so anpassen, dass Relay einen OTLP-HTTP-Endpoint (/api/{project}/integration/otlp/v1/traces) annimmt" — konsistent. OK. Update 2026-05-18: Sentry-Relay 25.x bietet OTLP-Ingest bereits out-of-the-box auf dem /integration/otlp/-Pfad an (keine config-Anpassung nötig); B-005 war ein Pfad-Mismatch, kein Relay-Bug.

Finding F-8 (Minor — Verifikations-Hinweis): Sentry-Relay OTLP-Ingest ist Beta-Feature (Stand Anfang 2026). Der Explore-Subagent-Hinweis im Subagent Recommendations (#33: "Sentry-Relay OTLP-Ingest-Config Stand 2026-05, gibt es Rate-Limits") greift das auf — gut. Empfehlung: Vor Implementation Decision-Punkt dokumentieren: "Falls OTLP-Ingest in v25.x noch nicht stabil → Fallback auf Jaeger/Tempo (Doku in docs/observability/otel.md als Alt-Exporter bereits vorgesehen)".

7.3 "no-console: error für alle server-side Code" — Erstphase Migration + Zweitphase ESLint klar getrennt?

#34 ist explizit in zwei Phasen geteilt:

  • Phase 1 — Aufräumen (manuelle Migration) — Steps 1-13
  • Phase 2 — Enforce (ESLint-Rule) — Steps 14-17

Reihenfolge ist korrekt: erst migrieren, dann Rule aktivieren (sonst würde Rule den eigenen Migration-Commit blocken). OK.

Override-Strategie:

  • Server-Code (**/*.server.ts(x), apps/api/src/**, apps/worker/src/**, packages/**/src/**) → error
  • Test-Files → off
  • Client-Bundle (apps/web/app/components/**, apps/web/app/routes/** ohne .server.) → off (Browser-Konsole legitim)

OK.

Finding F-9 (Pfad-Korrektur): Die im #34 erwähnten High-PII-Files-Pfade sind teilweise falsch:

In Detail-MD Tatsächlicher Pfad im Repo
apps/web/app/utils/services/.server/authService.ts:99 apps/web/app/utils/services/authService.ts (kein .server-Subdir, 0 console-Calls beim Stichproben-grep)
apps/web/app/utils/services/.server/EmailService.ts:29 apps/web/app/modules/emails/services/EmailService.ts (Pfad in modules/emails/, console-Call bestätigt: EmailService.ts:29 + :44)
apps/web/app/utils/services/.server/CrmService.ts:433/445 apps/web/app/modules/crm/services/CrmService.ts (Pfad in modules/crm/, console-Calls bestätigt: :393, :421, :437, :449, :571-604)
apps/web/app/utils/services/.server/PromptBuilderService.ts:185/256 apps/web/app/modules/promptBuilder/services/.server/PromptBuilderService.ts (Pfad in modules/promptBuilder/services/.server/, console-Calls bestätigt)
apps/web/app/utils/services/.server/SeedService.ts:199-217 apps/web/app/utils/db/seed/SeedService.ts (Pfad in utils/db/seed/, nicht in services/.server/)

Fix vor Implementation: Detail-MD Step 2-6 mit korrekten Pfaden updaten. Sonst greift ein Subagent ins Leere. Konkret: Inventar-Script aus Step 1 zuerst laufen lassen, das wird die Pfade automatisch korrigieren — Empfehlung an ausführenden Agent: Step 1 strikt vor Step 2 fertigstellen und Inventar als Source-of-Truth für die Reihenfolge nehmen (nicht die hier vorgeschlagenen statischen Pfade).

7.4 "/status + Prometheus + Grafana mit Business-Metriken" — Business-Metrics abgedeckt?

Final-Liste in #35 Approach-Section "Business":

  • active_tenants ✓
  • active_users_24h ✓
  • ai_tokens_consumed_total{provider, model, tenant_id} ✓ (mit Cardinality-Bucketing-Decision)
  • stripe_webhook_events_total{event_type, status} ✓
  • mail_sent_total{provider, status} ✓
  • webhook_delivery_attempts_total{status} ✓
  • csrf_token_rotation_total ✓
  • subscription_active{plan_id} ✓

User-Wunsch explizit gefordert: active_tenants, ai_tokens, stripe_webhook_events — alle drei abgedeckt + zusätzlich Mail, Webhook-Delivery, CSRF-Rotation, Subscriptions. OK.

Instrumentierung als Implementation-Steps separiert (Step 10 AI-Cost, Step 11 Stripe, Step 12 Mail, Step 13 Webhook-Delivery) mit je einem atomic Commit. OK.

5 Grafana-Dashboards (Overview, API-Latency, Queue-Health, Business-KPI, AI-Cost-per-Tenant) — sinnvolle Aufteilung, deckt User-Wunsch ab.

OK.


8. Performance-Quickwins — Alle 8 Items mit file:line?

# Item Datei Line Datei existiert?
1 N+1 Users-Admin apps/web/app/routes/admin/accounts/users.tsx 119-129 ✓ existiert
2 currentTenant Doppel-Fetch apps/web/app/utils/data/.server/rootData.ts 30 ✓ existiert
3 Storage Signed-URL-Cache apps/api/src/storage.ts 56-80, 82-131 ✓ existiert
4 clearSubscriptionsCache Thrash apps/web/app/utils/services/.server/subscriptionService.ts 543-548 ✓ existiert
5 CSRF Body-Clone apps/web/app/utils/session.server.ts 230-268 ✓ existiert
6 Recovery-Code Rejection-Sampling apps/web/app/utils/auth/mfa/recovery-codes.server.ts 80-83 ✓ existiert
7 UUID-Collision-Check apps/api/src/auth/session/session-store.ts 47-61 ✓ existiert
8 CSRF-Token 100 → 32 Bytes apps/web/app/utils/session.server.ts 212-219 ✓ existiert

Alle 8 Items mit konkretem file:line + Problem-Description + Fix-Approach + Tests. Item 8 hat zusätzlich Rollback-Warnung (bestehende Sessions mit 100-Byte-Token) und Migration-Hinweis (beide Längen akzeptieren bis TTL ablauf). Sehr gründlich. OK.

Finding F-10 (Optional): Item 8 könnte vor Implementation in eigenen Folge-Task ausgegliedert werden (siehe Item-8-Subagent-Hinweis), falls Session-TTL > 24h ist. Die Detail-MD adressiert das bereits in Rollback-Strategy + Subagent-Plan-Hinweis. OK.


9. Phase-Reihenfolge (intern)

  • #29 Sentry-Setup zuerst ✓ (Voraussetzung für DSNs)
  • #30 / #31 parallel danach ✓ (unterschiedliche Apps, kein File-Konflikt)
  • #32 nach #30+#31 ✓ (CI-Release-Tagging braucht Wiring)
  • #33 OTel "später" ✓ (kann theoretisch parallel zu #34/#35, README ordnet sie parallel ein — OK weil #33 keinen #32-Block deklariert; OTel-Backend = Sentry-Relay aus #29, also nur #29 ist harte Voraussetzung)
  • #34 logging-migration parallel zu #33/#35 ✓
  • #35 metrics-grafana parallel zu #33/#34 ✓
  • #36 perf-quickwins zuletzt ✓ (braucht #35 zum Messen)

OTel nutzt Sentry-Relay als Backend — bestätigt:

  • #29 Step 6 aktiviert OTLP-Ingest in Relay
  • #33 Step 10 verifiziert Relay-Config (idempotent zu #29 Step 6 — saubere Defense-in-Depth)
  • #33 Default-Exporter zielt auf https://sentry.<domain>/api/<project_id>/otlp

Reihenfolge ist korrekt. OK.


10. Fehlende Aspekte (Critical Gaps)

10.1 Geprüft — vorhanden ✓

  • DSGVO/PII-Schutz (in #30 beforeSend, #31 Replay-Masking, #33 PII-Span-Processor, #34 Pino-Redaction)
  • Rollback-Strategie pro Task
  • Security Notes pro Task
  • Cardinality-Schutz (#35)
  • Self-Host vs SaaS-Entscheidung dokumentiert + Alternative (GlitchTip)
  • TLS via Coolify-Traefik
  • 2FA für Sentry-Admin
  • Secret-Rotation (CI-Token, METRICS_TOKEN)
  • Token-minimal-Scope (project:releases)
  • Source-Maps werden gelöscht nach Upload (filesToDeleteAfterUpload)
  • Sample-Rates env-konfigurierbar
  • No-Op-Verhalten ohne DSN/Endpoint/Token

10.2 Fehlend / Verbesserungswürdig

Finding F-11 (Minor — Suggestion): Alerting ist nicht thematisiert. Phase 02 baut Metriken + Sentry, aber wer wird benachrichtigt wenn queue_jobs_failed_total spike oder stripe_webhook_events_total{status="failed"} > threshold? Empfehlung:

  • In #35 metrics-grafana.md Acceptance-Criteria ergänzen: "Mindestens 1 Grafana-Alert-Rule definiert (z.B. up == 0 for 2m für API/Worker/Web) mit Notification-Channel (Email oder Webhook)".
  • Optional: Sentry-Alerts (Issue-Frequency-Threshold) in #29 oder #30 AC ergänzen.

Finding F-12 (Minor — Suggestion): Log-Aggregation (Loki o.ä.) ist nicht eingeplant. Pino schreibt JSON in stdout, Coolify aggregiert in Container-Logs — aber kein zentraler queryable Store. Phase-02 erwähnt es nur am Rand ("Loki/Grafana"). Für 10/10-Boilerplate wäre infra/loki/ mit Promtail-Sidecar sinnvoll. Empfehlung: Entweder in Phase 02 hinzufügen (eigener loki-stack.md-Task) oder in 11-backlog/ aufnehmen mit Begründung "Pino-JSON in Coolify-Container-Logs reicht für MVP".

Finding F-13 (Minor — Suggestion): Sentry-Sentry-Heartbeat / Dead-Man-Switch für den Sentry-Self-Host selbst nicht behandelt. Wenn Sentry down ist, weiß niemand davon. Empfehlung in #29 AC ergänzen: "Externer Uptime-Check (z.B. UptimeKuma in separatem Stack) prüft https://sentry.<domain>/_health/ alle 5 Min, alarmiert via Email bei Down".

Finding F-14 (Cosmetic): Web-Side OTel-Bootstrap in #33 Steps 7-9 erwähnt Browser+SSR getrennt, was korrekt ist, aber das Service-Naming-Schema sollte sauberer differenziert sein: boilerplate-web-client vs boilerplate-web-ssr. Aktuell beide unter boilerplate-web → in Traces nicht unterscheidbar. Empfehlung: Resource-Attribute-Liste in Approach-Section anpassen oder in Step 7/9 explizit dokumentieren.

Finding F-15 (Nice-to-have): Synthetic-Monitoring (z.B. ein Worker-Job alle 5 Min, der einen End-to-End-Flow simuliert und Metriken/Traces emittiert) wird nicht explizit besprochen. Wäre die natürliche Erweiterung von #36 aber out-of-scope für Phase 02. OK to defer.


11. Findings — Zusammenfassung & Priorität

Must-fix vor Implementation (3 Items)

  1. F-3 — #33 Step 9: Import-Pfad ./otel.server vs Dateipfad lib/otel/server.ts konsistent machen.
  2. F-4 — #30 Step 9: Falsche Sentry-API-Referenz Sentry.bunIntegration für BullMQ entfernen; durch "manueller Wrapper (Default-Approach in diesem Step)" ersetzen.
  3. F-9 — #34 Steps 2-6: Pfade der 5 High-PII-Services korrigieren ODER explizit "Pfade sind Beispiele; Inventar aus Step 1 als Source-of-Truth nehmen" hinzufügen.

Should-fix (3 Items)

  1. F-7 — #29 Step 8: Restore-Drill als expliziten Implementation-Step ergänzen (nicht nur AC).
  2. F-8 — #33: OTLP-Ingest-Beta-Status erwähnen + Fallback-Pfad zu Tempo/Jaeger dokumentieren (ist in Doku-Plan, aber als Decision-Punkt im Approach gut sichtbar machen).
  3. F-14 — #33: Web-Service-Naming boilerplate-web-client vs boilerplate-web-ssr differenzieren.

Nice-to-have (4 Items)

  1. F-11 — #35 AC: Mindestens 1 Grafana-Alert-Rule + Notification-Channel.
  2. F-12 — Loki/Promtail-Sidecar als Phase-02-Erweiterung oder in 11-backlog/.
  3. F-13 — #29 AC: Externer Uptime-Check für Sentry-Self-Host.
  4. F-15 — Synthetic-Monitoring als zukünftige Erweiterung dokumentieren.

Reine Beobachtungen (keine Fixes nötig)

  • F-1: Cross-Phase-Block #29 → 09-authentik-setup korrekt deklariert.
  • F-2: #35 bzgl. #36 Symmetrie OK (Depends-on auf #36-Seite reicht).
  • F-5: #34 Coverage-Strategie OK (Migration-Task).
  • F-6: #35 Cardinality-AC etwas weich aber akzeptabel.
  • F-10: #36 Item 8 Risiko bereits in Rollback adressiert.

12. Quantitative Gesamt-Bewertung

Dimension Score (0-10) Begründung
Template-Konformität 10 Alle 8 Files folgen Pflicht-Reihenfolge
Dependency-Korrektheit 9.5 Sauber deklariert, Cross-Phase-Refs gültig
Atomic-Commits-Eignung 9 Steps sind sauber separierbar, einige Bulk-Migrationen pragmatisch zusammengefasst
Tech-Korrektheit 8.5 -1.5 für F-3, F-4 (kleine API-Referenzen)
Test-Verifizierbarkeit 9.5 In-Memory-Transports + Staging-Smoke konkret
AC-Objektivität 9 Wenige weiche Items (Cardinality-Schutz)
Staging-Coverage 9 -1 für fehlenden Restore-Drill-Step (F-7)
User-Wunsch-Abdeckung 9.5 Alles drin; -0.5 für Pfad-Inkonsistenz F-9
Performance-Quickwins-Konkretheit 10 Alle 8 file:line verifiziert, alle Dateien existieren
Phase-Reihenfolge-Sauberkeit 10 Saubere Topologie, parallelisierbar gut markiert
Security-Notes-Tiefe 10 PII, Token-Scopes, Cardinality, Allowlists durchgängig
Gesamtscore 9.3 / 10 Ausführungsreif nach 3 Must-fixes

13. Empfehlung

APPROVED FOR EXECUTION nach Adressierung der 3 Must-fixes (F-3, F-4, F-9). Die 3 Should-fixes können während Implementation adressiert werden (im jeweiligen Step-Subagent-Brief erwähnt). Nice-to-haves sind echte Verbesserungen — wenn Zeit, in Phase 02 mitnehmen, sonst in 11-backlog/ aufnehmen.

Konkrete nächste Schritte für ausführenden Agent:

  1. Vor Phase-02-Start die 3 Must-fixes als kleinen Doku-Commit auf agent/phase-02-prep einarbeiten (5-Minuten-Edit auf den Detail-MDs).
  2. #29 als Solo-Agent-Run starten (3-4d), parallel kann ein anderer Agent bereits #34-Inventar-Script (Step 1) bauen — das ist Pre-Migration-Vorbereitung ohne Wiring-Dependency.
  3. Nach #29 grün: #30 + #31 parallel zwei Agents.
  4. Nach #30+#31 grün: #32 (Solo) + #33/#34/#35 parallel drei Agents starten.
  5. Zuletzt #36 mit #35-Baseline.