@objectstack/plugin-webhooks 7.2.1 → 7.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/.turbo/turbo-build.log +30 -26
  2. package/CHANGELOG.md +116 -0
  3. package/dist/chunk-7HS5DLU2.js +319 -0
  4. package/dist/chunk-7HS5DLU2.js.map +1 -0
  5. package/dist/{chunk-FA66GQEO.cjs → chunk-HF7CCDPB.cjs} +3 -3
  6. package/dist/{chunk-FA66GQEO.cjs.map → chunk-HF7CCDPB.cjs.map} +1 -1
  7. package/dist/{chunk-BS2QTZH3.js → chunk-KNGLLSSP.js} +2 -2
  8. package/dist/{chunk-MJZGD37S.cjs → chunk-TDSI7UHY.cjs} +138 -3
  9. package/dist/chunk-TDSI7UHY.cjs.map +1 -0
  10. package/dist/index.cjs +43 -14
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.js +33 -4
  13. package/dist/index.js.map +1 -1
  14. package/dist/schema.cjs +4 -2
  15. package/dist/schema.cjs.map +1 -1
  16. package/dist/schema.d.cts +3002 -137
  17. package/dist/schema.d.ts +3002 -137
  18. package/dist/schema.js +3 -1
  19. package/dist/sql-outbox.cjs +3 -3
  20. package/dist/sql-outbox.js +2 -2
  21. package/dist/translations-AV47AVPV.js +727 -0
  22. package/dist/translations-AV47AVPV.js.map +1 -0
  23. package/dist/translations-OAKKANSP.cjs +727 -0
  24. package/dist/translations-OAKKANSP.cjs.map +1 -0
  25. package/package.json +6 -6
  26. package/scripts/i18n-extract.config.ts +32 -0
  27. package/src/schema.ts +7 -3
  28. package/src/sys-webhook.object.ts +177 -0
  29. package/src/translations/en.objects.generated.ts +187 -0
  30. package/src/translations/es-ES.objects.generated.ts +187 -0
  31. package/src/translations/index.ts +23 -0
  32. package/src/translations/ja-JP.objects.generated.ts +187 -0
  33. package/src/translations/zh-CN.objects.generated.ts +187 -0
  34. package/src/webhook-outbox-plugin.ts +38 -7
  35. package/dist/chunk-33LYZT7O.js +0 -184
  36. package/dist/chunk-33LYZT7O.js.map +0 -1
  37. package/dist/chunk-MJZGD37S.cjs.map +0 -1
  38. /package/dist/{chunk-BS2QTZH3.js.map → chunk-KNGLLSSP.js.map} +0 -0
@@ -1,184 +0,0 @@
1
- // src/sys-webhook-delivery.object.ts
2
- import { Field, ObjectSchema } from "@objectstack/spec/data";
3
- var SysWebhookDelivery = ObjectSchema.create({
4
- name: "sys_webhook_delivery",
5
- label: "Webhook Delivery",
6
- pluralLabel: "Webhook Deliveries",
7
- icon: "package",
8
- isSystem: true,
9
- managedBy: "config",
10
- userActions: { create: false, edit: false, delete: false, import: false },
11
- description: "Durable outbox row for one webhook attempt. Managed by @objectstack/plugin-webhooks; do not write directly.",
12
- displayNameField: "id",
13
- titleFormat: "{event_type} \u2192 {url}",
14
- compactLayout: ["event_type", "url", "status", "attempts", "next_retry_at"],
15
- actions: [
16
- {
17
- name: "redeliver",
18
- label: "Redeliver",
19
- icon: "refresh-cw",
20
- variant: "secondary",
21
- locations: ["list_item", "record_header"],
22
- type: "api",
23
- target: "/api/v1/webhooks/redeliver",
24
- method: "POST",
25
- recordIdParam: "deliveryId",
26
- confirmText: "Replay this delivery? The receiver will get the original payload again \u2014 they must be idempotent on the X-Objectstack-Delivery header.",
27
- successMessage: "Queued for redelivery",
28
- refreshAfter: true,
29
- // Only terminal rows are safe to replay. Pending / in_flight rows
30
- // are either already queued or actively being sent — replaying
31
- // would double-deliver.
32
- disabled: "!(status in ['success', 'failed', 'dead'])"
33
- }
34
- ],
35
- listViews: {
36
- recent: {
37
- type: "grid",
38
- name: "recent",
39
- label: "Recent",
40
- data: { provider: "object", object: "sys_webhook_delivery" },
41
- columns: ["event_type", "url", "status", "attempts", "response_code", "updated_at"],
42
- sort: [{ field: "updated_at", order: "desc" }],
43
- pagination: { pageSize: 50 }
44
- },
45
- failures: {
46
- type: "grid",
47
- name: "failures",
48
- label: "Failures",
49
- data: { provider: "object", object: "sys_webhook_delivery" },
50
- columns: ["event_type", "url", "status", "attempts", "response_code", "error", "updated_at"],
51
- filter: [{ field: "status", operator: "in", value: ["failed", "dead"] }],
52
- sort: [{ field: "updated_at", order: "desc" }],
53
- pagination: { pageSize: 50 }
54
- },
55
- in_flight: {
56
- type: "grid",
57
- name: "in_flight",
58
- label: "In Flight",
59
- data: { provider: "object", object: "sys_webhook_delivery" },
60
- columns: ["event_type", "url", "attempts", "claimed_by", "claimed_at"],
61
- filter: [{ field: "status", operator: "equals", value: "in_flight" }],
62
- sort: [{ field: "claimed_at", order: "desc" }],
63
- pagination: { pageSize: 50 }
64
- },
65
- pending: {
66
- type: "grid",
67
- name: "pending",
68
- label: "Pending",
69
- data: { provider: "object", object: "sys_webhook_delivery" },
70
- columns: ["event_type", "url", "attempts", "next_retry_at", "updated_at"],
71
- filter: [{ field: "status", operator: "equals", value: "pending" }],
72
- sort: [{ field: "next_retry_at", order: "asc" }],
73
- pagination: { pageSize: 50 }
74
- },
75
- by_status: {
76
- type: "grid",
77
- name: "by_status",
78
- label: "By Status",
79
- data: { provider: "object", object: "sys_webhook_delivery" },
80
- columns: ["status", "event_type", "url", "attempts", "updated_at"],
81
- sort: [{ field: "status", order: "asc" }, { field: "updated_at", order: "desc" }],
82
- grouping: { fields: [{ field: "status", order: "asc", collapsed: false }] },
83
- pagination: { pageSize: 100 }
84
- },
85
- by_webhook: {
86
- type: "grid",
87
- name: "by_webhook",
88
- label: "By Webhook",
89
- data: { provider: "object", object: "sys_webhook_delivery" },
90
- columns: ["webhook_id", "event_type", "status", "attempts", "updated_at"],
91
- sort: [{ field: "webhook_id", order: "asc" }, { field: "updated_at", order: "desc" }],
92
- grouping: { fields: [{ field: "webhook_id", order: "asc", collapsed: true }] },
93
- pagination: { pageSize: 100 }
94
- },
95
- all_deliveries: {
96
- type: "grid",
97
- name: "all_deliveries",
98
- label: "All",
99
- data: { provider: "object", object: "sys_webhook_delivery" },
100
- columns: ["event_type", "url", "status", "attempts", "response_code", "updated_at"],
101
- sort: [{ field: "updated_at", order: "desc" }],
102
- pagination: { pageSize: 100 }
103
- }
104
- },
105
- fields: {
106
- id: Field.text({
107
- label: "Delivery ID",
108
- required: true,
109
- maxLength: 64,
110
- description: "UUID \u2014 also doubles as the receiver-side idempotency key"
111
- }),
112
- webhook_id: Field.text({
113
- label: "Webhook ID",
114
- required: true,
115
- maxLength: 64,
116
- description: "FK to sys_webhook.id (loosely coupled \u2014 denormalised URL/secret on row)"
117
- }),
118
- event_id: Field.text({
119
- label: "Event ID",
120
- required: true,
121
- maxLength: 128,
122
- description: "Source event id; UNIQUE(event_id, webhook_id) for dedup"
123
- }),
124
- event_type: Field.text({
125
- label: "Event Type",
126
- required: true,
127
- maxLength: 128,
128
- description: "e.g. data.record.created"
129
- }),
130
- url: Field.text({
131
- label: "Target URL",
132
- required: true,
133
- maxLength: 2048,
134
- description: "Snapshotted at enqueue so config edits do not rewrite live rows"
135
- }),
136
- method: Field.text({ label: "Method", required: false, maxLength: 10 }),
137
- headers_json: Field.textarea({ label: "Headers JSON", required: false }),
138
- secret: Field.text({ label: "HMAC Secret", required: false, maxLength: 256 }),
139
- timeout_ms: Field.number({ label: "Timeout (ms)", required: false }),
140
- payload_json: Field.textarea({ label: "Payload JSON", required: true }),
141
- partition_key: Field.number({
142
- label: "Partition",
143
- required: true,
144
- description: "hash(webhook_id) mod partitionCount \u2014 precomputed for cheap WHERE"
145
- }),
146
- status: Field.text({
147
- label: "Status",
148
- required: true,
149
- defaultValue: "pending",
150
- maxLength: 16,
151
- description: "pending | in_flight | success | failed | dead"
152
- }),
153
- attempts: Field.number({
154
- label: "Attempts",
155
- required: true,
156
- defaultValue: 0,
157
- description: "Number of POST attempts made so far"
158
- }),
159
- claimed_by: Field.text({ label: "Claimed By", required: false, maxLength: 128 }),
160
- claimed_at: Field.number({ label: "Claimed At (ms)", required: false }),
161
- next_retry_at: Field.number({ label: "Next Retry At (ms)", required: false }),
162
- last_attempted_at: Field.number({ label: "Last Attempted At (ms)", required: false }),
163
- response_code: Field.number({ label: "HTTP Status", required: false }),
164
- response_body: Field.textarea({ label: "Response Body (capped)", required: false }),
165
- error: Field.textarea({ label: "Error", required: false }),
166
- created_at: Field.number({ label: "Created At (ms)", required: true }),
167
- updated_at: Field.number({ label: "Updated At (ms)", required: true })
168
- },
169
- indexes: [
170
- { fields: ["event_id", "webhook_id"], unique: true },
171
- // Hot path: claim query
172
- { fields: ["status", "partition_key", "next_retry_at"] },
173
- // Reaper: scan stale in_flight rows by claimed_at
174
- { fields: ["status", "claimed_at"] },
175
- { fields: ["webhook_id"] }
176
- ]
177
- });
178
- var SYS_WEBHOOK_DELIVERY = "sys_webhook_delivery";
179
-
180
- export {
181
- SysWebhookDelivery,
182
- SYS_WEBHOOK_DELIVERY
183
- };
184
- //# sourceMappingURL=chunk-33LYZT7O.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/sys-webhook-delivery.object.ts"],"sourcesContent":["// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Field, ObjectSchema } from '@objectstack/spec/data';\n\n/**\n * sys_webhook_delivery — Durable outbox row for one HTTP attempt.\n *\n * Schema is owned by `@objectstack/plugin-webhooks`. Add it to your stack\n * via:\n *\n * import { SysWebhookDelivery } from '@objectstack/plugin-webhooks/schema';\n * defineStack({ objects: [SysWebhookDelivery, ...], plugins: [...] });\n *\n * Designed for the SqlWebhookOutbox claim algorithm:\n *\n * 1. Producers INSERT pending rows (dedup'd by (event_id, webhook_id)).\n * 2. The dispatcher's per-partition lock-holder runs:\n * SELECT id WHERE status='pending' AND partition_key=? AND (next_retry_at <= now OR null)\n * UPDATE SET status='in_flight' WHERE id IN (...) AND status='pending' ← atomic claim\n * POST to target URL\n * UPDATE SET status=success/pending/dead, attempts=attempts+1, ...\n *\n * `partition_key` is precomputed on enqueue (hash(webhook_id) mod N) so the\n * dispatcher can filter cheaply without DB-side hash functions.\n *\n * Indexes are tuned for the hot path: `(status, partition_key, next_retry_at)`\n * is the claim query; `(event_id, webhook_id)` is the dedup uniqueness.\n *\n * @namespace sys\n */\nexport const SysWebhookDelivery = ObjectSchema.create({\n name: 'sys_webhook_delivery',\n label: 'Webhook Delivery',\n pluralLabel: 'Webhook Deliveries',\n icon: 'package',\n isSystem: true,\n managedBy: 'config',\n userActions: { create: false, edit: false, delete: false, import: false },\n description:\n 'Durable outbox row for one webhook attempt. Managed by @objectstack/plugin-webhooks; do not write directly.',\n displayNameField: 'id',\n titleFormat: '{event_type} → {url}',\n compactLayout: ['event_type', 'url', 'status', 'attempts', 'next_retry_at'],\n\n actions: [\n {\n name: 'redeliver',\n label: 'Redeliver',\n icon: 'refresh-cw',\n variant: 'secondary',\n locations: ['list_item', 'record_header'],\n type: 'api',\n target: '/api/v1/webhooks/redeliver',\n method: 'POST',\n recordIdParam: 'deliveryId',\n confirmText:\n 'Replay this delivery? The receiver will get the original payload again — they must be idempotent on the X-Objectstack-Delivery header.',\n successMessage: 'Queued for redelivery',\n refreshAfter: true,\n // Only terminal rows are safe to replay. Pending / in_flight rows\n // are either already queued or actively being sent — replaying\n // would double-deliver.\n disabled: \"!(status in ['success', 'failed', 'dead'])\",\n },\n ],\n\n listViews: {\n recent: {\n type: 'grid',\n name: 'recent',\n label: 'Recent',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['event_type', 'url', 'status', 'attempts', 'response_code', 'updated_at'],\n sort: [{ field: 'updated_at', order: 'desc' }],\n pagination: { pageSize: 50 },\n },\n failures: {\n type: 'grid',\n name: 'failures',\n label: 'Failures',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['event_type', 'url', 'status', 'attempts', 'response_code', 'error', 'updated_at'],\n filter: [{ field: 'status', operator: 'in', value: ['failed', 'dead'] }],\n sort: [{ field: 'updated_at', order: 'desc' }],\n pagination: { pageSize: 50 },\n },\n in_flight: {\n type: 'grid',\n name: 'in_flight',\n label: 'In Flight',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['event_type', 'url', 'attempts', 'claimed_by', 'claimed_at'],\n filter: [{ field: 'status', operator: 'equals', value: 'in_flight' }],\n sort: [{ field: 'claimed_at', order: 'desc' }],\n pagination: { pageSize: 50 },\n },\n pending: {\n type: 'grid',\n name: 'pending',\n label: 'Pending',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['event_type', 'url', 'attempts', 'next_retry_at', 'updated_at'],\n filter: [{ field: 'status', operator: 'equals', value: 'pending' }],\n sort: [{ field: 'next_retry_at', order: 'asc' }],\n pagination: { pageSize: 50 },\n },\n by_status: {\n type: 'grid',\n name: 'by_status',\n label: 'By Status',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['status', 'event_type', 'url', 'attempts', 'updated_at'],\n sort: [{ field: 'status', order: 'asc' }, { field: 'updated_at', order: 'desc' }],\n grouping: { fields: [{ field: 'status', order: 'asc', collapsed: false }] },\n pagination: { pageSize: 100 },\n },\n by_webhook: {\n type: 'grid',\n name: 'by_webhook',\n label: 'By Webhook',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['webhook_id', 'event_type', 'status', 'attempts', 'updated_at'],\n sort: [{ field: 'webhook_id', order: 'asc' }, { field: 'updated_at', order: 'desc' }],\n grouping: { fields: [{ field: 'webhook_id', order: 'asc', collapsed: true }] },\n pagination: { pageSize: 100 },\n },\n all_deliveries: {\n type: 'grid',\n name: 'all_deliveries',\n label: 'All',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['event_type', 'url', 'status', 'attempts', 'response_code', 'updated_at'],\n sort: [{ field: 'updated_at', order: 'desc' }],\n pagination: { pageSize: 100 },\n },\n },\n\n fields: {\n id: Field.text({\n label: 'Delivery ID',\n required: true,\n maxLength: 64,\n description: 'UUID — also doubles as the receiver-side idempotency key',\n }),\n\n webhook_id: Field.text({\n label: 'Webhook ID',\n required: true,\n maxLength: 64,\n description: 'FK to sys_webhook.id (loosely coupled — denormalised URL/secret on row)',\n }),\n\n event_id: Field.text({\n label: 'Event ID',\n required: true,\n maxLength: 128,\n description: 'Source event id; UNIQUE(event_id, webhook_id) for dedup',\n }),\n\n event_type: Field.text({\n label: 'Event Type',\n required: true,\n maxLength: 128,\n description: 'e.g. data.record.created',\n }),\n\n url: Field.text({\n label: 'Target URL',\n required: true,\n maxLength: 2048,\n description: 'Snapshotted at enqueue so config edits do not rewrite live rows',\n }),\n\n method: Field.text({ label: 'Method', required: false, maxLength: 10 }),\n headers_json: Field.textarea({ label: 'Headers JSON', required: false }),\n secret: Field.text({ label: 'HMAC Secret', required: false, maxLength: 256 }),\n timeout_ms: Field.number({ label: 'Timeout (ms)', required: false }),\n payload_json: Field.textarea({ label: 'Payload JSON', required: true }),\n\n partition_key: Field.number({\n label: 'Partition',\n required: true,\n description: 'hash(webhook_id) mod partitionCount — precomputed for cheap WHERE',\n }),\n\n status: Field.text({\n label: 'Status',\n required: true,\n defaultValue: 'pending',\n maxLength: 16,\n description: 'pending | in_flight | success | failed | dead',\n }),\n\n attempts: Field.number({\n label: 'Attempts',\n required: true,\n defaultValue: 0,\n description: 'Number of POST attempts made so far',\n }),\n\n claimed_by: Field.text({ label: 'Claimed By', required: false, maxLength: 128 }),\n claimed_at: Field.number({ label: 'Claimed At (ms)', required: false }),\n next_retry_at: Field.number({ label: 'Next Retry At (ms)', required: false }),\n last_attempted_at: Field.number({ label: 'Last Attempted At (ms)', required: false }),\n response_code: Field.number({ label: 'HTTP Status', required: false }),\n response_body: Field.textarea({ label: 'Response Body (capped)', required: false }),\n error: Field.textarea({ label: 'Error', required: false }),\n\n created_at: Field.number({ label: 'Created At (ms)', required: true }),\n updated_at: Field.number({ label: 'Updated At (ms)', required: true }),\n },\n\n indexes: [\n { fields: ['event_id', 'webhook_id'], unique: true },\n // Hot path: claim query\n { fields: ['status', 'partition_key', 'next_retry_at'] },\n // Reaper: scan stale in_flight rows by claimed_at\n { fields: ['status', 'claimed_at'] },\n { fields: ['webhook_id'] },\n ],\n});\n\n/** Canonical object name — exported so SqlWebhookOutbox callers can override if needed. */\nexport const SYS_WEBHOOK_DELIVERY = 'sys_webhook_delivery' as const;\n"],"mappings":";AAEA,SAAS,OAAO,oBAAoB;AA4B7B,IAAM,qBAAqB,aAAa,OAAO;AAAA,EAClD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AAAA,EACX,aAAa,EAAE,QAAQ,OAAO,MAAM,OAAO,QAAQ,OAAO,QAAQ,MAAM;AAAA,EACxE,aACI;AAAA,EACJ,kBAAkB;AAAA,EAClB,aAAa;AAAA,EACb,eAAe,CAAC,cAAc,OAAO,UAAU,YAAY,eAAe;AAAA,EAE1E,SAAS;AAAA,IACL;AAAA,MACI,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,WAAW,CAAC,aAAa,eAAe;AAAA,MACxC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,eAAe;AAAA,MACf,aACI;AAAA,MACJ,gBAAgB;AAAA,MAChB,cAAc;AAAA;AAAA;AAAA;AAAA,MAId,UAAU;AAAA,IACd;AAAA,EACJ;AAAA,EAEA,WAAW;AAAA,IACP,QAAQ;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM,EAAE,UAAU,UAAU,QAAQ,uBAAuB;AAAA,MAC3D,SAAS,CAAC,cAAc,OAAO,UAAU,YAAY,iBAAiB,YAAY;AAAA,MAClF,MAAM,CAAC,EAAE,OAAO,cAAc,OAAO,OAAO,CAAC;AAAA,MAC7C,YAAY,EAAE,UAAU,GAAG;AAAA,IAC/B;AAAA,IACA,UAAU;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM,EAAE,UAAU,UAAU,QAAQ,uBAAuB;AAAA,MAC3D,SAAS,CAAC,cAAc,OAAO,UAAU,YAAY,iBAAiB,SAAS,YAAY;AAAA,MAC3F,QAAQ,CAAC,EAAE,OAAO,UAAU,UAAU,MAAM,OAAO,CAAC,UAAU,MAAM,EAAE,CAAC;AAAA,MACvE,MAAM,CAAC,EAAE,OAAO,cAAc,OAAO,OAAO,CAAC;AAAA,MAC7C,YAAY,EAAE,UAAU,GAAG;AAAA,IAC/B;AAAA,IACA,WAAW;AAAA,MACP,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM,EAAE,UAAU,UAAU,QAAQ,uBAAuB;AAAA,MAC3D,SAAS,CAAC,cAAc,OAAO,YAAY,cAAc,YAAY;AAAA,MACrE,QAAQ,CAAC,EAAE,OAAO,UAAU,UAAU,UAAU,OAAO,YAAY,CAAC;AAAA,MACpE,MAAM,CAAC,EAAE,OAAO,cAAc,OAAO,OAAO,CAAC;AAAA,MAC7C,YAAY,EAAE,UAAU,GAAG;AAAA,IAC/B;AAAA,IACA,SAAS;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM,EAAE,UAAU,UAAU,QAAQ,uBAAuB;AAAA,MAC3D,SAAS,CAAC,cAAc,OAAO,YAAY,iBAAiB,YAAY;AAAA,MACxE,QAAQ,CAAC,EAAE,OAAO,UAAU,UAAU,UAAU,OAAO,UAAU,CAAC;AAAA,MAClE,MAAM,CAAC,EAAE,OAAO,iBAAiB,OAAO,MAAM,CAAC;AAAA,MAC/C,YAAY,EAAE,UAAU,GAAG;AAAA,IAC/B;AAAA,IACA,WAAW;AAAA,MACP,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM,EAAE,UAAU,UAAU,QAAQ,uBAAuB;AAAA,MAC3D,SAAS,CAAC,UAAU,cAAc,OAAO,YAAY,YAAY;AAAA,MACjE,MAAM,CAAC,EAAE,OAAO,UAAU,OAAO,MAAM,GAAG,EAAE,OAAO,cAAc,OAAO,OAAO,CAAC;AAAA,MAChF,UAAU,EAAE,QAAQ,CAAC,EAAE,OAAO,UAAU,OAAO,OAAO,WAAW,MAAM,CAAC,EAAE;AAAA,MAC1E,YAAY,EAAE,UAAU,IAAI;AAAA,IAChC;AAAA,IACA,YAAY;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM,EAAE,UAAU,UAAU,QAAQ,uBAAuB;AAAA,MAC3D,SAAS,CAAC,cAAc,cAAc,UAAU,YAAY,YAAY;AAAA,MACxE,MAAM,CAAC,EAAE,OAAO,cAAc,OAAO,MAAM,GAAG,EAAE,OAAO,cAAc,OAAO,OAAO,CAAC;AAAA,MACpF,UAAU,EAAE,QAAQ,CAAC,EAAE,OAAO,cAAc,OAAO,OAAO,WAAW,KAAK,CAAC,EAAE;AAAA,MAC7E,YAAY,EAAE,UAAU,IAAI;AAAA,IAChC;AAAA,IACA,gBAAgB;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM,EAAE,UAAU,UAAU,QAAQ,uBAAuB;AAAA,MAC3D,SAAS,CAAC,cAAc,OAAO,UAAU,YAAY,iBAAiB,YAAY;AAAA,MAClF,MAAM,CAAC,EAAE,OAAO,cAAc,OAAO,OAAO,CAAC;AAAA,MAC7C,YAAY,EAAE,UAAU,IAAI;AAAA,IAChC;AAAA,EACJ;AAAA,EAEA,QAAQ;AAAA,IACJ,IAAI,MAAM,KAAK;AAAA,MACX,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa;AAAA,IACjB,CAAC;AAAA,IAED,YAAY,MAAM,KAAK;AAAA,MACnB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa;AAAA,IACjB,CAAC;AAAA,IAED,UAAU,MAAM,KAAK;AAAA,MACjB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa;AAAA,IACjB,CAAC;AAAA,IAED,YAAY,MAAM,KAAK;AAAA,MACnB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa;AAAA,IACjB,CAAC;AAAA,IAED,KAAK,MAAM,KAAK;AAAA,MACZ,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa;AAAA,IACjB,CAAC;AAAA,IAED,QAAQ,MAAM,KAAK,EAAE,OAAO,UAAU,UAAU,OAAO,WAAW,GAAG,CAAC;AAAA,IACtE,cAAc,MAAM,SAAS,EAAE,OAAO,gBAAgB,UAAU,MAAM,CAAC;AAAA,IACvE,QAAQ,MAAM,KAAK,EAAE,OAAO,eAAe,UAAU,OAAO,WAAW,IAAI,CAAC;AAAA,IAC5E,YAAY,MAAM,OAAO,EAAE,OAAO,gBAAgB,UAAU,MAAM,CAAC;AAAA,IACnE,cAAc,MAAM,SAAS,EAAE,OAAO,gBAAgB,UAAU,KAAK,CAAC;AAAA,IAEtE,eAAe,MAAM,OAAO;AAAA,MACxB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,aAAa;AAAA,IACjB,CAAC;AAAA,IAED,QAAQ,MAAM,KAAK;AAAA,MACf,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,MACd,WAAW;AAAA,MACX,aAAa;AAAA,IACjB,CAAC;AAAA,IAED,UAAU,MAAM,OAAO;AAAA,MACnB,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,MACd,aAAa;AAAA,IACjB,CAAC;AAAA,IAED,YAAY,MAAM,KAAK,EAAE,OAAO,cAAc,UAAU,OAAO,WAAW,IAAI,CAAC;AAAA,IAC/E,YAAY,MAAM,OAAO,EAAE,OAAO,mBAAmB,UAAU,MAAM,CAAC;AAAA,IACtE,eAAe,MAAM,OAAO,EAAE,OAAO,sBAAsB,UAAU,MAAM,CAAC;AAAA,IAC5E,mBAAmB,MAAM,OAAO,EAAE,OAAO,0BAA0B,UAAU,MAAM,CAAC;AAAA,IACpF,eAAe,MAAM,OAAO,EAAE,OAAO,eAAe,UAAU,MAAM,CAAC;AAAA,IACrE,eAAe,MAAM,SAAS,EAAE,OAAO,0BAA0B,UAAU,MAAM,CAAC;AAAA,IAClF,OAAO,MAAM,SAAS,EAAE,OAAO,SAAS,UAAU,MAAM,CAAC;AAAA,IAEzD,YAAY,MAAM,OAAO,EAAE,OAAO,mBAAmB,UAAU,KAAK,CAAC;AAAA,IACrE,YAAY,MAAM,OAAO,EAAE,OAAO,mBAAmB,UAAU,KAAK,CAAC;AAAA,EACzE;AAAA,EAEA,SAAS;AAAA,IACL,EAAE,QAAQ,CAAC,YAAY,YAAY,GAAG,QAAQ,KAAK;AAAA;AAAA,IAEnD,EAAE,QAAQ,CAAC,UAAU,iBAAiB,eAAe,EAAE;AAAA;AAAA,IAEvD,EAAE,QAAQ,CAAC,UAAU,YAAY,EAAE;AAAA,IACnC,EAAE,QAAQ,CAAC,YAAY,EAAE;AAAA,EAC7B;AACJ,CAAC;AAGM,IAAM,uBAAuB;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/framework/framework/packages/plugins/plugin-webhooks/dist/chunk-MJZGD37S.cjs","../src/sys-webhook-delivery.object.ts"],"names":[],"mappings":"AAAA;ACEA,8CAAoC;AA4B7B,IAAM,mBAAA,EAAqB,kBAAA,CAAa,MAAA,CAAO;AAAA,EAClD,IAAA,EAAM,sBAAA;AAAA,EACN,KAAA,EAAO,kBAAA;AAAA,EACP,WAAA,EAAa,oBAAA;AAAA,EACb,IAAA,EAAM,SAAA;AAAA,EACN,QAAA,EAAU,IAAA;AAAA,EACV,SAAA,EAAW,QAAA;AAAA,EACX,WAAA,EAAa,EAAE,MAAA,EAAQ,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,MAAM,CAAA;AAAA,EACxE,WAAA,EACI,6GAAA;AAAA,EACJ,gBAAA,EAAkB,IAAA;AAAA,EAClB,WAAA,EAAa,2BAAA;AAAA,EACb,aAAA,EAAe,CAAC,YAAA,EAAc,KAAA,EAAO,QAAA,EAAU,UAAA,EAAY,eAAe,CAAA;AAAA,EAE1E,OAAA,EAAS;AAAA,IACL;AAAA,MACI,IAAA,EAAM,WAAA;AAAA,MACN,KAAA,EAAO,WAAA;AAAA,MACP,IAAA,EAAM,YAAA;AAAA,MACN,OAAA,EAAS,WAAA;AAAA,MACT,SAAA,EAAW,CAAC,WAAA,EAAa,eAAe,CAAA;AAAA,MACxC,IAAA,EAAM,KAAA;AAAA,MACN,MAAA,EAAQ,4BAAA;AAAA,MACR,MAAA,EAAQ,MAAA;AAAA,MACR,aAAA,EAAe,YAAA;AAAA,MACf,WAAA,EACI,6IAAA;AAAA,MACJ,cAAA,EAAgB,uBAAA;AAAA,MAChB,YAAA,EAAc,IAAA;AAAA;AAAA;AAAA;AAAA,MAId,QAAA,EAAU;AAAA,IACd;AAAA,EACJ,CAAA;AAAA,EAEA,SAAA,EAAW;AAAA,IACP,MAAA,EAAQ;AAAA,MACJ,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM,QAAA;AAAA,MACN,KAAA,EAAO,QAAA;AAAA,MACP,IAAA,EAAM,EAAE,QAAA,EAAU,QAAA,EAAU,MAAA,EAAQ,uBAAuB,CAAA;AAAA,MAC3D,OAAA,EAAS,CAAC,YAAA,EAAc,KAAA,EAAO,QAAA,EAAU,UAAA,EAAY,eAAA,EAAiB,YAAY,CAAA;AAAA,MAClF,IAAA,EAAM,CAAC,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,OAAO,CAAC,CAAA;AAAA,MAC7C,UAAA,EAAY,EAAE,QAAA,EAAU,GAAG;AAAA,IAC/B,CAAA;AAAA,IACA,QAAA,EAAU;AAAA,MACN,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM,UAAA;AAAA,MACN,KAAA,EAAO,UAAA;AAAA,MACP,IAAA,EAAM,EAAE,QAAA,EAAU,QAAA,EAAU,MAAA,EAAQ,uBAAuB,CAAA;AAAA,MAC3D,OAAA,EAAS,CAAC,YAAA,EAAc,KAAA,EAAO,QAAA,EAAU,UAAA,EAAY,eAAA,EAAiB,OAAA,EAAS,YAAY,CAAA;AAAA,MAC3F,MAAA,EAAQ,CAAC,EAAE,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,CAAC,QAAA,EAAU,MAAM,EAAE,CAAC,CAAA;AAAA,MACvE,IAAA,EAAM,CAAC,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,OAAO,CAAC,CAAA;AAAA,MAC7C,UAAA,EAAY,EAAE,QAAA,EAAU,GAAG;AAAA,IAC/B,CAAA;AAAA,IACA,SAAA,EAAW;AAAA,MACP,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM,WAAA;AAAA,MACN,KAAA,EAAO,WAAA;AAAA,MACP,IAAA,EAAM,EAAE,QAAA,EAAU,QAAA,EAAU,MAAA,EAAQ,uBAAuB,CAAA;AAAA,MAC3D,OAAA,EAAS,CAAC,YAAA,EAAc,KAAA,EAAO,UAAA,EAAY,YAAA,EAAc,YAAY,CAAA;AAAA,MACrE,MAAA,EAAQ,CAAC,EAAE,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,QAAA,EAAU,KAAA,EAAO,YAAY,CAAC,CAAA;AAAA,MACpE,IAAA,EAAM,CAAC,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,OAAO,CAAC,CAAA;AAAA,MAC7C,UAAA,EAAY,EAAE,QAAA,EAAU,GAAG;AAAA,IAC/B,CAAA;AAAA,IACA,OAAA,EAAS;AAAA,MACL,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM,SAAA;AAAA,MACN,KAAA,EAAO,SAAA;AAAA,MACP,IAAA,EAAM,EAAE,QAAA,EAAU,QAAA,EAAU,MAAA,EAAQ,uBAAuB,CAAA;AAAA,MAC3D,OAAA,EAAS,CAAC,YAAA,EAAc,KAAA,EAAO,UAAA,EAAY,eAAA,EAAiB,YAAY,CAAA;AAAA,MACxE,MAAA,EAAQ,CAAC,EAAE,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,QAAA,EAAU,KAAA,EAAO,UAAU,CAAC,CAAA;AAAA,MAClE,IAAA,EAAM,CAAC,EAAE,KAAA,EAAO,eAAA,EAAiB,KAAA,EAAO,MAAM,CAAC,CAAA;AAAA,MAC/C,UAAA,EAAY,EAAE,QAAA,EAAU,GAAG;AAAA,IAC/B,CAAA;AAAA,IACA,SAAA,EAAW;AAAA,MACP,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM,WAAA;AAAA,MACN,KAAA,EAAO,WAAA;AAAA,MACP,IAAA,EAAM,EAAE,QAAA,EAAU,QAAA,EAAU,MAAA,EAAQ,uBAAuB,CAAA;AAAA,MAC3D,OAAA,EAAS,CAAC,QAAA,EAAU,YAAA,EAAc,KAAA,EAAO,UAAA,EAAY,YAAY,CAAA;AAAA,MACjE,IAAA,EAAM,CAAC,EAAE,KAAA,EAAO,QAAA,EAAU,KAAA,EAAO,MAAM,CAAA,EAAG,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,OAAO,CAAC,CAAA;AAAA,MAChF,QAAA,EAAU,EAAE,MAAA,EAAQ,CAAC,EAAE,KAAA,EAAO,QAAA,EAAU,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,MAAM,CAAC,EAAE,CAAA;AAAA,MAC1E,UAAA,EAAY,EAAE,QAAA,EAAU,IAAI;AAAA,IAChC,CAAA;AAAA,IACA,UAAA,EAAY;AAAA,MACR,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM,YAAA;AAAA,MACN,KAAA,EAAO,YAAA;AAAA,MACP,IAAA,EAAM,EAAE,QAAA,EAAU,QAAA,EAAU,MAAA,EAAQ,uBAAuB,CAAA;AAAA,MAC3D,OAAA,EAAS,CAAC,YAAA,EAAc,YAAA,EAAc,QAAA,EAAU,UAAA,EAAY,YAAY,CAAA;AAAA,MACxE,IAAA,EAAM,CAAC,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,MAAM,CAAA,EAAG,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,OAAO,CAAC,CAAA;AAAA,MACpF,QAAA,EAAU,EAAE,MAAA,EAAQ,CAAC,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,KAAA,EAAO,SAAA,EAAW,KAAK,CAAC,EAAE,CAAA;AAAA,MAC7E,UAAA,EAAY,EAAE,QAAA,EAAU,IAAI;AAAA,IAChC,CAAA;AAAA,IACA,cAAA,EAAgB;AAAA,MACZ,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM,gBAAA;AAAA,MACN,KAAA,EAAO,KAAA;AAAA,MACP,IAAA,EAAM,EAAE,QAAA,EAAU,QAAA,EAAU,MAAA,EAAQ,uBAAuB,CAAA;AAAA,MAC3D,OAAA,EAAS,CAAC,YAAA,EAAc,KAAA,EAAO,QAAA,EAAU,UAAA,EAAY,eAAA,EAAiB,YAAY,CAAA;AAAA,MAClF,IAAA,EAAM,CAAC,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,OAAO,CAAC,CAAA;AAAA,MAC7C,UAAA,EAAY,EAAE,QAAA,EAAU,IAAI;AAAA,IAChC;AAAA,EACJ,CAAA;AAAA,EAEA,MAAA,EAAQ;AAAA,IACJ,EAAA,EAAI,WAAA,CAAM,IAAA,CAAK;AAAA,MACX,KAAA,EAAO,aAAA;AAAA,MACP,QAAA,EAAU,IAAA;AAAA,MACV,SAAA,EAAW,EAAA;AAAA,MACX,WAAA,EAAa;AAAA,IACjB,CAAC,CAAA;AAAA,IAED,UAAA,EAAY,WAAA,CAAM,IAAA,CAAK;AAAA,MACnB,KAAA,EAAO,YAAA;AAAA,MACP,QAAA,EAAU,IAAA;AAAA,MACV,SAAA,EAAW,EAAA;AAAA,MACX,WAAA,EAAa;AAAA,IACjB,CAAC,CAAA;AAAA,IAED,QAAA,EAAU,WAAA,CAAM,IAAA,CAAK;AAAA,MACjB,KAAA,EAAO,UAAA;AAAA,MACP,QAAA,EAAU,IAAA;AAAA,MACV,SAAA,EAAW,GAAA;AAAA,MACX,WAAA,EAAa;AAAA,IACjB,CAAC,CAAA;AAAA,IAED,UAAA,EAAY,WAAA,CAAM,IAAA,CAAK;AAAA,MACnB,KAAA,EAAO,YAAA;AAAA,MACP,QAAA,EAAU,IAAA;AAAA,MACV,SAAA,EAAW,GAAA;AAAA,MACX,WAAA,EAAa;AAAA,IACjB,CAAC,CAAA;AAAA,IAED,GAAA,EAAK,WAAA,CAAM,IAAA,CAAK;AAAA,MACZ,KAAA,EAAO,YAAA;AAAA,MACP,QAAA,EAAU,IAAA;AAAA,MACV,SAAA,EAAW,IAAA;AAAA,MACX,WAAA,EAAa;AAAA,IACjB,CAAC,CAAA;AAAA,IAED,MAAA,EAAQ,WAAA,CAAM,IAAA,CAAK,EAAE,KAAA,EAAO,QAAA,EAAU,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,GAAG,CAAC,CAAA;AAAA,IACtE,YAAA,EAAc,WAAA,CAAM,QAAA,CAAS,EAAE,KAAA,EAAO,cAAA,EAAgB,QAAA,EAAU,MAAM,CAAC,CAAA;AAAA,IACvE,MAAA,EAAQ,WAAA,CAAM,IAAA,CAAK,EAAE,KAAA,EAAO,aAAA,EAAe,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,IAAI,CAAC,CAAA;AAAA,IAC5E,UAAA,EAAY,WAAA,CAAM,MAAA,CAAO,EAAE,KAAA,EAAO,cAAA,EAAgB,QAAA,EAAU,MAAM,CAAC,CAAA;AAAA,IACnE,YAAA,EAAc,WAAA,CAAM,QAAA,CAAS,EAAE,KAAA,EAAO,cAAA,EAAgB,QAAA,EAAU,KAAK,CAAC,CAAA;AAAA,IAEtE,aAAA,EAAe,WAAA,CAAM,MAAA,CAAO;AAAA,MACxB,KAAA,EAAO,WAAA;AAAA,MACP,QAAA,EAAU,IAAA;AAAA,MACV,WAAA,EAAa;AAAA,IACjB,CAAC,CAAA;AAAA,IAED,MAAA,EAAQ,WAAA,CAAM,IAAA,CAAK;AAAA,MACf,KAAA,EAAO,QAAA;AAAA,MACP,QAAA,EAAU,IAAA;AAAA,MACV,YAAA,EAAc,SAAA;AAAA,MACd,SAAA,EAAW,EAAA;AAAA,MACX,WAAA,EAAa;AAAA,IACjB,CAAC,CAAA;AAAA,IAED,QAAA,EAAU,WAAA,CAAM,MAAA,CAAO;AAAA,MACnB,KAAA,EAAO,UAAA;AAAA,MACP,QAAA,EAAU,IAAA;AAAA,MACV,YAAA,EAAc,CAAA;AAAA,MACd,WAAA,EAAa;AAAA,IACjB,CAAC,CAAA;AAAA,IAED,UAAA,EAAY,WAAA,CAAM,IAAA,CAAK,EAAE,KAAA,EAAO,YAAA,EAAc,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,IAAI,CAAC,CAAA;AAAA,IAC/E,UAAA,EAAY,WAAA,CAAM,MAAA,CAAO,EAAE,KAAA,EAAO,iBAAA,EAAmB,QAAA,EAAU,MAAM,CAAC,CAAA;AAAA,IACtE,aAAA,EAAe,WAAA,CAAM,MAAA,CAAO,EAAE,KAAA,EAAO,oBAAA,EAAsB,QAAA,EAAU,MAAM,CAAC,CAAA;AAAA,IAC5E,iBAAA,EAAmB,WAAA,CAAM,MAAA,CAAO,EAAE,KAAA,EAAO,wBAAA,EAA0B,QAAA,EAAU,MAAM,CAAC,CAAA;AAAA,IACpF,aAAA,EAAe,WAAA,CAAM,MAAA,CAAO,EAAE,KAAA,EAAO,aAAA,EAAe,QAAA,EAAU,MAAM,CAAC,CAAA;AAAA,IACrE,aAAA,EAAe,WAAA,CAAM,QAAA,CAAS,EAAE,KAAA,EAAO,wBAAA,EAA0B,QAAA,EAAU,MAAM,CAAC,CAAA;AAAA,IAClF,KAAA,EAAO,WAAA,CAAM,QAAA,CAAS,EAAE,KAAA,EAAO,OAAA,EAAS,QAAA,EAAU,MAAM,CAAC,CAAA;AAAA,IAEzD,UAAA,EAAY,WAAA,CAAM,MAAA,CAAO,EAAE,KAAA,EAAO,iBAAA,EAAmB,QAAA,EAAU,KAAK,CAAC,CAAA;AAAA,IACrE,UAAA,EAAY,WAAA,CAAM,MAAA,CAAO,EAAE,KAAA,EAAO,iBAAA,EAAmB,QAAA,EAAU,KAAK,CAAC;AAAA,EACzE,CAAA;AAAA,EAEA,OAAA,EAAS;AAAA,IACL,EAAE,MAAA,EAAQ,CAAC,UAAA,EAAY,YAAY,CAAA,EAAG,MAAA,EAAQ,KAAK,CAAA;AAAA;AAAA,IAEnD,EAAE,MAAA,EAAQ,CAAC,QAAA,EAAU,eAAA,EAAiB,eAAe,EAAE,CAAA;AAAA;AAAA,IAEvD,EAAE,MAAA,EAAQ,CAAC,QAAA,EAAU,YAAY,EAAE,CAAA;AAAA,IACnC,EAAE,MAAA,EAAQ,CAAC,YAAY,EAAE;AAAA,EAC7B;AACJ,CAAC,CAAA;AAGM,IAAM,qBAAA,EAAuB,sBAAA;AD7CpC;AACA;AACE;AACA;AACF,qGAAC","file":"/home/runner/work/framework/framework/packages/plugins/plugin-webhooks/dist/chunk-MJZGD37S.cjs","sourcesContent":[null,"// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Field, ObjectSchema } from '@objectstack/spec/data';\n\n/**\n * sys_webhook_delivery — Durable outbox row for one HTTP attempt.\n *\n * Schema is owned by `@objectstack/plugin-webhooks`. Add it to your stack\n * via:\n *\n * import { SysWebhookDelivery } from '@objectstack/plugin-webhooks/schema';\n * defineStack({ objects: [SysWebhookDelivery, ...], plugins: [...] });\n *\n * Designed for the SqlWebhookOutbox claim algorithm:\n *\n * 1. Producers INSERT pending rows (dedup'd by (event_id, webhook_id)).\n * 2. The dispatcher's per-partition lock-holder runs:\n * SELECT id WHERE status='pending' AND partition_key=? AND (next_retry_at <= now OR null)\n * UPDATE SET status='in_flight' WHERE id IN (...) AND status='pending' ← atomic claim\n * POST to target URL\n * UPDATE SET status=success/pending/dead, attempts=attempts+1, ...\n *\n * `partition_key` is precomputed on enqueue (hash(webhook_id) mod N) so the\n * dispatcher can filter cheaply without DB-side hash functions.\n *\n * Indexes are tuned for the hot path: `(status, partition_key, next_retry_at)`\n * is the claim query; `(event_id, webhook_id)` is the dedup uniqueness.\n *\n * @namespace sys\n */\nexport const SysWebhookDelivery = ObjectSchema.create({\n name: 'sys_webhook_delivery',\n label: 'Webhook Delivery',\n pluralLabel: 'Webhook Deliveries',\n icon: 'package',\n isSystem: true,\n managedBy: 'config',\n userActions: { create: false, edit: false, delete: false, import: false },\n description:\n 'Durable outbox row for one webhook attempt. Managed by @objectstack/plugin-webhooks; do not write directly.',\n displayNameField: 'id',\n titleFormat: '{event_type} → {url}',\n compactLayout: ['event_type', 'url', 'status', 'attempts', 'next_retry_at'],\n\n actions: [\n {\n name: 'redeliver',\n label: 'Redeliver',\n icon: 'refresh-cw',\n variant: 'secondary',\n locations: ['list_item', 'record_header'],\n type: 'api',\n target: '/api/v1/webhooks/redeliver',\n method: 'POST',\n recordIdParam: 'deliveryId',\n confirmText:\n 'Replay this delivery? The receiver will get the original payload again — they must be idempotent on the X-Objectstack-Delivery header.',\n successMessage: 'Queued for redelivery',\n refreshAfter: true,\n // Only terminal rows are safe to replay. Pending / in_flight rows\n // are either already queued or actively being sent — replaying\n // would double-deliver.\n disabled: \"!(status in ['success', 'failed', 'dead'])\",\n },\n ],\n\n listViews: {\n recent: {\n type: 'grid',\n name: 'recent',\n label: 'Recent',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['event_type', 'url', 'status', 'attempts', 'response_code', 'updated_at'],\n sort: [{ field: 'updated_at', order: 'desc' }],\n pagination: { pageSize: 50 },\n },\n failures: {\n type: 'grid',\n name: 'failures',\n label: 'Failures',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['event_type', 'url', 'status', 'attempts', 'response_code', 'error', 'updated_at'],\n filter: [{ field: 'status', operator: 'in', value: ['failed', 'dead'] }],\n sort: [{ field: 'updated_at', order: 'desc' }],\n pagination: { pageSize: 50 },\n },\n in_flight: {\n type: 'grid',\n name: 'in_flight',\n label: 'In Flight',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['event_type', 'url', 'attempts', 'claimed_by', 'claimed_at'],\n filter: [{ field: 'status', operator: 'equals', value: 'in_flight' }],\n sort: [{ field: 'claimed_at', order: 'desc' }],\n pagination: { pageSize: 50 },\n },\n pending: {\n type: 'grid',\n name: 'pending',\n label: 'Pending',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['event_type', 'url', 'attempts', 'next_retry_at', 'updated_at'],\n filter: [{ field: 'status', operator: 'equals', value: 'pending' }],\n sort: [{ field: 'next_retry_at', order: 'asc' }],\n pagination: { pageSize: 50 },\n },\n by_status: {\n type: 'grid',\n name: 'by_status',\n label: 'By Status',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['status', 'event_type', 'url', 'attempts', 'updated_at'],\n sort: [{ field: 'status', order: 'asc' }, { field: 'updated_at', order: 'desc' }],\n grouping: { fields: [{ field: 'status', order: 'asc', collapsed: false }] },\n pagination: { pageSize: 100 },\n },\n by_webhook: {\n type: 'grid',\n name: 'by_webhook',\n label: 'By Webhook',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['webhook_id', 'event_type', 'status', 'attempts', 'updated_at'],\n sort: [{ field: 'webhook_id', order: 'asc' }, { field: 'updated_at', order: 'desc' }],\n grouping: { fields: [{ field: 'webhook_id', order: 'asc', collapsed: true }] },\n pagination: { pageSize: 100 },\n },\n all_deliveries: {\n type: 'grid',\n name: 'all_deliveries',\n label: 'All',\n data: { provider: 'object', object: 'sys_webhook_delivery' },\n columns: ['event_type', 'url', 'status', 'attempts', 'response_code', 'updated_at'],\n sort: [{ field: 'updated_at', order: 'desc' }],\n pagination: { pageSize: 100 },\n },\n },\n\n fields: {\n id: Field.text({\n label: 'Delivery ID',\n required: true,\n maxLength: 64,\n description: 'UUID — also doubles as the receiver-side idempotency key',\n }),\n\n webhook_id: Field.text({\n label: 'Webhook ID',\n required: true,\n maxLength: 64,\n description: 'FK to sys_webhook.id (loosely coupled — denormalised URL/secret on row)',\n }),\n\n event_id: Field.text({\n label: 'Event ID',\n required: true,\n maxLength: 128,\n description: 'Source event id; UNIQUE(event_id, webhook_id) for dedup',\n }),\n\n event_type: Field.text({\n label: 'Event Type',\n required: true,\n maxLength: 128,\n description: 'e.g. data.record.created',\n }),\n\n url: Field.text({\n label: 'Target URL',\n required: true,\n maxLength: 2048,\n description: 'Snapshotted at enqueue so config edits do not rewrite live rows',\n }),\n\n method: Field.text({ label: 'Method', required: false, maxLength: 10 }),\n headers_json: Field.textarea({ label: 'Headers JSON', required: false }),\n secret: Field.text({ label: 'HMAC Secret', required: false, maxLength: 256 }),\n timeout_ms: Field.number({ label: 'Timeout (ms)', required: false }),\n payload_json: Field.textarea({ label: 'Payload JSON', required: true }),\n\n partition_key: Field.number({\n label: 'Partition',\n required: true,\n description: 'hash(webhook_id) mod partitionCount — precomputed for cheap WHERE',\n }),\n\n status: Field.text({\n label: 'Status',\n required: true,\n defaultValue: 'pending',\n maxLength: 16,\n description: 'pending | in_flight | success | failed | dead',\n }),\n\n attempts: Field.number({\n label: 'Attempts',\n required: true,\n defaultValue: 0,\n description: 'Number of POST attempts made so far',\n }),\n\n claimed_by: Field.text({ label: 'Claimed By', required: false, maxLength: 128 }),\n claimed_at: Field.number({ label: 'Claimed At (ms)', required: false }),\n next_retry_at: Field.number({ label: 'Next Retry At (ms)', required: false }),\n last_attempted_at: Field.number({ label: 'Last Attempted At (ms)', required: false }),\n response_code: Field.number({ label: 'HTTP Status', required: false }),\n response_body: Field.textarea({ label: 'Response Body (capped)', required: false }),\n error: Field.textarea({ label: 'Error', required: false }),\n\n created_at: Field.number({ label: 'Created At (ms)', required: true }),\n updated_at: Field.number({ label: 'Updated At (ms)', required: true }),\n },\n\n indexes: [\n { fields: ['event_id', 'webhook_id'], unique: true },\n // Hot path: claim query\n { fields: ['status', 'partition_key', 'next_retry_at'] },\n // Reaper: scan stale in_flight rows by claimed_at\n { fields: ['status', 'claimed_at'] },\n { fields: ['webhook_id'] },\n ],\n});\n\n/** Canonical object name — exported so SqlWebhookOutbox callers can override if needed. */\nexport const SYS_WEBHOOK_DELIVERY = 'sys_webhook_delivery' as const;\n"]}