@objectstack/plugin-webhooks 17.0.0 → 17.1.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.
- package/CHANGELOG.md +214 -0
- package/dist/{chunk-Q4FEMGD6.cjs → chunk-DRHJ2M45.cjs} +61 -2
- package/dist/chunk-DRHJ2M45.cjs.map +1 -0
- package/dist/{chunk-GDCWDVDT.js → chunk-XERWWQKN.js} +61 -2
- package/dist/{chunk-GDCWDVDT.js.map → chunk-XERWWQKN.js.map} +1 -1
- package/dist/index.cjs +135 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -1
- package/dist/index.d.ts +66 -1
- package/dist/index.js +106 -3
- package/dist/index.js.map +1 -1
- package/dist/schema.cjs +2 -2
- package/dist/schema.d.cts +1188 -269
- package/dist/schema.d.ts +1188 -269
- package/dist/schema.js +1 -1
- package/dist/{translations-U32QIEPB.js → translations-IAKF6NAP.js} +1 -1
- package/dist/translations-IAKF6NAP.js.map +1 -0
- package/dist/{translations-H5ZYI6YP.cjs → translations-IHRALWSP.cjs} +1 -1
- package/dist/translations-IHRALWSP.cjs.map +1 -0
- package/package.json +7 -7
- package/dist/chunk-Q4FEMGD6.cjs.map +0 -1
- package/dist/translations-H5ZYI6YP.cjs.map +0 -1
- package/dist/translations-U32QIEPB.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -572,6 +572,71 @@ declare const WEBHOOK_SECRET_FIELD = "signing_secret";
|
|
|
572
572
|
/** Column on `sys_webhook` holding the encrypted custom-header map. */
|
|
573
573
|
declare const WEBHOOK_HEADERS_FIELD = "headers_secret";
|
|
574
574
|
|
|
575
|
+
/**
|
|
576
|
+
* ADR-0112 envelope for this refusal. `VALIDATION_ERROR`/400 is the standard
|
|
577
|
+
* catalog member for "the payload is not acceptable" — the SAME pair #8559's
|
|
578
|
+
* `EmptyCredentialWriteError` carries at the same door for the same class of
|
|
579
|
+
* verdict, so a client branching on `code`/`status` handles both malformed
|
|
580
|
+
* credential writes identically. A standard-catalog code needs no ledger entry.
|
|
581
|
+
*/
|
|
582
|
+
declare const WEBHOOK_HEADERS_SHAPE_REFUSAL_CODE = "VALIDATION_ERROR";
|
|
583
|
+
declare const WEBHOOK_HEADERS_SHAPE_REFUSAL_STATUS = 400;
|
|
584
|
+
/**
|
|
585
|
+
* [#8566] Refusal to persist a `headers_secret` plaintext that is not a flat
|
|
586
|
+
* JSON object of string values.
|
|
587
|
+
*
|
|
588
|
+
* Carries the ADR-0112 pair plus the LOCATION (`object`/`field`) as fields, so
|
|
589
|
+
* a consumer branches on `code`/`status` rather than on message text — the same
|
|
590
|
+
* discipline {@link WebhookHeadersUnresolvableError} follows on the read side
|
|
591
|
+
* of this seam, and `EmptyCredentialWriteError` follows on the write side.
|
|
592
|
+
*/
|
|
593
|
+
declare class WebhookHeadersShapeError extends Error {
|
|
594
|
+
readonly code = "VALIDATION_ERROR";
|
|
595
|
+
readonly status = 400;
|
|
596
|
+
readonly object: string;
|
|
597
|
+
readonly field: string;
|
|
598
|
+
constructor(object: string, field: string, diagnosis: string);
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* The verdict, as a pure function of the write payload — exported so the gate
|
|
602
|
+
* can be reasoned about and tested without booting an engine, and so any future
|
|
603
|
+
* caller uses the same one rule rather than restating it.
|
|
604
|
+
*
|
|
605
|
+
* Mutates nothing and returns nothing: it either passes or throws
|
|
606
|
+
* {@link WebhookHeadersShapeError}.
|
|
607
|
+
*/
|
|
608
|
+
declare function assertWritableWebhookHeaders(data: Record<string, unknown> | null | undefined, object?: string, field?: string): void;
|
|
609
|
+
/** Minimal engine surface this binding needs — mirrors `webhook-provenance.ts`. */
|
|
610
|
+
interface MinimalEngine {
|
|
611
|
+
registerHook(event: string, handler: (ctx: any) => any, options?: Record<string, any>): void;
|
|
612
|
+
unregisterHooksByPackage(packageId: string): number;
|
|
613
|
+
}
|
|
614
|
+
interface MinimalLogger {
|
|
615
|
+
info?: (msg: string, meta?: Record<string, any>) => void;
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Bind the shape gate to both write events on `sys_webhook`.
|
|
619
|
+
*
|
|
620
|
+
* ## Deliberately NOT exempt for `isSystem`
|
|
621
|
+
* The provenance stamp next door skips system writes because it is detecting an
|
|
622
|
+
* ADMIN edit; this is a validity verdict on a payload, and a malformed header
|
|
623
|
+
* map is exactly as unusable when a seeder writes it. Ruling item 2 says the
|
|
624
|
+
* plugin's own write paths inherit this validation through the hook, which is
|
|
625
|
+
* only true if system writes are covered. They pass by construction —
|
|
626
|
+
* `bootstrapDeclaredWebhooks` and the migration sweep both write
|
|
627
|
+
* `serializeHeaders(...)` of an already `isHeaderMap`-filtered map — so
|
|
628
|
+
* covering them costs nothing and closes the door for a future write path that
|
|
629
|
+
* is less careful.
|
|
630
|
+
*
|
|
631
|
+
* Registered in CODE rather than from metadata, which also means
|
|
632
|
+
* `session.skipAutomations` (an import run with automations unchecked) cannot
|
|
633
|
+
* suppress it: the engine only skips metadata-bound entries. A validation door
|
|
634
|
+
* that an import could switch off would not be a door.
|
|
635
|
+
*/
|
|
636
|
+
declare function bindWebhookHeadersShapeGate(engine: MinimalEngine, logger?: MinimalLogger): void;
|
|
637
|
+
/** Remove the gate — mirrors `unbindWebhookProvenanceStamp`, for `dispose()`. */
|
|
638
|
+
declare function unbindWebhookHeadersShapeGate(engine: MinimalEngine): void;
|
|
639
|
+
|
|
575
640
|
/**
|
|
576
641
|
* [#7799] One-shot boot sweep that moves already-persisted cleartext signing
|
|
577
642
|
* secrets out of `sys_webhook.definition_json` and into the encrypted
|
|
@@ -625,4 +690,4 @@ interface MigrateWebhookSecretsResult {
|
|
|
625
690
|
*/
|
|
626
691
|
declare function migrateLegacyWebhookSecrets(engine: IDataEngine, logger?: Logger, subscriptionsObject?: string): Promise<MigrateWebhookSecretsResult>;
|
|
627
692
|
|
|
628
|
-
export { AutoEnqueuer, type AutoEnqueuerOptions, type HttpEnqueueFn, type MigrateWebhookSecretsResult, WEBHOOK_HEADERS_FIELD, WEBHOOK_SECRET_FIELD, WebhookOutboxPlugin, type WebhookOutboxPluginOptions, migrateLegacyWebhookSecrets };
|
|
693
|
+
export { AutoEnqueuer, type AutoEnqueuerOptions, type HttpEnqueueFn, type MigrateWebhookSecretsResult, WEBHOOK_HEADERS_FIELD, WEBHOOK_HEADERS_SHAPE_REFUSAL_CODE, WEBHOOK_HEADERS_SHAPE_REFUSAL_STATUS, WEBHOOK_SECRET_FIELD, WebhookHeadersShapeError, WebhookOutboxPlugin, type WebhookOutboxPluginOptions, assertWritableWebhookHeaders, bindWebhookHeadersShapeGate, migrateLegacyWebhookSecrets, unbindWebhookHeadersShapeGate };
|
package/dist/index.d.ts
CHANGED
|
@@ -572,6 +572,71 @@ declare const WEBHOOK_SECRET_FIELD = "signing_secret";
|
|
|
572
572
|
/** Column on `sys_webhook` holding the encrypted custom-header map. */
|
|
573
573
|
declare const WEBHOOK_HEADERS_FIELD = "headers_secret";
|
|
574
574
|
|
|
575
|
+
/**
|
|
576
|
+
* ADR-0112 envelope for this refusal. `VALIDATION_ERROR`/400 is the standard
|
|
577
|
+
* catalog member for "the payload is not acceptable" — the SAME pair #8559's
|
|
578
|
+
* `EmptyCredentialWriteError` carries at the same door for the same class of
|
|
579
|
+
* verdict, so a client branching on `code`/`status` handles both malformed
|
|
580
|
+
* credential writes identically. A standard-catalog code needs no ledger entry.
|
|
581
|
+
*/
|
|
582
|
+
declare const WEBHOOK_HEADERS_SHAPE_REFUSAL_CODE = "VALIDATION_ERROR";
|
|
583
|
+
declare const WEBHOOK_HEADERS_SHAPE_REFUSAL_STATUS = 400;
|
|
584
|
+
/**
|
|
585
|
+
* [#8566] Refusal to persist a `headers_secret` plaintext that is not a flat
|
|
586
|
+
* JSON object of string values.
|
|
587
|
+
*
|
|
588
|
+
* Carries the ADR-0112 pair plus the LOCATION (`object`/`field`) as fields, so
|
|
589
|
+
* a consumer branches on `code`/`status` rather than on message text — the same
|
|
590
|
+
* discipline {@link WebhookHeadersUnresolvableError} follows on the read side
|
|
591
|
+
* of this seam, and `EmptyCredentialWriteError` follows on the write side.
|
|
592
|
+
*/
|
|
593
|
+
declare class WebhookHeadersShapeError extends Error {
|
|
594
|
+
readonly code = "VALIDATION_ERROR";
|
|
595
|
+
readonly status = 400;
|
|
596
|
+
readonly object: string;
|
|
597
|
+
readonly field: string;
|
|
598
|
+
constructor(object: string, field: string, diagnosis: string);
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* The verdict, as a pure function of the write payload — exported so the gate
|
|
602
|
+
* can be reasoned about and tested without booting an engine, and so any future
|
|
603
|
+
* caller uses the same one rule rather than restating it.
|
|
604
|
+
*
|
|
605
|
+
* Mutates nothing and returns nothing: it either passes or throws
|
|
606
|
+
* {@link WebhookHeadersShapeError}.
|
|
607
|
+
*/
|
|
608
|
+
declare function assertWritableWebhookHeaders(data: Record<string, unknown> | null | undefined, object?: string, field?: string): void;
|
|
609
|
+
/** Minimal engine surface this binding needs — mirrors `webhook-provenance.ts`. */
|
|
610
|
+
interface MinimalEngine {
|
|
611
|
+
registerHook(event: string, handler: (ctx: any) => any, options?: Record<string, any>): void;
|
|
612
|
+
unregisterHooksByPackage(packageId: string): number;
|
|
613
|
+
}
|
|
614
|
+
interface MinimalLogger {
|
|
615
|
+
info?: (msg: string, meta?: Record<string, any>) => void;
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Bind the shape gate to both write events on `sys_webhook`.
|
|
619
|
+
*
|
|
620
|
+
* ## Deliberately NOT exempt for `isSystem`
|
|
621
|
+
* The provenance stamp next door skips system writes because it is detecting an
|
|
622
|
+
* ADMIN edit; this is a validity verdict on a payload, and a malformed header
|
|
623
|
+
* map is exactly as unusable when a seeder writes it. Ruling item 2 says the
|
|
624
|
+
* plugin's own write paths inherit this validation through the hook, which is
|
|
625
|
+
* only true if system writes are covered. They pass by construction —
|
|
626
|
+
* `bootstrapDeclaredWebhooks` and the migration sweep both write
|
|
627
|
+
* `serializeHeaders(...)` of an already `isHeaderMap`-filtered map — so
|
|
628
|
+
* covering them costs nothing and closes the door for a future write path that
|
|
629
|
+
* is less careful.
|
|
630
|
+
*
|
|
631
|
+
* Registered in CODE rather than from metadata, which also means
|
|
632
|
+
* `session.skipAutomations` (an import run with automations unchecked) cannot
|
|
633
|
+
* suppress it: the engine only skips metadata-bound entries. A validation door
|
|
634
|
+
* that an import could switch off would not be a door.
|
|
635
|
+
*/
|
|
636
|
+
declare function bindWebhookHeadersShapeGate(engine: MinimalEngine, logger?: MinimalLogger): void;
|
|
637
|
+
/** Remove the gate — mirrors `unbindWebhookProvenanceStamp`, for `dispose()`. */
|
|
638
|
+
declare function unbindWebhookHeadersShapeGate(engine: MinimalEngine): void;
|
|
639
|
+
|
|
575
640
|
/**
|
|
576
641
|
* [#7799] One-shot boot sweep that moves already-persisted cleartext signing
|
|
577
642
|
* secrets out of `sys_webhook.definition_json` and into the encrypted
|
|
@@ -625,4 +690,4 @@ interface MigrateWebhookSecretsResult {
|
|
|
625
690
|
*/
|
|
626
691
|
declare function migrateLegacyWebhookSecrets(engine: IDataEngine, logger?: Logger, subscriptionsObject?: string): Promise<MigrateWebhookSecretsResult>;
|
|
627
692
|
|
|
628
|
-
export { AutoEnqueuer, type AutoEnqueuerOptions, type HttpEnqueueFn, type MigrateWebhookSecretsResult, WEBHOOK_HEADERS_FIELD, WEBHOOK_SECRET_FIELD, WebhookOutboxPlugin, type WebhookOutboxPluginOptions, migrateLegacyWebhookSecrets };
|
|
693
|
+
export { AutoEnqueuer, type AutoEnqueuerOptions, type HttpEnqueueFn, type MigrateWebhookSecretsResult, WEBHOOK_HEADERS_FIELD, WEBHOOK_HEADERS_SHAPE_REFUSAL_CODE, WEBHOOK_HEADERS_SHAPE_REFUSAL_STATUS, WEBHOOK_SECRET_FIELD, WebhookHeadersShapeError, WebhookOutboxPlugin, type WebhookOutboxPluginOptions, assertWritableWebhookHeaders, bindWebhookHeadersShapeGate, migrateLegacyWebhookSecrets, unbindWebhookHeadersShapeGate };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SysWebhook
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XERWWQKN.js";
|
|
4
4
|
|
|
5
5
|
// src/webhook-secret.ts
|
|
6
6
|
var WEBHOOK_SECRET_FIELD = "signing_secret";
|
|
@@ -1062,6 +1062,98 @@ function unbindWebhookProvenanceStamp(engine) {
|
|
|
1062
1062
|
}
|
|
1063
1063
|
}
|
|
1064
1064
|
|
|
1065
|
+
// src/webhook-headers-gate.ts
|
|
1066
|
+
var WEBHOOK_HEADERS_SHAPE_REFUSAL_CODE = "VALIDATION_ERROR";
|
|
1067
|
+
var WEBHOOK_HEADERS_SHAPE_REFUSAL_STATUS = 400;
|
|
1068
|
+
var DECLARED_SHAPE = 'Custom HTTP headers sent with each delivery, as a JSON object ({"Authorization": "Bearer ..."})';
|
|
1069
|
+
var WebhookHeadersShapeError = class extends Error {
|
|
1070
|
+
constructor(object, field, diagnosis) {
|
|
1071
|
+
super(
|
|
1072
|
+
`Custom headers refused for "${object}.${field}": ${diagnosis}. The required shape is a FLAT JSON object of string values, which is what the field itself asks for \u2014 its description reads: "${DECLARED_SHAPE}". This is checked at the write door because one step later there is nothing left to check: the engine encrypts this value into sys_secret and every read path returns only the mask, so a stored value that can never be used is indistinguishable from one that works until the next delivery tries to send it \u2014 at which point the subscription parks and the report arrives an unbounded time later, in a different surface from the one it was typed into (#7986, #8558, #8566). ${HEADERS_REMEDY}`
|
|
1073
|
+
);
|
|
1074
|
+
this.code = WEBHOOK_HEADERS_SHAPE_REFUSAL_CODE;
|
|
1075
|
+
this.status = WEBHOOK_HEADERS_SHAPE_REFUSAL_STATUS;
|
|
1076
|
+
this.name = "WebhookHeadersShapeError";
|
|
1077
|
+
this.object = object;
|
|
1078
|
+
this.field = field;
|
|
1079
|
+
}
|
|
1080
|
+
};
|
|
1081
|
+
function describeParsed(parsed) {
|
|
1082
|
+
if (parsed === null) return "null";
|
|
1083
|
+
if (Array.isArray(parsed)) return "a JSON array";
|
|
1084
|
+
if (typeof parsed !== "object") return `a JSON ${typeof parsed}`;
|
|
1085
|
+
const entries = Object.entries(parsed);
|
|
1086
|
+
if (entries.length === 0) {
|
|
1087
|
+
return 'an EMPTY JSON object, which is not the same thing as "send no custom headers"';
|
|
1088
|
+
}
|
|
1089
|
+
const bad = entries.filter(([, v]) => typeof v !== "string");
|
|
1090
|
+
if (bad.length > 0) {
|
|
1091
|
+
const named = bad.map(([k, v]) => `${JSON.stringify(k)} (${Array.isArray(v) ? "array" : v === null ? "null" : typeof v})`).join(", ");
|
|
1092
|
+
return `a JSON object, but the wire carries only strings and ${bad.length === 1 ? "this value is" : "these values are"} not a string: ${named}`;
|
|
1093
|
+
}
|
|
1094
|
+
return "a JSON object the header seam does not accept";
|
|
1095
|
+
}
|
|
1096
|
+
function describeRejected(value) {
|
|
1097
|
+
if (typeof value === "string") {
|
|
1098
|
+
let parsed;
|
|
1099
|
+
try {
|
|
1100
|
+
parsed = JSON.parse(value);
|
|
1101
|
+
} catch {
|
|
1102
|
+
return "the value is a string that is not valid JSON at all \u2014 check for unquoted keys or values ({X-Team: crm}), single quotes instead of double, or a trailing comma";
|
|
1103
|
+
}
|
|
1104
|
+
return `the value parses as JSON but is ${describeParsed(parsed)}`;
|
|
1105
|
+
}
|
|
1106
|
+
return `the value is ${describeParsed(value)}`;
|
|
1107
|
+
}
|
|
1108
|
+
function assertWritableWebhookHeaders(data, object = WEBHOOK_OBJECT, field = WEBHOOK_HEADERS_FIELD) {
|
|
1109
|
+
if (!data || typeof data !== "object") return;
|
|
1110
|
+
if (!Object.prototype.hasOwnProperty.call(data, field)) return;
|
|
1111
|
+
const value = data[field];
|
|
1112
|
+
if (value === null || typeof value === "undefined") return;
|
|
1113
|
+
if (value === "") return;
|
|
1114
|
+
if (isOpaqueSecretForm(value)) return;
|
|
1115
|
+
let serialized;
|
|
1116
|
+
if (typeof value === "string") {
|
|
1117
|
+
serialized = value;
|
|
1118
|
+
} else {
|
|
1119
|
+
try {
|
|
1120
|
+
serialized = JSON.stringify(value);
|
|
1121
|
+
} catch {
|
|
1122
|
+
throw new WebhookHeadersShapeError(
|
|
1123
|
+
object,
|
|
1124
|
+
field,
|
|
1125
|
+
"the value cannot be serialized to JSON at all (it contains a circular reference)"
|
|
1126
|
+
);
|
|
1127
|
+
}
|
|
1128
|
+
if (typeof serialized !== "string") {
|
|
1129
|
+
throw new WebhookHeadersShapeError(object, field, `the value is a ${typeof value}`);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
if (parseStoredHeaders(serialized)) return;
|
|
1133
|
+
throw new WebhookHeadersShapeError(object, field, describeRejected(value));
|
|
1134
|
+
}
|
|
1135
|
+
var WEBHOOK_HEADERS_GATE_PACKAGE = "plugin-webhooks:headers-shape-gate";
|
|
1136
|
+
var GATE_PRIORITY = 50;
|
|
1137
|
+
function bindWebhookHeadersShapeGate(engine, logger) {
|
|
1138
|
+
if (typeof engine?.registerHook !== "function") return;
|
|
1139
|
+
const handler = (ctx) => {
|
|
1140
|
+
assertWritableWebhookHeaders(ctx?.input?.data);
|
|
1141
|
+
};
|
|
1142
|
+
for (const event of ["beforeInsert", "beforeUpdate"]) {
|
|
1143
|
+
engine.registerHook(event, handler, {
|
|
1144
|
+
object: WEBHOOK_OBJECT,
|
|
1145
|
+
packageId: WEBHOOK_HEADERS_GATE_PACKAGE,
|
|
1146
|
+
priority: GATE_PRIORITY
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
logger?.info?.("[webhook] headers_secret shape gate bound (refuses non-flat-string-map plaintext)");
|
|
1150
|
+
}
|
|
1151
|
+
function unbindWebhookHeadersShapeGate(engine) {
|
|
1152
|
+
if (typeof engine?.unregisterHooksByPackage === "function") {
|
|
1153
|
+
engine.unregisterHooksByPackage(WEBHOOK_HEADERS_GATE_PACKAGE);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1065
1157
|
// src/webhook-outbox-plugin.ts
|
|
1066
1158
|
var WebhookOutboxPlugin = class {
|
|
1067
1159
|
constructor(options = {}) {
|
|
@@ -1115,7 +1207,7 @@ var WebhookOutboxPlugin = class {
|
|
|
1115
1207
|
try {
|
|
1116
1208
|
const i18n = ctx.getService("i18n");
|
|
1117
1209
|
if (i18n && typeof i18n.loadTranslations === "function") {
|
|
1118
|
-
const { WebhooksTranslations } = await import("./translations-
|
|
1210
|
+
const { WebhooksTranslations } = await import("./translations-IAKF6NAP.js");
|
|
1119
1211
|
for (const [locale, data] of Object.entries(WebhooksTranslations)) {
|
|
1120
1212
|
i18n.loadTranslations(locale, data);
|
|
1121
1213
|
}
|
|
@@ -1143,6 +1235,10 @@ var WebhookOutboxPlugin = class {
|
|
|
1143
1235
|
unbindWebhookProvenanceStamp(this.boundEngine);
|
|
1144
1236
|
} catch {
|
|
1145
1237
|
}
|
|
1238
|
+
try {
|
|
1239
|
+
unbindWebhookHeadersShapeGate(this.boundEngine);
|
|
1240
|
+
} catch {
|
|
1241
|
+
}
|
|
1146
1242
|
this.boundEngine = void 0;
|
|
1147
1243
|
}
|
|
1148
1244
|
}
|
|
@@ -1170,6 +1266,7 @@ var WebhookOutboxPlugin = class {
|
|
|
1170
1266
|
}
|
|
1171
1267
|
this.boundEngine = engine;
|
|
1172
1268
|
bindWebhookProvenanceStamp(engine, ctx.logger);
|
|
1269
|
+
bindWebhookHeadersShapeGate(engine, ctx.logger);
|
|
1173
1270
|
let metadataService;
|
|
1174
1271
|
try {
|
|
1175
1272
|
metadataService = ctx.getService("metadata");
|
|
@@ -1331,8 +1428,14 @@ export {
|
|
|
1331
1428
|
AutoEnqueuer,
|
|
1332
1429
|
SysWebhook,
|
|
1333
1430
|
WEBHOOK_HEADERS_FIELD,
|
|
1431
|
+
WEBHOOK_HEADERS_SHAPE_REFUSAL_CODE,
|
|
1432
|
+
WEBHOOK_HEADERS_SHAPE_REFUSAL_STATUS,
|
|
1334
1433
|
WEBHOOK_SECRET_FIELD,
|
|
1434
|
+
WebhookHeadersShapeError,
|
|
1335
1435
|
WebhookOutboxPlugin,
|
|
1336
|
-
|
|
1436
|
+
assertWritableWebhookHeaders,
|
|
1437
|
+
bindWebhookHeadersShapeGate,
|
|
1438
|
+
migrateLegacyWebhookSecrets,
|
|
1439
|
+
unbindWebhookHeadersShapeGate
|
|
1337
1440
|
};
|
|
1338
1441
|
//# sourceMappingURL=index.js.map
|