09 - User Behaviour (Webhooks Module)
- 1. Behavioural contract (what the user sees must match the server)
- 2. Create → verify loop (developer)
- 3. Failure → diagnose → retry loop
- 4. Pause → vendor fix → resume loop (admin)
- 5. Behavioural gaps (flagged, see 14)
Expected behaviour patterns mapped to the implemented backend. Section 1 enumerates the observable server-side states users depend on; §2-§4 describe behaviour loops; §5 lists behavioural gaps.
1. Behavioural contract (what the user sees must match the server)
| User-visible fact | Server source |
|---|---|
| List is newest-first | findAll sort { createdAt: -1 } (webhooks.service.ts:35-37) |
| Logs are newest-first, max 50 | findLogs limit 50 (webhooks.service.ts:88-93) |
Statuses: pending, success, failed only | enum (webhook-delivery-log.schema.ts:18-23) |
"Active" vs "Paused" = enabled | webhook.schema.ts:22-23, pause/resume (webhooks.controller.ts:78-90) |
| Metrics counts match logs | both from same collection (webhooks.service.ts:142-156) |
| Test/retry replies are "queued", not "delivered" | { message: 'Test delivery queued' }, { message: 'Retry queued' } (webhooks.controller.ts:62, 69) |
| Retry works only when a failure exists | NotFoundException('No failed deliveries to retry') (webhooks.service.ts:103-108) |
| Deleting is soft (logs survive) | repo.softDelete (webhooks.service.ts:50-53, base.repository.ts:68-74) |
2. Create → verify loop (developer)
- Form submit → success → test ping → watch logs go
pending → success. - Pattern: developer expects the test attempt within seconds; if the logs stay
empty after ~15 s, surface "queued but not yet processed" (queue is async,
webhooks.service.ts:69-84). - Signature verification happens out-of-band on the receiver side - the app
offers
SignatureVerifyCard(dev mode) for quick checks (webhook-delivery.worker.ts:103-105).
3. Failure → diagnose → retry loop
- Metrics show
failed > 0or a red log row. - Open S6:
responseCode+responseBodyexplain (e.g.404on stale URL). - Fix URL (PATCH,
webhooks.controller.ts:39-43) → retry (POST /webhooks/:id/retry) → new attempt row. - Note: retry re-sends the old payload captured at failure time
(
webhooks.service.ts:110-118) - users should expect historical data, not a fresh event. - If retry fails again, BullMQ gave it 3 attempts already
(
webhooks.service.ts:80-83) - persistent failure = endpoint problem, not a queue problem.
4. Pause → vendor fix → resume loop (admin)
- Vendor incidents → pause (stops fan-out immediately,
webhook.repository.ts:23-28) → vendor fixes → resume → backfills happen manually via the vendor's own replay (no replay API today -(planned)gap). - Users should know: paused webhooks drop events silently; no queue accumulates.
5. Behavioural gaps (flagged, see 14)
| Gap | Evidence | User impact |
|---|---|---|
| No replay/backfill API | only retry-latest-failure exists (webhooks.service.ts:95-120) | missed events during downtime are gone |
| Retry creates a duplicate log rather than updating the failed one | worker always startDelivery (new pending row, :163-177) | log history mixes attempts |
attemptCount stuck at 0 | schema default, never incremented (webhook-delivery-log.schema.ts:31-32) | no per-attempt numbering |
lastTriggeredAt / failureCount never written | fields exist (webhook.schema.ts:25-29), no writes found | cannot sort by last activity server-side |
| HTTP-error double record | worker records failed w/ code then catch records failed w/o (webhook-delivery.worker.ts:84-99) | responseCode may be lost on failure path |
| Events free-form | create-webhook.dto.ts:20-24 | typos silently never fire |