chahinebrini a95e66560d feat(magic): Hard-Lock + Geräte-UX (Push, Realtime, Detail-Sheet, Offline-Removal)
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>
2026-06-07 22:26:25 +02:00

35 lines
1016 B
TypeScript

import { findMagicDeviceByToken } from "../../db/devices";
/**
* GET /api/magic/status?token=<dnsToken>
*
* KEIN auth required — Token selbst ist das Secret (64-char hex).
*
* Polling-Endpoint für den Windows-Tamper-Service (rebreak-magic-win):
* Service prüft alle 5 Minuten ob das Binding noch aktiv ist.
* - active=true → DoH-Schutz muss aktiv sein (bei Manipulation re-applien)
* - active=false → Release-Cooldown abgelaufen, Token revoked → Teardown erlaubt
*
* Offline-Verhalten ist Client-Sache: kein Response → fail-closed (Schutz bleibt).
*/
export default defineEventHandler(async (event) => {
const query = getQuery(event);
const token = query.token as string | undefined;
if (!token || !/^[0-9a-f]{64}$/.test(token)) {
throw createError({
statusCode: 400,
message: "token query parameter required",
});
}
const device = await findMagicDeviceByToken(token);
return {
success: true,
data: {
active: device !== null,
},
};
});