karbe/src/app/api
Ubuntu a6ea488732
All checks were successful
CI / test (pull_request) Successful in 2m45s
feat(prod): Sprint Q — reminders J-1 + cleanup cron endpoints
Endpoints automatisables par cron externe (Hermes, GitHub Actions,
ou crontab système) pour gérer les tâches récurrentes de la
plateforme.

src/lib/cron-auth.ts (NEW) : isAuthorizedCronRequest(req) vérifie
l'en-tête Authorization Bearer ${CRON_TOKEN}. Le token est déjà dans
.env.production.

GET /api/cron/reminders :
- Itère bookings carbet CONFIRMED + rentalBookings CONFIRMED dont
  startDate ∈ [now+22h, now+26h] (fenêtre 4h pour absorber les
  éventuels retards de cron).
- Envoie sendBookingReminder (carbet) ou sendRentalReminder (rental).
- Compte bookingSent/bookingErrors et rentalSent/rentalErrors.
- Audit log scope=cron event=cron.reminders.run avec stats.
- Retourne JSON {ok, window, booking:{candidates,sent,errors},
  rental:{candidates,sent,errors}}.

GET /api/cron/cleanup :
- Purge OrgInviteToken expirés depuis > 30j.
- Booking PENDING + paymentStatus≠SUCCEEDED + createdAt > 7j →
  status=CANCELLED + paymentStatus=FAILED (libère le créneau).
- RentalBooking idem + delete RentalItemAvailability associée
  (libère stock) en transaction.
- Audit log scope=cron event=cron.cleanup.run avec compteurs.

src/lib/email.ts :
- sendBookingReminder(to, firstName, bookingId, title, startDate,
  slug) : email rappel J-1 avec CTA vers /reservations/[id].
- sendRentalReminder(to, firstName, rbId, providerName, startDate,
  contactInfo) : rappel pour récup matériel, affiche contacts
  provider (phone + email).

tests/lib/cron-auth.test.ts (6 cas) :
- Refus si CRON_TOKEN absent, header absent, format incorrect (Basic
  ou Token), token mismatch.
- Accept si match exact, accept avec espaces autour du token (defensive).

Total tests : 89/89 ✓.

Schedule recommandé (à brancher côté Hermes ou crontab) :
- GET /api/cron/reminders : 1× par jour à 9h (Authorization: Bearer
  $CRON_TOKEN)
- GET /api/cron/cleanup : 1× par semaine

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 03:23:58 +00:00
..
admin fix(admin): PATCH content-pages respecte ?lang= (sinon écrasait FR) 2026-06-01 00:51:19 +00:00
auth/[...nextauth] feat(auth): add multi-role NextAuth with role guards 2026-05-29 10:46:54 +00:00
bookings feat(hardening): rate limit (signup/reset/bookings) + tâches cron + backup PostgreSQL nocturne 2026-06-01 20:16:57 +00:00
carbets/[carbetId] feat(ce): Sprint I — CRUD carbets côté CE 2026-06-02 23:34:17 +00:00
cron feat(prod): Sprint Q — reminders J-1 + cleanup cron endpoints 2026-06-03 03:23:58 +00:00
favorites feat: « Au fil de l'eau » — Reels mobile + uploader pro + favoris 2026-06-02 00:27:16 +00:00
health feat(p2): vitest + 27 tests + /api/health enrichi + /api/metrics + workflow CI 2026-06-01 02:27:14 +00:00
me/export feat: reset password + page mon-compte (RGPD) + facettes recherche (prix max, équipements) 2026-06-01 10:16:37 +00:00
media feat: « Au fil de l'eau » — Reels mobile + uploader pro + favoris 2026-06-02 00:27:16 +00:00
metrics feat(p2): vitest + 27 tests + /api/health enrichi + /api/metrics + workflow CI 2026-06-01 02:27:14 +00:00
password feat(hardening): rate limit (signup/reset/bookings) + tâches cron + backup PostgreSQL nocturne 2026-06-01 20:16:57 +00:00
rental-media feat(ce): Sprint J — matériel rental côté CE 2026-06-02 23:47:57 +00:00
rentals feat(rental): Sprint M — refonds + annulations Stripe 2026-06-03 02:17:58 +00:00
reviews/[reviewId]/response feat(reviews): avis & notes carbet (SYS-8) 2026-05-30 15:08:55 +00:00
signup feat(ce): Sprint K — public badge + invites CE_MEMBER + tests 2026-06-03 00:03:03 +00:00
stripe feat(rental): Sprint E — emails + plugin toggle + tests 2026-06-02 08:49:39 +00:00
uploads feat(ce): Sprint J — matériel rental côté CE 2026-06-02 23:47:57 +00:00