@secondlayer/shared 6.21.0 → 6.23.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.
@@ -0,0 +1,22 @@
1
+ import { KeyObject } from "node:crypto";
2
+ /**
3
+ * Asymmetric ed25519 signing for Streams response proofs.
4
+ *
5
+ * Asymmetric (not HMAC) so the proof is real: only the server holds the private
6
+ * key, and any consumer verifies with the published public key — no shared
7
+ * secret to leak. ed25519 uses node's `sign`/`verify` with a `null` algorithm.
8
+ * Keys are PEM (PKCS8 private / SPKI public) for env transport; load once and
9
+ * reuse the KeyObject on hot paths.
10
+ */
11
+ declare function generateEd25519KeyPair(): {
12
+ privateKeyPem: string
13
+ publicKeyPem: string
14
+ };
15
+ declare function loadEd25519PrivateKey(pem: string): KeyObject;
16
+ declare function loadEd25519PublicKey(pem: string): KeyObject;
17
+ declare function publicKeyPemFromPrivate(privateKeyPem: string): string;
18
+ /** Stable short id for a public key (rotation hint via X-Signature-KeyId). */
19
+ declare function ed25519KeyId(publicKeyPem: string): string;
20
+ declare function signEd25519(payload: string, privateKey: KeyObject): string;
21
+ declare function verifyEd25519(payload: string, signatureBase64: string, publicKey: KeyObject): boolean;
22
+ export { verifyEd25519, signEd25519, publicKeyPemFromPrivate, loadEd25519PublicKey, loadEd25519PrivateKey, generateEd25519KeyPair, ed25519KeyId };
@@ -0,0 +1,80 @@
1
+ import { createRequire } from "node:module";
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+
17
+ // src/crypto/ed25519.ts
18
+ var exports_ed25519 = {};
19
+ __export(exports_ed25519, {
20
+ verifyEd25519: () => verifyEd25519,
21
+ signEd25519: () => signEd25519,
22
+ publicKeyPemFromPrivate: () => publicKeyPemFromPrivate,
23
+ loadEd25519PublicKey: () => loadEd25519PublicKey,
24
+ loadEd25519PrivateKey: () => loadEd25519PrivateKey,
25
+ generateEd25519KeyPair: () => generateEd25519KeyPair,
26
+ ed25519KeyId: () => ed25519KeyId
27
+ });
28
+ import {
29
+ createHash,
30
+ createPrivateKey,
31
+ createPublicKey,
32
+ generateKeyPairSync,
33
+ sign as nodeSign,
34
+ verify as nodeVerify
35
+ } from "node:crypto";
36
+ function generateEd25519KeyPair() {
37
+ const { privateKey, publicKey } = generateKeyPairSync("ed25519");
38
+ return {
39
+ privateKeyPem: privateKey.export({ format: "pem", type: "pkcs8" }).toString(),
40
+ publicKeyPem: publicKey.export({ format: "pem", type: "spki" }).toString()
41
+ };
42
+ }
43
+ function loadEd25519PrivateKey(pem) {
44
+ return createPrivateKey(pem);
45
+ }
46
+ function loadEd25519PublicKey(pem) {
47
+ return createPublicKey(pem);
48
+ }
49
+ function publicKeyPemFromPrivate(privateKeyPem) {
50
+ return createPublicKey(createPrivateKey(privateKeyPem)).export({ format: "pem", type: "spki" }).toString();
51
+ }
52
+ function ed25519KeyId(publicKeyPem) {
53
+ const der = createPublicKey(publicKeyPem).export({
54
+ format: "der",
55
+ type: "spki"
56
+ });
57
+ return createHash("sha256").update(der).digest("base64url").slice(0, 16);
58
+ }
59
+ function signEd25519(payload, privateKey) {
60
+ return nodeSign(null, Buffer.from(payload, "utf8"), privateKey).toString("base64");
61
+ }
62
+ function verifyEd25519(payload, signatureBase64, publicKey) {
63
+ try {
64
+ return nodeVerify(null, Buffer.from(payload, "utf8"), publicKey, Buffer.from(signatureBase64, "base64"));
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+ export {
70
+ verifyEd25519,
71
+ signEd25519,
72
+ publicKeyPemFromPrivate,
73
+ loadEd25519PublicKey,
74
+ loadEd25519PrivateKey,
75
+ generateEd25519KeyPair,
76
+ ed25519KeyId
77
+ };
78
+
79
+ //# debugId=B4FC95F24211B0D064756E2164756E21
80
+ //# sourceMappingURL=ed25519.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/crypto/ed25519.ts"],
4
+ "sourcesContent": [
5
+ "import {\n\ttype KeyObject,\n\tcreateHash,\n\tcreatePrivateKey,\n\tcreatePublicKey,\n\tgenerateKeyPairSync,\n\tsign as nodeSign,\n\tverify as nodeVerify,\n} from \"node:crypto\";\n\n/**\n * Asymmetric ed25519 signing for Streams response proofs.\n *\n * Asymmetric (not HMAC) so the proof is real: only the server holds the private\n * key, and any consumer verifies with the published public key — no shared\n * secret to leak. ed25519 uses node's `sign`/`verify` with a `null` algorithm.\n * Keys are PEM (PKCS8 private / SPKI public) for env transport; load once and\n * reuse the KeyObject on hot paths.\n */\n\nexport function generateEd25519KeyPair(): {\n\tprivateKeyPem: string;\n\tpublicKeyPem: string;\n} {\n\tconst { privateKey, publicKey } = generateKeyPairSync(\"ed25519\");\n\treturn {\n\t\tprivateKeyPem: privateKey\n\t\t\t.export({ format: \"pem\", type: \"pkcs8\" })\n\t\t\t.toString(),\n\t\tpublicKeyPem: publicKey.export({ format: \"pem\", type: \"spki\" }).toString(),\n\t};\n}\n\nexport function loadEd25519PrivateKey(pem: string): KeyObject {\n\treturn createPrivateKey(pem);\n}\n\nexport function loadEd25519PublicKey(pem: string): KeyObject {\n\treturn createPublicKey(pem);\n}\n\nexport function publicKeyPemFromPrivate(privateKeyPem: string): string {\n\treturn createPublicKey(createPrivateKey(privateKeyPem))\n\t\t.export({ format: \"pem\", type: \"spki\" })\n\t\t.toString();\n}\n\n/** Stable short id for a public key (rotation hint via X-Signature-KeyId). */\nexport function ed25519KeyId(publicKeyPem: string): string {\n\tconst der = createPublicKey(publicKeyPem).export({\n\t\tformat: \"der\",\n\t\ttype: \"spki\",\n\t});\n\treturn createHash(\"sha256\").update(der).digest(\"base64url\").slice(0, 16);\n}\n\nexport function signEd25519(payload: string, privateKey: KeyObject): string {\n\treturn nodeSign(null, Buffer.from(payload, \"utf8\"), privateKey).toString(\n\t\t\"base64\",\n\t);\n}\n\nexport function verifyEd25519(\n\tpayload: string,\n\tsignatureBase64: string,\n\tpublicKey: KeyObject,\n): boolean {\n\ttry {\n\t\treturn nodeVerify(\n\t\t\tnull,\n\t\t\tBuffer.from(payload, \"utf8\"),\n\t\t\tpublicKey,\n\t\t\tBuffer.from(signatureBase64, \"base64\"),\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n"
6
+ ],
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMC;AAAA,YACA;AAAA;AAaM,SAAS,sBAAsB,GAGpC;AAAA,EACD,QAAQ,YAAY,cAAc,oBAAoB,SAAS;AAAA,EAC/D,OAAO;AAAA,IACN,eAAe,WACb,OAAO,EAAE,QAAQ,OAAO,MAAM,QAAQ,CAAC,EACvC,SAAS;AAAA,IACX,cAAc,UAAU,OAAO,EAAE,QAAQ,OAAO,MAAM,OAAO,CAAC,EAAE,SAAS;AAAA,EAC1E;AAAA;AAGM,SAAS,qBAAqB,CAAC,KAAwB;AAAA,EAC7D,OAAO,iBAAiB,GAAG;AAAA;AAGrB,SAAS,oBAAoB,CAAC,KAAwB;AAAA,EAC5D,OAAO,gBAAgB,GAAG;AAAA;AAGpB,SAAS,uBAAuB,CAAC,eAA+B;AAAA,EACtE,OAAO,gBAAgB,iBAAiB,aAAa,CAAC,EACpD,OAAO,EAAE,QAAQ,OAAO,MAAM,OAAO,CAAC,EACtC,SAAS;AAAA;AAIL,SAAS,YAAY,CAAC,cAA8B;AAAA,EAC1D,MAAM,MAAM,gBAAgB,YAAY,EAAE,OAAO;AAAA,IAChD,QAAQ;AAAA,IACR,MAAM;AAAA,EACP,CAAC;AAAA,EACD,OAAO,WAAW,QAAQ,EAAE,OAAO,GAAG,EAAE,OAAO,WAAW,EAAE,MAAM,GAAG,EAAE;AAAA;AAGjE,SAAS,WAAW,CAAC,SAAiB,YAA+B;AAAA,EAC3E,OAAO,SAAS,MAAM,OAAO,KAAK,SAAS,MAAM,GAAG,UAAU,EAAE,SAC/D,QACD;AAAA;AAGM,SAAS,aAAa,CAC5B,SACA,iBACA,WACU;AAAA,EACV,IAAI;AAAA,IACH,OAAO,WACN,MACA,OAAO,KAAK,SAAS,MAAM,GAC3B,WACA,OAAO,KAAK,iBAAiB,QAAQ,CACtC;AAAA,IACC,MAAM;AAAA,IACP,OAAO;AAAA;AAAA;",
8
+ "debugId": "B4FC95F24211B0D064756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Universal Secondlayer webhook authenticity — an ed25519 signature attached to
3
+ * EVERY delivery regardless of body format.
4
+ *
5
+ * Only the `standard-webhooks` format carries an HMAC; `raw`/`cloudevents`/etc.
6
+ * carried no Secondlayer proof, so a receiver had no way to know a payload came
7
+ * from us. This signs each delivery with a single platform ed25519 key so any
8
+ * receiver verifies with the published public key — no per-subscription secret,
9
+ * and the body shape stays format-specific.
10
+ *
11
+ * Header names are lowercase to match the format builders' header maps (HTTP
12
+ * header names are case-insensitive on the wire).
13
+ */
14
+ declare const WEBHOOK_ID_HEADER = "webhook-id";
15
+ declare const SECONDLAYER_SIGNATURE_HEADER = "x-secondlayer-signature";
16
+ declare const SECONDLAYER_KEY_ID_HEADER = "x-secondlayer-signature-keyid";
17
+ type SecondlayerWebhookSigner = {
18
+ keyId: string
19
+ publicKeyPem: string
20
+ sign(payload: string): string
21
+ };
22
+ /**
23
+ * Memoized webhook signer, or null when no key is configured (signing is then a
24
+ * no-op, so the universal header is safe to ship before a key is provisioned).
25
+ */
26
+ declare function getSecondlayerWebhookSigner(): SecondlayerWebhookSigner | null;
27
+ /** Reset the memoized signer. Tests only. */
28
+ declare function resetSecondlayerWebhookSignerForTest(): void;
29
+ /**
30
+ * Build the universal authenticity headers for a delivery. Returns null when no
31
+ * signing key is configured (caller leaves the delivery unsigned).
32
+ */
33
+ declare function signSecondlayerWebhook(webhookId: string, body: string): Record<string, string> | null;
34
+ /**
35
+ * Verify a delivery's ed25519 signature over `${webhookId}.${rawBody}` against
36
+ * the published public key. Low-level (raw values); receivers use the SDK's
37
+ * `verifySecondlayerSignature`, which extracts the headers ergonomically.
38
+ */
39
+ declare function verifySecondlayerSignatureValues(rawBody: string, webhookId: string | undefined, signatureBase64: string | undefined, publicKeyPem: string): boolean;
40
+ export { verifySecondlayerSignatureValues, signSecondlayerWebhook, resetSecondlayerWebhookSignerForTest, getSecondlayerWebhookSigner, WEBHOOK_ID_HEADER, SecondlayerWebhookSigner, SECONDLAYER_SIGNATURE_HEADER, SECONDLAYER_KEY_ID_HEADER };
@@ -0,0 +1,130 @@
1
+ import { createRequire } from "node:module";
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+
17
+ // src/crypto/ed25519.ts
18
+ var exports_ed25519 = {};
19
+ __export(exports_ed25519, {
20
+ verifyEd25519: () => verifyEd25519,
21
+ signEd25519: () => signEd25519,
22
+ publicKeyPemFromPrivate: () => publicKeyPemFromPrivate,
23
+ loadEd25519PublicKey: () => loadEd25519PublicKey,
24
+ loadEd25519PrivateKey: () => loadEd25519PrivateKey,
25
+ generateEd25519KeyPair: () => generateEd25519KeyPair,
26
+ ed25519KeyId: () => ed25519KeyId
27
+ });
28
+ import {
29
+ createHash,
30
+ createPrivateKey,
31
+ createPublicKey,
32
+ generateKeyPairSync,
33
+ sign as nodeSign,
34
+ verify as nodeVerify
35
+ } from "node:crypto";
36
+ function generateEd25519KeyPair() {
37
+ const { privateKey, publicKey } = generateKeyPairSync("ed25519");
38
+ return {
39
+ privateKeyPem: privateKey.export({ format: "pem", type: "pkcs8" }).toString(),
40
+ publicKeyPem: publicKey.export({ format: "pem", type: "spki" }).toString()
41
+ };
42
+ }
43
+ function loadEd25519PrivateKey(pem) {
44
+ return createPrivateKey(pem);
45
+ }
46
+ function loadEd25519PublicKey(pem) {
47
+ return createPublicKey(pem);
48
+ }
49
+ function publicKeyPemFromPrivate(privateKeyPem) {
50
+ return createPublicKey(createPrivateKey(privateKeyPem)).export({ format: "pem", type: "spki" }).toString();
51
+ }
52
+ function ed25519KeyId(publicKeyPem) {
53
+ const der = createPublicKey(publicKeyPem).export({
54
+ format: "der",
55
+ type: "spki"
56
+ });
57
+ return createHash("sha256").update(der).digest("base64url").slice(0, 16);
58
+ }
59
+ function signEd25519(payload, privateKey) {
60
+ return nodeSign(null, Buffer.from(payload, "utf8"), privateKey).toString("base64");
61
+ }
62
+ function verifyEd25519(payload, signatureBase64, publicKey) {
63
+ try {
64
+ return nodeVerify(null, Buffer.from(payload, "utf8"), publicKey, Buffer.from(signatureBase64, "base64"));
65
+ } catch {
66
+ return false;
67
+ }
68
+ }
69
+
70
+ // src/crypto/secondlayer-webhook.ts
71
+ var WEBHOOK_ID_HEADER = "webhook-id";
72
+ var SECONDLAYER_SIGNATURE_HEADER = "x-secondlayer-signature";
73
+ var SECONDLAYER_KEY_ID_HEADER = "x-secondlayer-signature-keyid";
74
+ var cached;
75
+ function signingKeyFromEnv() {
76
+ return process.env.SECONDLAYER_WEBHOOK_SIGNING_PRIVATE_KEY || process.env.STREAMS_SIGNING_PRIVATE_KEY || undefined;
77
+ }
78
+ function getSecondlayerWebhookSigner() {
79
+ if (cached !== undefined)
80
+ return cached;
81
+ const raw = signingKeyFromEnv();
82
+ if (!raw) {
83
+ cached = null;
84
+ return null;
85
+ }
86
+ const pem = raw.includes("\\n") ? raw.replace(/\\n/g, `
87
+ `) : raw;
88
+ const privateKey = loadEd25519PrivateKey(pem);
89
+ const publicKeyPem = publicKeyPemFromPrivate(pem);
90
+ cached = {
91
+ keyId: ed25519KeyId(publicKeyPem),
92
+ publicKeyPem,
93
+ sign: (payload) => signEd25519(payload, privateKey)
94
+ };
95
+ return cached;
96
+ }
97
+ function resetSecondlayerWebhookSignerForTest() {
98
+ cached = undefined;
99
+ }
100
+ function signedContent(webhookId, body) {
101
+ return `${webhookId}.${body}`;
102
+ }
103
+ function signSecondlayerWebhook(webhookId, body) {
104
+ const signer = getSecondlayerWebhookSigner();
105
+ if (!signer)
106
+ return null;
107
+ return {
108
+ [WEBHOOK_ID_HEADER]: webhookId,
109
+ [SECONDLAYER_SIGNATURE_HEADER]: signer.sign(signedContent(webhookId, body)),
110
+ [SECONDLAYER_KEY_ID_HEADER]: signer.keyId
111
+ };
112
+ }
113
+ function verifySecondlayerSignatureValues(rawBody, webhookId, signatureBase64, publicKeyPem) {
114
+ if (!webhookId || !signatureBase64)
115
+ return false;
116
+ const publicKey = loadEd25519PublicKey(publicKeyPem);
117
+ return verifyEd25519(signedContent(webhookId, rawBody), signatureBase64, publicKey);
118
+ }
119
+ export {
120
+ verifySecondlayerSignatureValues,
121
+ signSecondlayerWebhook,
122
+ resetSecondlayerWebhookSignerForTest,
123
+ getSecondlayerWebhookSigner,
124
+ WEBHOOK_ID_HEADER,
125
+ SECONDLAYER_SIGNATURE_HEADER,
126
+ SECONDLAYER_KEY_ID_HEADER
127
+ };
128
+
129
+ //# debugId=ECECE08A1A6DA84764756E2164756E21
130
+ //# sourceMappingURL=secondlayer-webhook.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/crypto/ed25519.ts", "../src/crypto/secondlayer-webhook.ts"],
4
+ "sourcesContent": [
5
+ "import {\n\ttype KeyObject,\n\tcreateHash,\n\tcreatePrivateKey,\n\tcreatePublicKey,\n\tgenerateKeyPairSync,\n\tsign as nodeSign,\n\tverify as nodeVerify,\n} from \"node:crypto\";\n\n/**\n * Asymmetric ed25519 signing for Streams response proofs.\n *\n * Asymmetric (not HMAC) so the proof is real: only the server holds the private\n * key, and any consumer verifies with the published public key — no shared\n * secret to leak. ed25519 uses node's `sign`/`verify` with a `null` algorithm.\n * Keys are PEM (PKCS8 private / SPKI public) for env transport; load once and\n * reuse the KeyObject on hot paths.\n */\n\nexport function generateEd25519KeyPair(): {\n\tprivateKeyPem: string;\n\tpublicKeyPem: string;\n} {\n\tconst { privateKey, publicKey } = generateKeyPairSync(\"ed25519\");\n\treturn {\n\t\tprivateKeyPem: privateKey\n\t\t\t.export({ format: \"pem\", type: \"pkcs8\" })\n\t\t\t.toString(),\n\t\tpublicKeyPem: publicKey.export({ format: \"pem\", type: \"spki\" }).toString(),\n\t};\n}\n\nexport function loadEd25519PrivateKey(pem: string): KeyObject {\n\treturn createPrivateKey(pem);\n}\n\nexport function loadEd25519PublicKey(pem: string): KeyObject {\n\treturn createPublicKey(pem);\n}\n\nexport function publicKeyPemFromPrivate(privateKeyPem: string): string {\n\treturn createPublicKey(createPrivateKey(privateKeyPem))\n\t\t.export({ format: \"pem\", type: \"spki\" })\n\t\t.toString();\n}\n\n/** Stable short id for a public key (rotation hint via X-Signature-KeyId). */\nexport function ed25519KeyId(publicKeyPem: string): string {\n\tconst der = createPublicKey(publicKeyPem).export({\n\t\tformat: \"der\",\n\t\ttype: \"spki\",\n\t});\n\treturn createHash(\"sha256\").update(der).digest(\"base64url\").slice(0, 16);\n}\n\nexport function signEd25519(payload: string, privateKey: KeyObject): string {\n\treturn nodeSign(null, Buffer.from(payload, \"utf8\"), privateKey).toString(\n\t\t\"base64\",\n\t);\n}\n\nexport function verifyEd25519(\n\tpayload: string,\n\tsignatureBase64: string,\n\tpublicKey: KeyObject,\n): boolean {\n\ttry {\n\t\treturn nodeVerify(\n\t\t\tnull,\n\t\t\tBuffer.from(payload, \"utf8\"),\n\t\t\tpublicKey,\n\t\t\tBuffer.from(signatureBase64, \"base64\"),\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n",
6
+ "import {\n\ted25519KeyId,\n\tloadEd25519PrivateKey,\n\tloadEd25519PublicKey,\n\tpublicKeyPemFromPrivate,\n\tsignEd25519,\n\tverifyEd25519,\n} from \"./ed25519.ts\";\n\n/**\n * Universal Secondlayer webhook authenticity — an ed25519 signature attached to\n * EVERY delivery regardless of body format.\n *\n * Only the `standard-webhooks` format carries an HMAC; `raw`/`cloudevents`/etc.\n * carried no Secondlayer proof, so a receiver had no way to know a payload came\n * from us. This signs each delivery with a single platform ed25519 key so any\n * receiver verifies with the published public key — no per-subscription secret,\n * and the body shape stays format-specific.\n *\n * Header names are lowercase to match the format builders' header maps (HTTP\n * header names are case-insensitive on the wire).\n */\nexport const WEBHOOK_ID_HEADER = \"webhook-id\";\nexport const SECONDLAYER_SIGNATURE_HEADER = \"x-secondlayer-signature\";\nexport const SECONDLAYER_KEY_ID_HEADER = \"x-secondlayer-signature-keyid\";\n\nexport type SecondlayerWebhookSigner = {\n\tkeyId: string;\n\tpublicKeyPem: string;\n\tsign(payload: string): string;\n};\n\nlet cached: SecondlayerWebhookSigner | null | undefined;\n\nfunction signingKeyFromEnv(): string | undefined {\n\t// A dedicated webhook key if provided, else the platform Streams key — both\n\t// are the same ed25519 \"single platform identity\", so reusing it keeps key\n\t// distribution to one published public key.\n\treturn (\n\t\tprocess.env.SECONDLAYER_WEBHOOK_SIGNING_PRIVATE_KEY ||\n\t\tprocess.env.STREAMS_SIGNING_PRIVATE_KEY ||\n\t\tundefined\n\t);\n}\n\n/**\n * Memoized webhook signer, or null when no key is configured (signing is then a\n * no-op, so the universal header is safe to ship before a key is provisioned).\n */\nexport function getSecondlayerWebhookSigner(): SecondlayerWebhookSigner | null {\n\tif (cached !== undefined) return cached;\n\tconst raw = signingKeyFromEnv();\n\tif (!raw) {\n\t\tcached = null;\n\t\treturn null;\n\t}\n\t// Env transport often escapes newlines; restore real PEM line breaks.\n\tconst pem = raw.includes(\"\\\\n\") ? raw.replace(/\\\\n/g, \"\\n\") : raw;\n\tconst privateKey = loadEd25519PrivateKey(pem);\n\tconst publicKeyPem = publicKeyPemFromPrivate(pem);\n\tcached = {\n\t\tkeyId: ed25519KeyId(publicKeyPem),\n\t\tpublicKeyPem,\n\t\tsign: (payload) => signEd25519(payload, privateKey),\n\t};\n\treturn cached;\n}\n\n/** Reset the memoized signer. Tests only. */\nexport function resetSecondlayerWebhookSignerForTest(): void {\n\tcached = undefined;\n}\n\n/**\n * The exact bytes the signature covers: `${webhookId}.${body}`. Binding the id\n * into the signed content stops a captured body from being replayed under a\n * different delivery id.\n */\nfunction signedContent(webhookId: string, body: string): string {\n\treturn `${webhookId}.${body}`;\n}\n\n/**\n * Build the universal authenticity headers for a delivery. Returns null when no\n * signing key is configured (caller leaves the delivery unsigned).\n */\nexport function signSecondlayerWebhook(\n\twebhookId: string,\n\tbody: string,\n): Record<string, string> | null {\n\tconst signer = getSecondlayerWebhookSigner();\n\tif (!signer) return null;\n\treturn {\n\t\t[WEBHOOK_ID_HEADER]: webhookId,\n\t\t[SECONDLAYER_SIGNATURE_HEADER]: signer.sign(signedContent(webhookId, body)),\n\t\t[SECONDLAYER_KEY_ID_HEADER]: signer.keyId,\n\t};\n}\n\n/**\n * Verify a delivery's ed25519 signature over `${webhookId}.${rawBody}` against\n * the published public key. Low-level (raw values); receivers use the SDK's\n * `verifySecondlayerSignature`, which extracts the headers ergonomically.\n */\nexport function verifySecondlayerSignatureValues(\n\trawBody: string,\n\twebhookId: string | undefined,\n\tsignatureBase64: string | undefined,\n\tpublicKeyPem: string,\n): boolean {\n\tif (!webhookId || !signatureBase64) return false;\n\tconst publicKey = loadEd25519PublicKey(publicKeyPem);\n\treturn verifyEd25519(\n\t\tsignedContent(webhookId, rawBody),\n\t\tsignatureBase64,\n\t\tpublicKey,\n\t);\n}\n"
7
+ ],
8
+ "mappings": "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",
9
+ "debugId": "ECECE08A1A6DA84764756E2164756E21",
10
+ "names": []
11
+ }
@@ -948,6 +948,113 @@ declare const SOURCE_READ_COLUMNS: {
948
948
  readonly events: readonly ["block_height", "data", "event_index", "tx_id", "type"]
949
949
  readonly chain_reorgs: readonly ["detected_at"]
950
950
  };
951
+ /**
952
+ * Per-migration DB-plane gating for the source/target split.
953
+ *
954
+ * Under the split, SOURCE (chain DB) holds only chain+decoded tables — the
955
+ * control-plane tables were dropped to reclaim space — while TARGET (platform
956
+ * DB) holds the control plane. `migrate.ts` still runs EVERY migration on EVERY
957
+ * database (kysely integrity: the provider set must never be filtered per-DB, or
958
+ * kysely throws "previously executed migration is missing" because each DB's
959
+ * `kysely_migration` already records all of them). Instead, `migrate.ts` sets a
960
+ * role before each pass and a migration gates its DDL with the helpers below: a
961
+ * control migration's `up()` is a no-op on SOURCE but is still recorded applied,
962
+ * so there is no missing-migration error and no re-run.
963
+ *
964
+ * `'both'` is single-DB / collapsed-split mode (dev / OSS / CI): every helper
965
+ * runs, identical to pre-split behavior.
966
+ *
967
+ * Authoring a new migration under the split:
968
+ * async function up(db: Kysely<unknown>): Promise<void> {
969
+ * await onControlPlane(() => sql`ALTER TABLE accounts ADD COLUMN …`.execute(db));
970
+ * await onChainPlane(() => sql`ALTER TABLE blocks ADD COLUMN …`.execute(db));
971
+ * // schema-wide / mixed statements: leave unwrapped (run on both).
972
+ * }
973
+ */
974
+ type MigrationRole = "source" | "target" | "both";
975
+ declare function setMigrationRole(role: MigrationRole): void;
976
+ declare function getMigrationRole(): MigrationRole;
977
+ /** Run control-plane (TARGET) DDL only when this pass targets the control plane. */
978
+ declare function onControlPlane(fn: () => Promise<void>): Promise<void>;
979
+ /** Run chain/decoded (SOURCE) DDL only when this pass targets the chain plane. */
980
+ declare function onChainPlane(fn: () => Promise<void>): Promise<void>;
981
+ type DbPlane = "source" | "target" | "both";
982
+ /**
983
+ * Canonical table → DB-plane mapping for the source/target split.
984
+ *
985
+ * SOURCE = chain + decoded (the `postgres` instance); TARGET = control plane
986
+ * (the `postgres-platform` instance). `both` = present/used on both planes
987
+ * (`service_heartbeats`: the indexer writes its row on SOURCE, the
988
+ * subgraph-processor writes its row on TARGET).
989
+ *
990
+ * `satisfies Record<keyof Database, DbPlane>` makes adding a table to `Database`
991
+ * without classifying it here a COMPILE error. This is the single source of
992
+ * truth for the split — `docker/SCHEMA_SPLIT.md` and the cutover script's
993
+ * `CONTROL_TABLES` mirror the `target` set (guarded by `table-plane.test.ts`).
994
+ * Use it to decide which migration helper a table's DDL belongs in
995
+ * (`onControlPlane` for `target`, `onChainPlane` for `source`).
996
+ *
997
+ * Note: `kysely_migration` / `kysely_migration_lock` are kysely-managed (not in
998
+ * `Database`) and exist on both — they are intentionally not listed here.
999
+ */
1000
+ declare const TABLE_TO_DB: {
1001
+ blocks: string
1002
+ transactions: string
1003
+ events: string
1004
+ transactions_archive: string
1005
+ events_archive: string
1006
+ dead_letter_events: string
1007
+ mempool_transactions: string
1008
+ index_progress: string
1009
+ contracts: string
1010
+ chain_reorgs: string
1011
+ decoded_events: string
1012
+ l2_decoder_checkpoints: string
1013
+ pox4_calls: string
1014
+ pox4_cycles_daily: string
1015
+ pox4_signers_daily: string
1016
+ burn_block_rewards: string
1017
+ burn_block_reward_slots: string
1018
+ sbtc_events: string
1019
+ sbtc_token_events: string
1020
+ sbtc_supply_snapshots: string
1021
+ bns_name_events: string
1022
+ bns_namespace_events: string
1023
+ bns_marketplace_events: string
1024
+ bns_names: string
1025
+ bns_namespaces: string
1026
+ accounts: string
1027
+ api_keys: string
1028
+ sessions: string
1029
+ magic_links: string
1030
+ usage_daily: string
1031
+ usage_snapshots: string
1032
+ account_insights: string
1033
+ account_agent_runs: string
1034
+ account_spend_caps: string
1035
+ processed_stripe_events: string
1036
+ tenants: string
1037
+ tenant_usage_monthly: string
1038
+ tenant_compute_addons: string
1039
+ provisioning_audit_log: string
1040
+ projects: string
1041
+ team_members: string
1042
+ team_invitations: string
1043
+ chat_sessions: string
1044
+ chat_messages: string
1045
+ subscriptions: string
1046
+ subscription_outbox: string
1047
+ subscription_deliveries: string
1048
+ trigger_evaluator_state: string
1049
+ subgraphs: string
1050
+ subgraph_operations: string
1051
+ subgraph_health_snapshots: string
1052
+ subgraph_gaps: string
1053
+ subgraph_usage_daily: string
1054
+ subgraph_processing_stats: string
1055
+ subgraph_table_snapshots: string
1056
+ service_heartbeats: string
1057
+ };
951
1058
  interface DbSplitStatus {
952
1059
  /** "split" when source/target resolve to different DBs, else "single". */
953
1060
  mode: "split" | "single";
@@ -1015,4 +1122,4 @@ declare function getRawClient(role?: "source" | "target"): ReturnType<typeof pos
1015
1122
  declare function getRawClientFor(url: string): ReturnType<typeof postgres>;
1016
1123
  /** Close all DB connection pools. Call in CLI commands to allow process exit. */
1017
1124
  declare function closeDb(): Promise<void>;
1018
- export { sql, parseJsonb, jsonb, getTargetDb, getSourceDb, getRawClientFor, getRawClient, getDbSplitStatus, getDb, closeDb, assertDbSplit, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateContract, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TriggerEvaluatorStateTable, TriggerEvaluatorState, TransactionsTable, TransactionsArchiveTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionStatus, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionKind, SubscriptionFormat, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, SessionsTable, Session, ServiceHeartbeatsTable, SbtcTokenEventsTable, SbtcTokenEventType, SbtcSupplySnapshotsTable, SbtcEventsTable, SbtcEventTopic, SOURCE_READ_COLUMNS, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, Pox4SignersDailyTable, Pox4FunctionName, Pox4CyclesDailyTable, Pox4CallsTable, OutboxStatus, NumericAsText, MempoolTransactionsTable, MempoolTransaction, MagicLinksTable, MagicLink, L2DecoderCheckpointsTable, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMempoolTransaction, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertContract, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, EventsArchiveTable, Event, DecodedEventsTable, DeadLetterEventsTable, DbSplitStatus, DbReadRow, Database, ContractsTable, Contract, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, ChainReorgsTable, BurnBlockRewardsTable, BurnBlockRewardSlotsTable, BnsNamespacesTable, BnsNamespaceEventsTable, BnsNamespaceEventStatus, BnsNamesTable, BnsNameEventsTable, BnsNameEventTopic, BnsMarketplaceEventsTable, BnsMarketplaceAction, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
1125
+ export { sql, setMigrationRole, parseJsonb, onControlPlane, onChainPlane, jsonb, getTargetDb, getSourceDb, getRawClientFor, getRawClient, getMigrationRole, getDbSplitStatus, getDb, closeDb, assertDbSplit, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateContract, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TriggerEvaluatorStateTable, TriggerEvaluatorState, TransactionsTable, TransactionsArchiveTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, TABLE_TO_DB, SubscriptionsTable, SubscriptionStatus, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionKind, SubscriptionFormat, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, SessionsTable, Session, ServiceHeartbeatsTable, SbtcTokenEventsTable, SbtcTokenEventType, SbtcSupplySnapshotsTable, SbtcEventsTable, SbtcEventTopic, SOURCE_READ_COLUMNS, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, Pox4SignersDailyTable, Pox4FunctionName, Pox4CyclesDailyTable, Pox4CallsTable, OutboxStatus, NumericAsText, MigrationRole, MempoolTransactionsTable, MempoolTransaction, MagicLinksTable, MagicLink, L2DecoderCheckpointsTable, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMempoolTransaction, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertContract, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, EventsArchiveTable, Event, DecodedEventsTable, DeadLetterEventsTable, DbSplitStatus, DbReadRow, DbPlane, Database, ContractsTable, Contract, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, ChainReorgsTable, BurnBlockRewardsTable, BurnBlockRewardSlotsTable, BnsNamespacesTable, BnsNamespaceEventsTable, BnsNamespaceEventStatus, BnsNamesTable, BnsNameEventsTable, BnsNameEventTopic, BnsMarketplaceEventsTable, BnsMarketplaceAction, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
@@ -378,6 +378,81 @@ var SOURCE_READ_COLUMNS = {
378
378
  events: ["block_height", "data", "event_index", "tx_id", "type"],
379
379
  chain_reorgs: ["detected_at"]
380
380
  };
381
+ // src/db/migration-role.ts
382
+ var currentRole = "both";
383
+ function setMigrationRole(role) {
384
+ currentRole = role;
385
+ }
386
+ function getMigrationRole() {
387
+ return currentRole;
388
+ }
389
+ async function onControlPlane(fn) {
390
+ if (currentRole === "target" || currentRole === "both")
391
+ await fn();
392
+ }
393
+ async function onChainPlane(fn) {
394
+ if (currentRole === "source" || currentRole === "both")
395
+ await fn();
396
+ }
397
+ // src/db/table-plane.ts
398
+ var TABLE_TO_DB = {
399
+ blocks: "source",
400
+ transactions: "source",
401
+ events: "source",
402
+ transactions_archive: "source",
403
+ events_archive: "source",
404
+ dead_letter_events: "source",
405
+ mempool_transactions: "source",
406
+ index_progress: "source",
407
+ contracts: "source",
408
+ chain_reorgs: "source",
409
+ decoded_events: "source",
410
+ l2_decoder_checkpoints: "source",
411
+ pox4_calls: "source",
412
+ pox4_cycles_daily: "source",
413
+ pox4_signers_daily: "source",
414
+ burn_block_rewards: "source",
415
+ burn_block_reward_slots: "source",
416
+ sbtc_events: "source",
417
+ sbtc_token_events: "source",
418
+ sbtc_supply_snapshots: "source",
419
+ bns_name_events: "source",
420
+ bns_namespace_events: "source",
421
+ bns_marketplace_events: "source",
422
+ bns_names: "source",
423
+ bns_namespaces: "source",
424
+ accounts: "target",
425
+ api_keys: "target",
426
+ sessions: "target",
427
+ magic_links: "target",
428
+ usage_daily: "target",
429
+ usage_snapshots: "target",
430
+ account_insights: "target",
431
+ account_agent_runs: "target",
432
+ account_spend_caps: "target",
433
+ processed_stripe_events: "target",
434
+ tenants: "target",
435
+ tenant_usage_monthly: "target",
436
+ tenant_compute_addons: "target",
437
+ provisioning_audit_log: "target",
438
+ projects: "target",
439
+ team_members: "target",
440
+ team_invitations: "target",
441
+ chat_sessions: "target",
442
+ chat_messages: "target",
443
+ subscriptions: "target",
444
+ subscription_outbox: "target",
445
+ subscription_deliveries: "target",
446
+ trigger_evaluator_state: "target",
447
+ subgraphs: "target",
448
+ subgraph_operations: "target",
449
+ subgraph_health_snapshots: "target",
450
+ subgraph_gaps: "target",
451
+ subgraph_usage_daily: "target",
452
+ subgraph_processing_stats: "target",
453
+ subgraph_table_snapshots: "target",
454
+ service_heartbeats: "both"
455
+ };
381
456
 
382
457
  // src/db/index.ts
383
458
  var DEFAULT_URL = "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
@@ -537,18 +612,23 @@ async function closeDb() {
537
612
  }
538
613
  export {
539
614
  sql2 as sql,
615
+ setMigrationRole,
540
616
  parseJsonb,
617
+ onControlPlane,
618
+ onChainPlane,
541
619
  jsonb,
542
620
  getTargetDb,
543
621
  getSourceDb,
544
622
  getRawClientFor,
545
623
  getRawClient,
624
+ getMigrationRole,
546
625
  getDbSplitStatus,
547
626
  getDb,
548
627
  closeDb,
549
628
  assertDbSplit,
629
+ TABLE_TO_DB,
550
630
  SOURCE_READ_COLUMNS
551
631
  };
552
632
 
553
- //# debugId=8E009B207AB7E55D64756E2164756E21
633
+ //# debugId=9BD00555AB68090864756E2164756E21
554
634
  //# sourceMappingURL=index.js.map