` (vor Zeile 132).
+
+## Shared Patterns
+
+### Tenant-Context Extraction
+**Source:** `apps/api/src/module-registry/module-registry.controller.ts` Zeilen 48-53
+**Apply to:** Alle Backend-Controller (dashboard.controller.ts, calendar.controller.ts)
+```typescript
+const tenantId = (req as any).tenantId ?? (req as any).user?.tenantId;
+if (!tenantId) {
+ throw new ForbiddenException('No tenant context');
+}
+```
+
+### User-Context Extraction (neu fuer Dashboard)
+**Source:** Abgeleitet aus Auth-Pattern
+**Apply to:** Alle Dashboard/Calendar-Endpoints (user-scoped, nicht tenant-scoped)
+```typescript
+const userId = (req as any).user?.id;
+const tenantId = (req as any).tenantId ?? (req as any).user?.tenantId;
+```
+
+### API Fetch Pattern (Frontend)
+**Source:** `apps/web/src/components/layout/header.tsx` Zeile 21 (fetchCurrentUser)
+**Apply to:** Dashboard-Store, Widget-Komponenten, Settings-Seiten
+```typescript
+// Alle API-Calls nutzen credentials: 'include' fuer Cookie-Auth
+await fetch('/api/dashboard/layout', {
+ credentials: 'include',
+});
+```
+
+### i18n Pattern
+**Source:** `apps/web/src/app/(portal)/page.tsx` Zeilen 1-6
+**Apply to:** Alle Frontend-Komponenten
+```typescript
+'use client';
+import { useTranslations } from 'next-intl';
+const t = useTranslations('dashboard');
+// Verwendung: {t('empty')}, {t('addWidget')}
+```
+
+### Tailwind UI Pattern
+**Source:** `apps/web/src/components/layout/header.tsx`
+**Apply to:** Alle neuen Komponenten
+- Farben: `bg-muted`, `text-muted-foreground`, `bg-primary`, `text-primary-foreground`, `border-border`, `bg-card`, `text-foreground`
+- Hover: `hover:bg-muted`, `hover:opacity-90`, `transition-colors`
+- Layout: `flex`, `items-center`, `gap-2`, `rounded-md`, `px-4 py-2`
+
+## No Analog Found
+
+| File | Role | Data Flow | Reason |
+|------|------|-----------|--------|
+| `apps/api/src/calendar/providers/caldav.provider.ts` | service | request-response | Kein externer API-Client-Pattern im Projekt. RESEARCH.md Pattern (tsdav) verwenden |
+| `apps/api/src/calendar/providers/ics.provider.ts` | service | request-response | Kein HTTP-Fetch + Parse Pattern. RESEARCH.md Pattern (node-ical) verwenden |
+| `apps/api/src/calendar/providers/exchange.provider.ts` | service | request-response | Kein EWS/Graph Pattern. RESEARCH.md Pattern verwenden |
+| `apps/web/src/components/dashboard/dashboard-grid.tsx` | component | event-driven | react-grid-layout ist neu im Projekt. RESEARCH.md Code-Beispiel verwenden |
+| `apps/web/src/components/dashboard/widget-catalog-modal.tsx` | component | event-driven | Kein Modal-Pattern im Projekt. shadcn/ui Dialog verwenden |
+| `apps/web/src/components/dashboard/widgets/*.tsx` | component | event-driven | Widget-Komponenten sind neues Pattern. RESEARCH.md WidgetProps Interface verwenden |
+
+## Metadata
+
+**Analog search scope:** `apps/api/src/`, `apps/web/src/`
+**Files scanned:** ~60
+**Pattern extraction date:** 2026-06-23
diff --git a/.planning/phases/05-dashboard-calendar/05-VALIDATION.md b/.planning/phases/05-dashboard-calendar/05-VALIDATION.md
new file mode 100644
index 0000000..7329d59
--- /dev/null
+++ b/.planning/phases/05-dashboard-calendar/05-VALIDATION.md
@@ -0,0 +1,77 @@
+---
+phase: 05
+slug: dashboard-calendar
+status: draft
+nyquist_compliant: false
+wave_0_complete: false
+created: 2026-06-23
+---
+
+# Phase 05 — Validation Strategy
+
+> Per-phase validation contract for feedback sampling during execution.
+
+---
+
+## Test Infrastructure
+
+| Property | Value |
+|----------|-------|
+| **Framework** | vitest |
+| **Config file** | apps/web/vitest.config.ts |
+| **Quick run command** | `pnpm --filter web test --run` |
+| **Full suite command** | `pnpm --filter web test --run && pnpm --filter api test --run` |
+| **Estimated runtime** | ~30 seconds |
+
+---
+
+## Sampling Rate
+
+- **After every task commit:** Run `pnpm --filter web test --run`
+- **After every plan wave:** Run `pnpm --filter web test --run && pnpm --filter api test --run`
+- **Before `/gsd-verify-work`:** Full suite must be green
+- **Max feedback latency:** 30 seconds
+
+---
+
+## Per-Task Verification Map
+
+| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
+|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
+| *Populated during planning* | | | | | | | | | ⬜ pending |
+
+*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
+
+---
+
+## Wave 0 Requirements
+
+- [ ] react-grid-layout installation and type stubs
+- [ ] Markdown editor library installation
+- [ ] Calendar library installations (tsdav, node-ical)
+- [ ] Dashboard API test stubs
+- [ ] Calendar source API test stubs
+
+---
+
+## Manual-Only Verifications
+
+| Behavior | Requirement | Why Manual | Test Instructions |
+|----------|-------------|------------|-------------------|
+| Drag & drop widget rearrangement | DASH-01 | Visual interaction | Open dashboard, enter edit mode, drag widget to new position |
+| Widget resize | DASH-02 | Visual interaction | Enter edit mode, resize widget via drag handle |
+| Calendar events display | CAL-03 | External service | Configure calendar source, verify events appear |
+| Responsive grid scaling | DASH-03 | Visual breakpoints | Resize browser window, verify grid scales proportionally |
+
+---
+
+## Validation Sign-Off
+
+- [ ] All tasks have `
` verify or Wave 0 dependencies
+- [ ] Sampling continuity: no 3 consecutive tasks without automated verify
+- [ ] Wave 0 covers all MISSING references
+- [ ] No watch-mode flags
+- [ ] Feedback latency < 30s
+- [ ] `nyquist_compliant: true` set in frontmatter
+
+**Approval:** pending