Processors and workers
Middleware Backend is not a second database. It is processors (HTTP), webhook workers, and scheduled / queue workers. All of them read and write Core Backend.
Nest shape: one folder per capability, same as file-manager. Use Nest cron or a queue for schedules — do not keep Convex crons.ts in the Vue repo as the long-term home.
Sync HTTP processors
Frontend or another route calls these. User JWT (except where noted).
| Job | Winner URL | Then Core Backend |
|---|---|---|
| Availability | POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/availability/check | GET rooms, rate_plans, bookings — return counts only |
| Start payment | POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/payments/initialize | POST payment; GET booking (must be JWT owner) |
| Verify payment | POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/payments/verify/{reference} | PUT payment + booking if paid |
| Refund | POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/refunds | PUT payment / booking cancelled |
| Send email | POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/emails/send | Optional metadata email_event_* on booking |
| Google ARI push | POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/google-rates/push | GET property (must own); metadata ari_last_push_at |
| Google rates pull | POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/google-rates/pull | Optional PUT rate_plan extra_data |
| Upload URL | POST https://middleware-dev.bookdirect.live/api/v1/nellalink/file-manager/aws/upload-url | Frontend then PUTs Core Backend gallery URLs |
Details: availability, payments, refunds, emails, google-rates, file-manager.
IDOR: JWT owned_by on booking/property. Availability must not leak guest PII.
Webhook workers
PSP → Middleware Backend. No user JWT. Verify the provider signature, then update Core Backend.
| Job | Winner URL | Then Core Backend |
|---|---|---|
| Paystack (and later Squad/Tsara) | POST https://middleware-dev.bookdirect.live/api/v1/bookdirect/payments/webhook/paystack | PUT payment paid; PUT booking confirmed; then emails |
Do not accept a browser body that says “mark paid.”
IDOR: do not take owned_by from the PSP payload as a new owner.
Scheduled / queue workers (internal)
Not frontend-callable. Name them in code (src/routes/... or a workers/ folder). They GET/PUT Core Backend only.
| Job | Trigger | Core Backend |
|---|---|---|
| Abandon stale holds | Every 5–15 min | Bookings pending older than N minutes → cancelled (no PSP capture) |
| Invoice / pay-later reminder | Daily | GET pending bookings; POST emails |
| ARI reconcile | Hourly or nightly | Same as google-rates push for published properties |
| Availability / inventory reconcile | After booking storms | Re-read bookings; no local inventory table as truth |
| Email retry | Queue | Failed emails/send; metadata on booking |
These replace Convex crons in bookdirect-legacy-code (convex/crons.ts). Do not document them as public OpenAPI operations. Optional comment in specs/middleware/v1 that workers are internal.
IDOR: workers use a Core Backend service x-api-key with tight path/entity scopes. They must not become a generic “update any booking” admin key for the frontend.