Overview
Human-owned documentation. This is the authoritative lane for package boundaries, constraints, and operational guidance.
Purpose
Section titled “Purpose”@lastshotlabs/slingshot-webhooks owns outbound webhook endpoint management, scoped delivery, and
inbound provider intake. It does not own the event universe. Event owners define what is externally
deliverable through the registry, and this package projects those definitions onto subscribers.
The webhook entities themselves follow the shared package-first/entity authoring model;
createWebhooksPackage() is the runtime shell that composes delivery and intake wiring.
Package Boundaries
Section titled “Package Boundaries”- Own endpoint persistence, delivery orchestration, retry state, and inbound provider hooks.
- Consume
slingshot-coreevent definitions, event envelopes, and subscriber authorization rules. - Stay policy-aware at the boundary but transport-light underneath. Queue implementations should carry projected payloads and subscriber metadata, not rebuild authorization later.
- Do not reintroduce a webhook-owned default event universe, string allowlist API, or cross-tenant widening path.
Operational Notes
Section titled “Operational Notes”- Webhook management routes now fail closed. Configure
adminGuardunless you explicitly disable the endpoints route group. - Pass
storewhen you cannot supply a liveadapterinstance — the package will construct the runtime adapter from the store and resolved cipher. Hand in concrete functions foradminGuard, custom queues, and inbound providers. - Webhook endpoint URLs must use
http:orhttps:. Non-HTTP schemes are rejected at validation time. - HTTP responses fully redact stored webhook secrets. The runtime adapter still holds the raw secret internally for signing deliveries.
- Management writes use
subscriptions, not legacyevents. Each entry is either{ event }or{ pattern }, and patterns are normalized up front into concrete approved event keys. - Endpoint records now carry
ownerType,ownerId, optionaltenantId, and normalizedsubscriptions. Delivery records preserveeventId,occurredAt, subscriber identity, and source scope. - Existing legacy rows are normalized at startup. If stored subscriptions cannot be resolved safely, the endpoint is disabled rather than widened.
- HTTP delivery timeout is configurable via the package-wide
deliveryTimeoutMs(default 30000) and the per-endpointdeliveryTimeoutMsoverride. Both are bounded to a hard 120000 ms ceiling to keep stuck deliveries from monopolising queue workers. - Inbound webhook routes enforce a maximum request body size via
inboundMaxBodyBytes(default 1 MiB). Oversized requests are rejected with413 Payload Too Largebefore any provider parsing runs. Raise this only when a known provider posts larger payloads.
Gotchas
Section titled “Gotchas”- Package config still has an
eventsfield, but that is only the webhook package’s own intake filter on the app bus. It is not the endpoint-management payload shape. - Future event registrations elsewhere in the app do not silently expand existing endpoint subscriptions. Concrete event subscriptions stay frozen until an endpoint is updated explicitly.
- Delivery attempts time out after
endpoint.deliveryTimeoutMs(when set), otherwiseconfig.deliveryTimeoutMs, otherwise 30 s. Both knobs accept a positive integer up to 120000 ms (2 min); larger values are rejected at validation time. Timeouts surface as retryable delivery failures. - If enqueueing a delivery fails, the delivery record is immediately marked
dead. If that status update itself fails, the error is logged but does not propagate — the event handler always returns cleanly.
Key Files
Section titled “Key Files”packages/slingshot-webhooks/src/index.tspackages/slingshot-webhooks/src/plugin.tspackages/slingshot-webhooks/src/entities/runtime.tspackages/slingshot-webhooks/src/lib/eventWiring.ts