@secondlayer/shared 6.22.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
+ }
@@ -1767,6 +1767,30 @@ declare function createSignatureHeader(payload: string, secret: string, timestam
1767
1767
  * Returns true if valid, false otherwise
1768
1768
  */
1769
1769
  declare function verifySignatureHeader(payload: string, header: string, secret: string, toleranceSeconds?: number): boolean;
1770
+ declare namespace exports_ed25519 {
1771
+ export { verifyEd25519, signEd25519, publicKeyPemFromPrivate, loadEd25519PublicKey, loadEd25519PrivateKey, generateEd25519KeyPair, ed25519KeyId };
1772
+ }
1773
+ import { KeyObject } from "node:crypto";
1774
+ /**
1775
+ * Asymmetric ed25519 signing for Streams response proofs.
1776
+ *
1777
+ * Asymmetric (not HMAC) so the proof is real: only the server holds the private
1778
+ * key, and any consumer verifies with the published public key — no shared
1779
+ * secret to leak. ed25519 uses node's `sign`/`verify` with a `null` algorithm.
1780
+ * Keys are PEM (PKCS8 private / SPKI public) for env transport; load once and
1781
+ * reuse the KeyObject on hot paths.
1782
+ */
1783
+ declare function generateEd25519KeyPair(): {
1784
+ privateKeyPem: string
1785
+ publicKeyPem: string
1786
+ };
1787
+ declare function loadEd25519PrivateKey(pem: string): KeyObject;
1788
+ declare function loadEd25519PublicKey(pem: string): KeyObject;
1789
+ declare function publicKeyPemFromPrivate(privateKeyPem: string): string;
1790
+ /** Stable short id for a public key (rotation hint via X-Signature-KeyId). */
1791
+ declare function ed25519KeyId(publicKeyPem: string): string;
1792
+ declare function signEd25519(payload: string, privateKey: KeyObject): string;
1793
+ declare function verifyEd25519(payload: string, signatureBase64: string, publicKey: KeyObject): boolean;
1770
1794
  declare const DECODED_EVENT_TYPES: readonly ["stx_transfer", "stx_mint", "stx_burn", "stx_lock", "ft_transfer", "ft_mint", "ft_burn", "nft_transfer", "nft_mint", "nft_burn", "print"];
1771
1795
  type DecodedEventType = (typeof DECODED_EVENT_TYPES)[number];
1772
1796
  /** Alias kept for the Streams surface (identical to {@link DECODED_EVENT_TYPES}).
@@ -1826,28 +1850,4 @@ type StreamsCursor = {
1826
1850
  declare const EMPTY_RANGE_EVENT_INDEX_SENTINEL = 2147483647;
1827
1851
  declare function encodeStreamsCursor(cursor: StreamsCursor): string;
1828
1852
  declare function decodeStreamsCursor(cursor: string): StreamsCursor;
1829
- declare namespace exports_ed25519 {
1830
- export { verifyEd25519, signEd25519, publicKeyPemFromPrivate, loadEd25519PublicKey, loadEd25519PrivateKey, generateEd25519KeyPair, ed25519KeyId };
1831
- }
1832
- import { KeyObject } from "node:crypto";
1833
- /**
1834
- * Asymmetric ed25519 signing for Streams response proofs.
1835
- *
1836
- * Asymmetric (not HMAC) so the proof is real: only the server holds the private
1837
- * key, and any consumer verifies with the published public key — no shared
1838
- * secret to leak. ed25519 uses node's `sign`/`verify` with a `null` algorithm.
1839
- * Keys are PEM (PKCS8 private / SPKI public) for env transport; load once and
1840
- * reuse the KeyObject on hot paths.
1841
- */
1842
- declare function generateEd25519KeyPair(): {
1843
- privateKeyPem: string
1844
- publicKeyPem: string
1845
- };
1846
- declare function loadEd25519PrivateKey(pem: string): KeyObject;
1847
- declare function loadEd25519PublicKey(pem: string): KeyObject;
1848
- declare function publicKeyPemFromPrivate(privateKeyPem: string): string;
1849
- /** Stable short id for a public key (rotation hint via X-Signature-KeyId). */
1850
- declare function ed25519KeyId(publicKeyPem: string): string;
1851
- declare function signEd25519(payload: string, privateKey: KeyObject): string;
1852
- declare function verifyEd25519(payload: string, signatureBase64: string, publicKey: KeyObject): boolean;
1853
1853
  export { validateSubscriptionFilterForTable, sql, setMigrationRole, parseJsonb, onControlPlane, onChainPlane, logger, jsonb, isPox4DecoderEnabled, getTargetDb, getSourceDb, getRawClientFor, getRawClient, getMigrationRole, getErrorMessage, getEnv, getDbSplitStatus, getDb, generateSubgraphSpec, generateSubgraphOpenApi, generateSubgraphMarkdown, generateSubgraphAgentSchema, formatSubscriptionSchemaErrors, finalizedBurnHeight, encodeStreamsCursor, exports_ed25519 as ed25519, decodeStreamsCursor, exports_hmac as crypto, closeDb, assertDbSplit, VersionConflictError, ValidationError, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionRequestSchema, UpdateSubscriptionRequest, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateContract, UpdateChatSession, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, TriggerEvaluatorStateTable, TriggerEvaluatorState, TransactionsTable, TransactionsArchiveTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantSuspendedError, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, TABLE_TO_DB, SubscriptionsTable, SubscriptionSummary, SubscriptionStatusSchema, SubscriptionStatus, SubscriptionSchemaTables, SubscriptionSchemaTable, SubscriptionSchemaColumn, SubscriptionRuntimeSchema, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionKind, SubscriptionFormatSchema, SubscriptionFormat, SubscriptionFilterSchema, SubscriptionFilterPrimitiveSchema, SubscriptionFilterPrimitive, SubscriptionFilterOperatorSchema, SubscriptionFilterOperator, SubscriptionFilterClauseSchema, SubscriptionFilterClause, SubscriptionFilter, SubscriptionDetail, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphSyncInfo, SubgraphSummary, SubgraphSpecOptions, SubgraphSpecFormat, SubgraphResourceWarning, SubgraphQueryParams, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGapsResponse, SubgraphGapRange, SubgraphGapEntry, SubgraphGap, SubgraphDetail, SubgraphAgentSchema, Subgraph, StxTransferFilterSchema, StxTransferFilter, StxMintFilterSchema, StxMintFilter, StxLockFilterSchema, StxLockFilter, StxBurnFilterSchema, StxBurnFilter, StreamsEventType, StreamsDbEventType, StreamsCursor, SessionsTable, Session, ServiceHeartbeatsTable, SecondLayerError, SbtcTokenEventsTable, SbtcTokenEventType, SbtcSupplySnapshotsTable, SbtcEventsTable, SbtcEventTopic, SUBSCRIPTION_STATUSES, SUBSCRIPTION_RUNTIMES, SUBSCRIPTION_FORMATS, SUBSCRIPTION_FILTER_OPERATORS, STREAMS_TO_DB_EVENT_TYPES, STREAMS_EVENT_TYPES, STREAMS_DB_EVENT_TYPES, SOURCE_READ_COLUMNS, RotateSecretResponse, ReplaySubscriptionRequestSchema, ReplaySubscriptionRequest, ReplayResult, ReindexResponse, RateLimitError, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, PrintEventFilterSchema, PrintEventFilter, Pox4SignersDailyTable, Pox4FunctionName, Pox4CyclesDailyTable, Pox4CallsTable, ParsedUpdateSubscriptionRequest, ParsedReplaySubscriptionRequest, ParsedCreateSubscriptionRequest, OutboxStatus, NumericAsText, NotFoundError, NftTransferFilterSchema, NftTransferFilter, NftMintFilterSchema, NftMintFilter, NftBurnFilterSchema, NftBurnFilter, MigrationRole, MempoolTransactionsTable, MempoolTransaction, MagicLinksTable, MagicLink, L2DecoderCheckpointsTable, KeyRotatedError, 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, FtTransferFilterSchema, FtTransferFilter, FtMintFilterSchema, FtMintFilter, FtBurnFilterSchema, FtBurnFilter, ForbiddenError, EventsTable, EventsArchiveTable, EventFilterSchema, EventFilter, Event, ErrorCodes, ErrorCode, Env, EMPTY_RANGE_EVENT_INDEX_SENTINEL, DeploySubgraphResponse, DeploySubgraphRequestSchema, DeploySubgraphRequest, DeliveryRow, DecodedEventsTable, DecodedEventType, DeadRow, DeadLetterEventsTable, DbSplitStatus, DbReadRow, DbPlane, DatabaseError, Database, DEFAULT_BTC_CONFIRMATIONS, DECODED_EVENT_TYPES, DB_TO_STREAMS_EVENT_TYPE, CreateSubscriptionResponse, CreateSubscriptionRequestSchema, CreateSubscriptionRequest, ContractsTable, ContractDeployFilterSchema, ContractDeployFilter, ContractCallFilterSchema, ContractCallFilter, Contract, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, ChainReorgsTable, CODE_TO_STATUS, CHAIN_TRIGGER_TYPES, BurnBlockRewardsTable, BurnBlockRewardSlotsTable, BnsNamespacesTable, BnsNamespaceEventsTable, BnsNamespaceEventStatus, BnsNamesTable, BnsNameEventsTable, BnsNameEventTopic, BnsMarketplaceEventsTable, BnsMarketplaceAction, BlocksTable, Block, AuthorizationError, AuthenticationError, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
package/dist/src/index.js CHANGED
@@ -1549,6 +1549,59 @@ function verifySignatureHeader(payload, header, secret, toleranceSeconds = 300)
1549
1549
  const signedPayload = `${ts}.${payload}`;
1550
1550
  return verifySignature(signedPayload, signature, secret);
1551
1551
  }
1552
+
1553
+ // src/crypto/ed25519.ts
1554
+ var exports_ed25519 = {};
1555
+ __export(exports_ed25519, {
1556
+ verifyEd25519: () => verifyEd25519,
1557
+ signEd25519: () => signEd25519,
1558
+ publicKeyPemFromPrivate: () => publicKeyPemFromPrivate,
1559
+ loadEd25519PublicKey: () => loadEd25519PublicKey,
1560
+ loadEd25519PrivateKey: () => loadEd25519PrivateKey,
1561
+ generateEd25519KeyPair: () => generateEd25519KeyPair,
1562
+ ed25519KeyId: () => ed25519KeyId
1563
+ });
1564
+ import {
1565
+ createHash,
1566
+ createPrivateKey,
1567
+ createPublicKey,
1568
+ generateKeyPairSync,
1569
+ sign as nodeSign,
1570
+ verify as nodeVerify
1571
+ } from "node:crypto";
1572
+ function generateEd25519KeyPair() {
1573
+ const { privateKey, publicKey } = generateKeyPairSync("ed25519");
1574
+ return {
1575
+ privateKeyPem: privateKey.export({ format: "pem", type: "pkcs8" }).toString(),
1576
+ publicKeyPem: publicKey.export({ format: "pem", type: "spki" }).toString()
1577
+ };
1578
+ }
1579
+ function loadEd25519PrivateKey(pem) {
1580
+ return createPrivateKey(pem);
1581
+ }
1582
+ function loadEd25519PublicKey(pem) {
1583
+ return createPublicKey(pem);
1584
+ }
1585
+ function publicKeyPemFromPrivate(privateKeyPem) {
1586
+ return createPublicKey(createPrivateKey(privateKeyPem)).export({ format: "pem", type: "spki" }).toString();
1587
+ }
1588
+ function ed25519KeyId(publicKeyPem) {
1589
+ const der = createPublicKey(publicKeyPem).export({
1590
+ format: "der",
1591
+ type: "spki"
1592
+ });
1593
+ return createHash("sha256").update(der).digest("base64url").slice(0, 16);
1594
+ }
1595
+ function signEd25519(payload, privateKey) {
1596
+ return nodeSign(null, Buffer.from(payload, "utf8"), privateKey).toString("base64");
1597
+ }
1598
+ function verifyEd25519(payload, signatureBase64, publicKey) {
1599
+ try {
1600
+ return nodeVerify(null, Buffer.from(payload, "utf8"), publicKey, Buffer.from(signatureBase64, "base64"));
1601
+ } catch {
1602
+ return false;
1603
+ }
1604
+ }
1552
1605
  // src/event-types.ts
1553
1606
  var DECODED_EVENT_TYPES = [
1554
1607
  "stx_transfer",
@@ -1636,58 +1689,6 @@ function decodeStreamsCursor(cursor) {
1636
1689
  }
1637
1690
  return decoded;
1638
1691
  }
1639
- // src/crypto/ed25519.ts
1640
- var exports_ed25519 = {};
1641
- __export(exports_ed25519, {
1642
- verifyEd25519: () => verifyEd25519,
1643
- signEd25519: () => signEd25519,
1644
- publicKeyPemFromPrivate: () => publicKeyPemFromPrivate,
1645
- loadEd25519PublicKey: () => loadEd25519PublicKey,
1646
- loadEd25519PrivateKey: () => loadEd25519PrivateKey,
1647
- generateEd25519KeyPair: () => generateEd25519KeyPair,
1648
- ed25519KeyId: () => ed25519KeyId
1649
- });
1650
- import {
1651
- createHash,
1652
- createPrivateKey,
1653
- createPublicKey,
1654
- generateKeyPairSync,
1655
- sign as nodeSign,
1656
- verify as nodeVerify
1657
- } from "node:crypto";
1658
- function generateEd25519KeyPair() {
1659
- const { privateKey, publicKey } = generateKeyPairSync("ed25519");
1660
- return {
1661
- privateKeyPem: privateKey.export({ format: "pem", type: "pkcs8" }).toString(),
1662
- publicKeyPem: publicKey.export({ format: "pem", type: "spki" }).toString()
1663
- };
1664
- }
1665
- function loadEd25519PrivateKey(pem) {
1666
- return createPrivateKey(pem);
1667
- }
1668
- function loadEd25519PublicKey(pem) {
1669
- return createPublicKey(pem);
1670
- }
1671
- function publicKeyPemFromPrivate(privateKeyPem) {
1672
- return createPublicKey(createPrivateKey(privateKeyPem)).export({ format: "pem", type: "spki" }).toString();
1673
- }
1674
- function ed25519KeyId(publicKeyPem) {
1675
- const der = createPublicKey(publicKeyPem).export({
1676
- format: "der",
1677
- type: "spki"
1678
- });
1679
- return createHash("sha256").update(der).digest("base64url").slice(0, 16);
1680
- }
1681
- function signEd25519(payload, privateKey) {
1682
- return nodeSign(null, Buffer.from(payload, "utf8"), privateKey).toString("base64");
1683
- }
1684
- function verifyEd25519(payload, signatureBase64, publicKey) {
1685
- try {
1686
- return nodeVerify(null, Buffer.from(payload, "utf8"), publicKey, Buffer.from(signatureBase64, "base64"));
1687
- } catch {
1688
- return false;
1689
- }
1690
- }
1691
1692
  export {
1692
1693
  validateSubscriptionFilterForTable,
1693
1694
  sql2 as sql,
@@ -1773,5 +1774,5 @@ export {
1773
1774
  AuthenticationError
1774
1775
  };
1775
1776
 
1776
- //# debugId=CB9C0FAE8D284C5164756E2164756E21
1777
+ //# debugId=E26BA28FDF632B7E64756E2164756E21
1777
1778
  //# sourceMappingURL=index.js.map