RebreakVpnService.onStartCommand crashed with SecurityException because Android 16's validateForegroundServiceType rejects the implicit 2-arg startForeground(). Now passes FOREGROUND_SERVICE_TYPE_SPECIAL_USE explicitly (Google's documented best practice) and guards the call so a failed foreground promotion stops the service cleanly instead of crashing the app. Verified vs reported Galaxy A54 / Android 16 signature (97% of crash events, 1-user crash loop).
Bundles pending working-tree work across native/marketing/locales/mac + graphify-out rebuild. gitignore: google-services.json + /screenshots/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Devices/Magic:
- Offline-Profil-Enroll deaktiviert (410) — Lock-PW würde im Klartext im
Download landen; stationärer Schutz läuft jetzt nur über Rebreak Magic
- Mac-DNS-Template: ProhibitDisablement (Filter nicht abschaltbar)
- Push "Neues Gerät verbunden" an mobile Geräte bei neuer Bindung
- Realtime auf user_devices → Settings aktualisiert Magic-Bindings live
- Geräte-Detail-Sheet (Tap auf Gerät): Status, verbunden-seit, Schutz-Donut
Hard-Lock (server-gehaltenes Removal-PW, User sieht es nie):
- magic_removal_password generiert/gespeichert + in Profil injiziert (Lazy-Backfill)
- Reveal NUR bei Account-Löschung (user/delete) + Kündigung (stripe webhook),
per Resend-Mail + in-Response
- Signing config-gated (inaktiv ohne Cert; Lock greift auch unsigniert)
Migrations: user_devices-Realtime-Publication + magic_removal_password-Spalten
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- backend: skip Expo alert push to iOS devices that already received VoIP push
(CallKit + banner = double ring)
- native: receiveIncoming no longer triggers InCallManager.startRingtone —
CallKit/ConnectionService play their own ring. Dedup if same callId
arrives twice (Realtime + VoIP-Push race).
MDM-VPN-Pivot (Phase F.2 done):
- ops/mdm/profiles/rebreak-iphone-protection.mobileconfig auf v5 mit
com.apple.vpn.managed Payload + OnDemandUserOverrideDisabled. iPhone-User
kann ReBreak-VPN-Profile nicht entfernen und "Bedarf verbinden"-Toggle
ist disabled. allowEnablingRestrictions empirisch widerlegt für FC-Toggle-
Lock — out.
- DEV-removable Variante als Test-Profile dazu.
- Bootstrap-Tool (rebreak-supervise.sh) + Supervision-Identity-Setup-Doc.
- PHASES.md updated mit empirischen Befunden.
App-side MDM-Detect (Pfad-a Banner-Logic):
- modules/rebreak-protection: getDeviceState() returnt mdmManaged via
Heuristik NETunnelProviderManager.count > 1 (App selbst kann nur einen
eigenen erstellen, MDM-Push fügt einen zweiten hinzu).
- DeviceLayers.mdmManaged?: boolean Type.
- blocker.tsx: lockedIn-Bedingung erweitert um mdmManaged. Bei MDM-managed
iPhones wird der App-Lock-Card (FC-Authorization-Toggle UI) ausgeblendet
weil der per-App FC-Toggle nicht lockbar ist und durch den MDM-VPN-Layer
redundant.
Layer-2-Country-Curated-Pivot:
- backend: vip-swap.post.ts raus, suggest.post.ts rein. Curated-domains
durch admin (separate Tabelle/Pfad), getrennt von User-Custom-Domains.
- Admin-APIs für curated-domain Pflege (index.get + [id].patch).
- seed-country-blocklists Script für initiale Curated-Domain-Liste.
- protection/webcontent-domains.get refactored für Country-Curated-Pfad.
- Migration drop_vip_swap_fields.sql + schema.prisma adjusted.
- docs/concepts/layer2-country-pivot.md mit Architektur + Decision-Trail.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Layer-2-webContent-Filter laeuft jetzt automatisch bei activateFamilyControls/
activate mit (Helper applyWebContentLayer). URLFilterExtension CFBundleVersion/
ShortVersion an die App angeglichen. Apple-DTS-Report einreichfertig.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
free: 5 custom domains (non-refillable), no global blocklist, 1 mail account,
basic coach. pro: global blocklist (the headline), 5 refillable domains, 3 mail
accounts (cron choice, no daemon), better coach. legend: + IMAP-IDLE daemon
(real-time mail scan — app highlight), 10 refillable domains with ≤24h ReBreak
validation, much better coach, +2 device DNS profiles. Marketing critique (§7)
pending from strategist.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Infisical staging holds the bot user IDs as NUXT_LYRA_BOT_USER_ID /
NUXT_REBREAK_BOT_USER_ID, but nitro.config.ts reads process.env.LYRA_BOT_USER_ID
(no NUXT_ fallback) and start-staging.sh had no alias for them → config.lyraBotUserId
was empty → POST /api/admin/lyra-post threw 500 "LYRA_BOT_USER_ID nicht
konfiguriert" (surfaced via the admin app proxy). Adds the alias + NITRO_ override
exports, same pattern as the other keys.
Also: ops/strategy/pricing-tiers.md — strategist's tier-pricing analysis,
stress-test, downgrade-policy matrix, plan-change briefing-screen content +
scenario test matrix (Task #8 Phase 1).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CX23 (4GB RAM) OOM'd am 2026-05-06 während webhook-getriggertem `pnpm build`
(Heap-Limit 1.5GB überschritten). Build raus aus Server, GitHub-Runner (7GB RAM)
übernimmt — Server deployed nur noch Artifact via scp + atomic-mv + pm2 restart.
- .github/workflows/deploy-staging.yml: 2-Job (build + deploy via SSH-Artifact-Push)
- scripts/deploy-from-artifact.sh: Server-Script mit Migration-Detection + atomic-mv
- ops/GITHUB_ACTIONS_PIPELINE.md: Architektur-Doku + Cheatsheet
Coexistence: alter rebreak-webhook bleibt als Failsafe, wird nach 5+ erfolgreichen
GA-Runs deaktiviert. Erster Run: Webhook temporär gestoppt für sauberen Test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase-1-Vorbereitung für den Rebreak-Cutover (apps/rebreak Nuxt → backend
standalone Nitro). Alle Änderungen sind lokal verifiziert (build = 9.66 MB
gzipped 3.08 MB, node .output/server/index.mjs startet ohne ERR_MODULE_NOT_FOUND
auf :3000). Kein Push, kein Server-Eingriff in dieser Session.
Inhalt:
- backend/nitro.config.ts: 8 zusätzliche runtimeConfig-Keys (cartesia*, eleven*,
supabaseUrl/AnonKey/ServiceKey, public.supabase.{url,key}). Schließt den
Auth-500-Cascade vom 2026-05-06 (server/utils/auth.ts:32 liest
config.public.supabase ?? config.supabase — beide Pfade jetzt deklariert).
- .npmrc (NEU, root-level): node-linker=hoisted für Prisma 7 transitive
@prisma/client-runtime-utils (siehe feedback_backend_runtime_config.md).
- backend/start-staging.sh: Pfad korrigiert von /srv/rebreak-monorepo/...
→ /srv/rebreak/backend/.output-staging/server/index.mjs. infisical run
wrapper (kein NUXT_*-Mapping mehr — runtimeConfig liest process.env.X
direkt). IMAP-Services entfernt (sind Mo's Scope, separat in ecosystem).
- scripts/deploy.sh (NEU): adaptiert von /srv/rebreak/scripts/deploy.sh
für backend/-Layout. APP_DIR=backend, pnpm --filter rebreak-backend build,
.output → .output-staging atomic-move bleibt erhalten, pm2 restart
--update-env zieht neue Infisical-Secrets.
- scripts/deploy-webhook/server.mjs (NEU): 1:1-Kopie vom Server, damit
ecosystem.config.js auf die Repo-Version zeigen kann.
- ecosystem.config.js (NEU, root-level): rebreak-staging zeigt auf
backend/start-staging.sh, rebreak-webhook zeigt auf scripts/deploy-webhook.
rebreak-prod + dns-* sind kommentiert (folgen in späterer Phase).
- ops/CUTOVER_PLAN.md: Plan-Doku vom 2026-05-06 (yesterday's work).
- .gitignore: .claude/ und xgit ergänzt (lokale Agent-State, nicht versioniert).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mein vorheriger Push hatte ältere ops/nginx/-Versionen aus dem rebreak-monorepo.
Server hatte ACME-Challenge, security-Headers (HSTS, X-Frame-Options, X-XSS),
separate /webhook Location, X-Robots-Tag — alles war im Repo nicht drin.
Geänderte/neue files:
- staging.rebreak.org.conf — full version mit ACME + security
- db-staging.rebreak.org.conf — minimal diff
- default.conf — NEU
- rebreak-staging-new.conf — NEU
Live nginx selbst war nicht betroffen (nginx -t ok), Repo-Sources jetzt
auf Live-Stand synchronisiert.