6 Commits

Author SHA1 Message Date
chahinebrini
5434254f74 feat(auth,mail): pw-reset OTP-flow + custom mail templates + account-switch cleanup
- Phase 3 PW-Reset: 3 screens (forgot-password → reset-otp → new-password),
  verifyOtp({type:'recovery'}), new updatePassword() action
- Custom Brevo-Mail templates (backend/public/templates/) — 5 HTMLs with
  go-template i18n (de/en/fr/ar incl. RTL for AR), OTP-only (no link),
  ReBreak branding
- signUp metadata.data.locale aus i18n.language → templates resolven Sprache
- Account-Switch-Bug fix: signOut() resettet alle 10 user-spezifischen stores
  + invalidateMe()
2026-05-19 10:49:23 +02:00
chahinebrini
8851f36f65 fix(native): protectedDevices store — unwrap response shape
Backend GET /api/devices/protected returns:
  { success, data: { devices, plan, max, isLegend } }

apiFetch already unwraps `data`, leaving us with the object
{ devices, plan, max, isLegend } — not an array.

Old code did `Array.isArray(res) ? res : []` on that object, which
silently fell through to an empty list. Effect: enrolled protected
devices (Mac/Windows) never appeared in the Geräte screen even though
the DB row existed and the API responded correctly.

Fix: read res.devices instead of assuming the response is the array.
2026-05-15 23:02:26 +02:00
chahinebrini
a0d67f33a8 feat(native): realtime debug page + protected-devices array guard
- stores/realtimeDebug.ts: neuer DEV-only Zustand-Store mit connection-state,
  reconnect-counter, token-expiry-countdown, channel-liste, rolling log-buffer
  (last 100 events). Hookt Phoenix-Socket open/close/reconnect + Channel-subscribe.
- _layout.tsx: initRealtimeDebug() im __DEV__-Block beim App-Start.
- debug.tsx: zwei neue Cards (RealtimeStatusCard + RealtimeLogCard) mit
  1s-Tick-Refresh, Copy + Clear Buttons. Settings-Entry 'Realtime connection (DEV)'.
- protectedDevices.ts: Array.isArray-Guard für apiFetch-Response — verhindert
  TypeError 'devices.filter is not a function' wenn Backend Non-Array zurückgibt.

Diagnostik-Tool für Realtime-Disconnect-Bug bei lange eingeloggten Usern.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 22:15:57 +02:00
chahinebrini
51697c3aa4 feat(tier): plan-change briefing sheet + over-limit cards (Phase 2 UI)
- components/plan/PlanChangeSheet.tsx — upgrade/downgrade briefing per pricing-tiers.md §4
  (fetches GET /api/plan/change-preview; gains/keeps/changes; recovery-safety line;
  billing hint w/o purchase button; CTA row, no 'are you sure?' interstitial)
- debug.tsx: PlanOverrideToggle routes every flip through PlanChangeSheet first
- devices.tsx + protectedDevices.ts: 'degraded' status (red, inline 'protection expired —
  remove the profile yourself' hint, no green checkmark); maxProtectedDevices limit hint
- mail.tsx + MailAccountCard.tsx + useMailStatus.ts: over-limit banner + paused-account
  greyed-out + PausedBadge (all defensive — only shows if backend sends the  field)
- blocker.tsx: free-tier transparency hint ('Grundschutz aktiv — voller Schutz: Pro/Legend')
  + custom-domain over-limit banner
- locales: plan.change.* + plan_limit.* (de + en)

tsc clean. Backend side (GET /api/plan/change-preview, paused/degraded fields) in progress
in parallel — UI built defensively to work before it lands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:21:47 +02:00
chahinebrini
dd3d8c6667 feat(devices): wire Windows DoH AddWindowsSheet into devices screen
- AddWindowsSheet: 5-step Lyra flow (download → datei → shield-check → wifi → done)
- devices.tsx: Windows button enabled, opens AddWindowsSheet
- protectedDevices store: enroll() takes platform 'mac' | 'windows'
- AddMacSheet: pass 'mac' to enroll()

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 13:44:41 +02:00
chahinebrini
6700391eed feat(devices): Settings → Geräte UI + AddMacSheet 3-step Lyra flow
Frontend:
- New devices.tsx: section 'this device' + 'protected devices' + Legend CTA
- AddMacSheet: label → Lyra-onboarding (4 steps) → success
- protectedDevices store (Zustand): load, enroll, confirmInstalled, remove
- Locale strings DE + EN (devices namespace, 36 keys each)
- Path-fix: /api/devices/protected (was /api/devices) + /api/devices/:id/revoke

Free/Pro see upgrade-CTA, Legend see add-Mac. Windows button shown disabled (soon).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 04:06:49 +02:00