01 - Product Overview (Webhooks Module)
StudyLyon - multi-tenant ERP / School Management API. This package designs the Webhooks module client (Flutter, forward-looking spec) against the implemented NestJS backend. All endpoints, DTO fields, schemas, domain events, permissions and wire contracts are derived directly from
src/modules/webhooks/**,src/infrastructure/bullmq/queue.constants.ts,src/infrastructure/bullmq/event-queue-map.ts,src/modules/rbac/permissions.constants.ts,docs/IMPLEMENTATION_PLAN.mdandstudylyon-blueprint/01-Product/PRODUCT_REQUIREMENTS_DOCUMENT.md. No feature is invented - anything not present in source is flagged(planned)/(proposed)/(forward-looking).
Heads-up: per the PRD, the mobile client is out of Phase 1 scope
(PRODUCT_REQUIREMENTS_DOCUMENT.md:144 - "Native mobile apps (web-first)");
this package is the forward-looking spec the client will be built against later.
Webhook management itself is a developer/admin console concern; it will surface in
a web-first admin surface before any mobile surface.
1. Purpose
The webhooks module lets a tenant subscribe to StudyLyon domain events and have them POSTed to an external HTTPS endpoint in near-real-time:
- Subscriptions - named webhooks with a destination
url, a free-formeventslist, a sharedsecretfor HMAC signing, and anenabledflag (webhook.schema.ts:8-30). - Delivery pipeline - every emitted domain event is matched against active
subscriptions and enqueued as a BullMQ job on the
webhook-deliverqueue; a dedicated worker POSTs the payload with an HMAC-SHA256 signature header and records a per-delivery log (webhooks.service.ts:26-86,webhook-delivery.worker.ts:20-105). - Observability - per-webhook delivery logs (last 50), metrics
(total/success/failed/pending), manual retry of the latest failed delivery, and a
test ping (
webhooks.controller.ts:52-76).
| Responsibility | Source |
|---|---|
| Webhook CRUD + soft delete | webhooks.controller.ts:21-50, webhooks.service.ts:31-53 |
| Event fan-out to subscriptions | webhooks.service.ts:26-28, 55-86, webhook.repository.ts:17-29 |
Queue registration (webhook-deliver) | queue.constants.ts:14, webhooks.module.ts:22 |
| Delivery worker (fetch, HMAC, timeout, retry) | webhook-delivery.worker.ts:20-105 |
| Delivery log + metrics + retry + test | webhooks.service.ts:88-161 |
| RBAC permissions | permissions.constants.ts:89-92 |
2. Business goals
| Goal | Measure |
|---|---|
| External systems notified of tenant events | active webhooks matched per event type (webhook.repository.ts:17-29) |
| Authenticated delivery | HMAC-SHA256 signature of the raw body (webhook-delivery.worker.ts:70-82, 103-105) |
| No silent losses | BullMQ retries (3 attempts, exponential backoff 5 s) + delivery log per attempt (webhooks.service.ts:80-83) |
| Tenant isolation | every query tenant-scoped via BaseRepository.scopedFilter (base.repository.ts:20-30) |
| Operational transparency | delivery logs, metrics endpoint, manual retry (webhooks.service.ts:88-161) |
3. User goals
- Tenant developer / system integrator: register a callback URL, choose which events to receive, manage the signing secret, watch delivery health, retry failures, verify signatures.
- School admin: (forward-looking) enable vendor integrations (SMS, attendance
hardware, analytics) that consume StudyLyon events - configured by an
administrator with
webhook.*permissions.
4. Scope
4.1 In scope (implemented backend)
Webhook CRUD with webhook.create/read/update/delete permissions
(permissions.constants.ts:89-92); event fan-out from the in-process EventBus
(event-bus.service.ts:11-22, webhooks.service.ts:26-28); asynchronous delivery
via the webhook-deliver BullMQ queue (queue.constants.ts:14) with 3 attempts /
exponential 5 s backoff (webhooks.service.ts:80-83); HMAC-SHA256 signature header
(webhook-delivery.worker.ts:103-105); per-delivery logs with status
pending/success/failed (webhook-delivery-log.schema.ts:18-23); pause/resume,
manual retry of latest failure, test ping (WebhookTested), and metrics
(webhooks.controller.ts:58-90).
4.2 Planned (IMPLEMENTATION_PLAN.md:48)
Unauthenticated public API scope (30 req/min, 1 min window) described as
"(webhooks, health)" - an inbound webhook receiver for external providers
(test-series integration, IMPLEMENTATION_PLAN.md:856) is planned but not
implemented. No such controller exists in src/ today - marked (planned)
throughout this package.
4.3 Forward-looking (client roadmap)
Admin console UI for webhook management, delivery-log browser with retry, and
event picker; per PRD the mobile client itself is post-Phase 1
(PRODUCT_REQUIREMENTS_DOCUMENT.md:144). Delivery-log pagination and secret
rotation UX fall here too (no endpoint today) - (forward-looking).
4.4 Proposed (analytics)
Analytics events on screens (webhooks.*.*) per 00-shared/10 §8 - (proposed).
5. Non-goals (this version)
- Inbound webhook receiver (receiving from external systems) -
(planned)only, perIMPLEMENTATION_PLAN.md:48. - Event whitelist validation -
eventsis a free-form string array (create-webhook.dto.ts:20-24); any eventType string is accepted. - Signature timestamp / replay protection - signature covers the body only
(
webhook-delivery.worker.ts:103-105); noX-Webhook-Timestampheader. - Attempt bookkeeping -
attemptCountdefaults to 0 and is never incremented (webhook-delivery-log.schema.ts:31-32);lastTriggeredAt/failureCounton the webhook doc are never written (webhook.schema.ts:25-29) - flagged in 14_QA_Checklist.md. - Log pagination / filtering - logs endpoint hard-limits to 50, newest first
(
webhooks.service.ts:88-93). - Secret masking - the signing secret is returned in plaintext by CRUD
responses (documents returned verbatim,
webhooks.service.ts:31-47).