meta {
  name: Checkin
  seq: 9
}

docs {
  ## Check-in — endpoints PUBLICS (pas d'auth Bearer)

  Le check-in est l'email envoyé à **l'utilisateur** (pas au client) pour
  confirmer qu'une facture a été payée AVANT que la première relance ne
  parte (cf. CLAUDE.md → Glossaire). Remplace l'intégration banking V1.

  ## Flow

  1. Quand une facture avec un plan est créée, `scheduleCheckinForInvoice`
     enqueue un BullMQ job à `dueDate` (pile à l'échéance).
  2. À l'exécution, `SendCheckinJob` envoie un email à l'user avec 2
     liens : "C'est payé" et "Toujours en attente".
  3. L'user clique → endpoint public ci-dessous → DB update + redirect SPA.

  ## Token

  - 32 bytes random base64url, généré au schedule.
  - Stocké hashé (SHA-256) en DB (CheckinTask.token_hash).
  - TTL 24h après envoi (sentAt + 24h).
  - Une seule réponse possible (idempotent : 2e click → already_answered).

  ## Pourquoi pas d'auth Bearer ?

  L'utilisateur clique depuis sa boîte mail — pas de session JS active.
  Le token est l'authentification : sa connaissance vaut autorisation
  (avec TTL 24h pour limiter la fenêtre de risque).

  ## Pour tester

  Crée une facture avec dueDate dans le passé (Invoices → 04 Create) :
  le check-in est programmé à `now + 1min`. ~1min plus tard, regarde
  Mailpit http://localhost:8025 → tu vois l'email avec les 2 liens.
  Copie le token de l'URL et utilise les requêtes Bruno ci-dessous.
}
