Files
mdm-ordinis/ordinis-outbox
Zimin A.N. e9a7278709 feat(webhook): Phase 3 — REST API CRUD + HMAC/SSRF tests
REST API endpoints под /api/v1/admin/webhooks/:
- GET    /subscriptions               — list (INTERNAL+ scope)
- POST   /subscriptions                — create (RESTRICTED scope)
- GET    /subscriptions/{id}           — get one (INTERNAL+)
- PUT    /subscriptions/{id}           — update (RESTRICTED)
- DELETE /subscriptions/{id}           — delete (RESTRICTED)
- POST   /subscriptions/{id}/rotate-secret  — regenerate HMAC (RESTRICTED)
- GET    /subscriptions/{id}/deliveries     — delivery history per sub
- GET    /deliveries/dlq                    — DLQ listing

RBAC через ScopeContext: RESTRICTED для mutating, INTERNAL+ для read.
PUBLIC scope получает 403.

DTOs:
- CreateWebhookSubscriptionRequest (Bean Validation: URL regex, length)
- WebhookSubscriptionResponse (с factory `from()` маскированный secret
  vs `fromWithSecret()` plaintext только для create response)
- WebhookDeliveryResponse

Service:
- HMAC secret 32 random bytes → 64 hex chars через SecureRandom
- Plaintext secret виден только в create/rotate response (single-time)
- list/get показывают `sk_****<last4>` masked

Tests (15 SsrfGuard + 8 HmacSigner = 23 new):
- HmacSigner: known vector verification, prefix, hex length, distinct
  inputs produce distinct sigs, empty secret rejected
- SsrfGuard: rejects 127/8, 169.254/16, 10/8, 192.168/16, 0.0.0.0,
  non-http schemes, missing host, unresolvable DNS. Allowlist bypass.
  isPrivate() unit tests для loopback/link-local/site-local/public IP.

Total: 109 → 132 unit tests.

Phase 4 далее: admin-ui /webhooks page (list + create + delivery history).
2026-05-06 15:12:28 +03:00
..