@vritti/api-sdk 0.3.2 → 0.3.3

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,12 @@
1
+ interface SignedDocument<T> {
2
+ payload: T;
3
+ signature: string;
4
+ }
5
+ declare function generateSigningKeyPair(): {
6
+ privateKey: string;
7
+ publicKey: string;
8
+ };
9
+ declare function signDocument<T>(payload: T, privateKeyBase64: string): SignedDocument<T>;
10
+ declare function verifyDocument<T>(doc: SignedDocument<T>, publicKeyBase64: string): boolean;
11
+
12
+ export { type SignedDocument as S, generateSigningKeyPair as g, signDocument as s, verifyDocument as v };
@@ -0,0 +1,12 @@
1
+ interface SignedDocument<T> {
2
+ payload: T;
3
+ signature: string;
4
+ }
5
+ declare function generateSigningKeyPair(): {
6
+ privateKey: string;
7
+ publicKey: string;
8
+ };
9
+ declare function signDocument<T>(payload: T, privateKeyBase64: string): SignedDocument<T>;
10
+ declare function verifyDocument<T>(doc: SignedDocument<T>, publicKeyBase64: string): boolean;
11
+
12
+ export { type SignedDocument as S, generateSigningKeyPair as g, signDocument as s, verifyDocument as v };
package/dist/license.cjs CHANGED
@@ -21,24 +21,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  // src/license/index.ts
22
22
  var license_exports = {};
23
23
  __export(license_exports, {
24
- canonicalStringify: () => canonicalStringify,
25
- generateLicenseKeyPair: () => generateLicenseKeyPair,
26
- hashSnapshot: () => hashSnapshot,
27
- signDocument: () => signDocument,
28
- verifyDocument: () => verifyDocument
24
+ hashSnapshot: () => hashSnapshot
29
25
  });
30
26
  module.exports = __toCommonJS(license_exports);
31
27
 
32
- // src/license/canonical.ts
28
+ // src/license/hash.ts
33
29
  var import_node_crypto = require("crypto");
30
+
31
+ // src/signing/canonical.ts
34
32
  function canonicalStringify(value) {
35
33
  return JSON.stringify(sortKeysDeep(value));
36
34
  }
37
35
  __name(canonicalStringify, "canonicalStringify");
38
- function hashSnapshot(value) {
39
- return (0, import_node_crypto.createHash)("sha256").update(canonicalStringify(value), "utf8").digest("hex");
40
- }
41
- __name(hashSnapshot, "hashSnapshot");
42
36
  function sortKeysDeep(value) {
43
37
  if (Array.isArray(value)) return value.map(sortKeysDeep);
44
38
  if (value !== null && typeof value === "object") {
@@ -51,54 +45,13 @@ function sortKeysDeep(value) {
51
45
  }
52
46
  __name(sortKeysDeep, "sortKeysDeep");
53
47
 
54
- // src/license/signing.ts
55
- var import_node_crypto2 = require("crypto");
56
- function generateLicenseKeyPair() {
57
- const { privateKey, publicKey } = (0, import_node_crypto2.generateKeyPairSync)("ed25519");
58
- return {
59
- privateKey: privateKey.export({
60
- type: "pkcs8",
61
- format: "der"
62
- }).toString("base64"),
63
- publicKey: publicKey.export({
64
- type: "spki",
65
- format: "der"
66
- }).toString("base64")
67
- };
68
- }
69
- __name(generateLicenseKeyPair, "generateLicenseKeyPair");
70
- function signDocument(payload, privateKeyBase64) {
71
- const key = (0, import_node_crypto2.createPrivateKey)({
72
- key: Buffer.from(privateKeyBase64, "base64"),
73
- format: "der",
74
- type: "pkcs8"
75
- });
76
- const signature = (0, import_node_crypto2.sign)(null, Buffer.from(canonicalStringify(payload), "utf8"), key).toString("base64");
77
- return {
78
- payload,
79
- signature
80
- };
81
- }
82
- __name(signDocument, "signDocument");
83
- function verifyDocument(doc, publicKeyBase64) {
84
- try {
85
- const key = (0, import_node_crypto2.createPublicKey)({
86
- key: Buffer.from(publicKeyBase64, "base64"),
87
- format: "der",
88
- type: "spki"
89
- });
90
- return (0, import_node_crypto2.verify)(null, Buffer.from(canonicalStringify(doc.payload), "utf8"), key, Buffer.from(doc.signature, "base64"));
91
- } catch {
92
- return false;
93
- }
48
+ // src/license/hash.ts
49
+ function hashSnapshot(value) {
50
+ return (0, import_node_crypto.createHash)("sha256").update(canonicalStringify(value), "utf8").digest("hex");
94
51
  }
95
- __name(verifyDocument, "verifyDocument");
52
+ __name(hashSnapshot, "hashSnapshot");
96
53
  // Annotate the CommonJS export names for ESM import in node:
97
54
  0 && (module.exports = {
98
- canonicalStringify,
99
- generateLicenseKeyPair,
100
- hashSnapshot,
101
- signDocument,
102
- verifyDocument
55
+ hashSnapshot
103
56
  });
104
57
  //# sourceMappingURL=license.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/license/index.ts","../src/license/canonical.ts","../src/license/signing.ts"],"sourcesContent":["// License module — Ed25519-signed catalog + entitlement documents over canonical JSON\nexport { canonicalStringify, hashSnapshot } from './canonical';\nexport { generateLicenseKeyPair, signDocument, verifyDocument } from './signing';\nexport type { CatalogLicense, OrgEntitlement, SignedDocument } from './types';\n","import { createHash } from 'node:crypto';\n\n// Serializes a value as deterministic JSON: object keys recursively sorted, arrays keep their order\nexport function canonicalStringify(value: unknown): string {\n return JSON.stringify(sortKeysDeep(value));\n}\n\n// Computes the sha256 hex digest of a value's canonical JSON\nexport function hashSnapshot(value: unknown): string {\n return createHash('sha256').update(canonicalStringify(value), 'utf8').digest('hex');\n}\n\n// Recursively rebuilds objects with sorted keys so JSON.stringify output is order-independent\nfunction sortKeysDeep(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeysDeep);\n if (value !== null && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(record).sort()) sorted[key] = sortKeysDeep(record[key]);\n return sorted;\n }\n return value;\n}\n","import { createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify } from 'node:crypto';\nimport { canonicalStringify } from './canonical';\nimport type { SignedDocument } from './types';\n\n// Generates an Ed25519 key pair as base64 DER strings (pkcs8 private / spki public)\nexport function generateLicenseKeyPair(): { privateKey: string; publicKey: string } {\n const { privateKey, publicKey } = generateKeyPairSync('ed25519');\n return {\n privateKey: privateKey.export({ type: 'pkcs8', format: 'der' }).toString('base64'),\n publicKey: publicKey.export({ type: 'spki', format: 'der' }).toString('base64'),\n };\n}\n\n// Signs a payload's canonical JSON with an Ed25519 private key (base64 pkcs8 DER)\nexport function signDocument<T>(payload: T, privateKeyBase64: string): SignedDocument<T> {\n const key = createPrivateKey({ key: Buffer.from(privateKeyBase64, 'base64'), format: 'der', type: 'pkcs8' });\n const signature = sign(null, Buffer.from(canonicalStringify(payload), 'utf8'), key).toString('base64');\n return { payload, signature };\n}\n\n// Verifies a signed document against an Ed25519 public key (base64 spki DER); malformed input ⇒ false\nexport function verifyDocument<T>(doc: SignedDocument<T>, publicKeyBase64: string): boolean {\n try {\n const key = createPublicKey({ key: Buffer.from(publicKeyBase64, 'base64'), format: 'der', type: 'spki' });\n return verify(\n null,\n Buffer.from(canonicalStringify(doc.payload), 'utf8'),\n key,\n Buffer.from(doc.signature, 'base64'),\n );\n } catch {\n return false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;ACAA,yBAA2B;AAGpB,SAASA,mBAAmBC,OAAc;AAC/C,SAAOC,KAAKC,UAAUC,aAAaH,KAAAA,CAAAA;AACrC;AAFgBD;AAKT,SAASK,aAAaJ,OAAc;AACzC,aAAOK,+BAAW,QAAA,EAAUC,OAAOP,mBAAmBC,KAAAA,GAAQ,MAAA,EAAQO,OAAO,KAAA;AAC/E;AAFgBH;AAKhB,SAASD,aAAaH,OAAc;AAClC,MAAIQ,MAAMC,QAAQT,KAAAA,EAAQ,QAAOA,MAAMU,IAAIP,YAAAA;AAC3C,MAAIH,UAAU,QAAQ,OAAOA,UAAU,UAAU;AAC/C,UAAMW,SAASX;AACf,UAAMY,SAAkC,CAAC;AACzC,eAAWC,OAAOC,OAAOC,KAAKJ,MAAAA,EAAQK,KAAI,EAAIJ,QAAOC,GAAAA,IAAOV,aAAaQ,OAAOE,GAAAA,CAAI;AACpF,WAAOD;EACT;AACA,SAAOZ;AACT;AATSG;;;ACbT,IAAAc,sBAAqF;AAK9E,SAASC,yBAAAA;AACd,QAAM,EAAEC,YAAYC,UAAS,QAAKC,yCAAoB,SAAA;AACtD,SAAO;IACLF,YAAYA,WAAWG,OAAO;MAAEC,MAAM;MAASC,QAAQ;IAAM,CAAA,EAAGC,SAAS,QAAA;IACzEL,WAAWA,UAAUE,OAAO;MAAEC,MAAM;MAAQC,QAAQ;IAAM,CAAA,EAAGC,SAAS,QAAA;EACxE;AACF;AANgBP;AAST,SAASQ,aAAgBC,SAAYC,kBAAwB;AAClE,QAAMC,UAAMC,sCAAiB;IAAED,KAAKE,OAAOC,KAAKJ,kBAAkB,QAAA;IAAWJ,QAAQ;IAAOD,MAAM;EAAQ,CAAA;AAC1G,QAAMU,gBAAYC,0BAAK,MAAMH,OAAOC,KAAKG,mBAAmBR,OAAAA,GAAU,MAAA,GAASE,GAAAA,EAAKJ,SAAS,QAAA;AAC7F,SAAO;IAAEE;IAASM;EAAU;AAC9B;AAJgBP;AAOT,SAASU,eAAkBC,KAAwBC,iBAAuB;AAC/E,MAAI;AACF,UAAMT,UAAMU,qCAAgB;MAAEV,KAAKE,OAAOC,KAAKM,iBAAiB,QAAA;MAAWd,QAAQ;MAAOD,MAAM;IAAO,CAAA;AACvG,eAAOiB,4BACL,MACAT,OAAOC,KAAKG,mBAAmBE,IAAIV,OAAO,GAAG,MAAA,GAC7CE,KACAE,OAAOC,KAAKK,IAAIJ,WAAW,QAAA,CAAA;EAE/B,QAAQ;AACN,WAAO;EACT;AACF;AAZgBG;","names":["canonicalStringify","value","JSON","stringify","sortKeysDeep","hashSnapshot","createHash","update","digest","Array","isArray","map","record","sorted","key","Object","keys","sort","import_node_crypto","generateLicenseKeyPair","privateKey","publicKey","generateKeyPairSync","export","type","format","toString","signDocument","payload","privateKeyBase64","key","createPrivateKey","Buffer","from","signature","sign","canonicalStringify","verifyDocument","doc","publicKeyBase64","createPublicKey","verify"]}
1
+ {"version":3,"sources":["../src/license/index.ts","../src/license/hash.ts","../src/signing/canonical.ts"],"sourcesContent":["// License module — licensing artifacts: signed catalog/entitlement document types and snapshot hashing\nexport { hashSnapshot } from './hash';\nexport type { CatalogLicense, OrgEntitlement, SignedDocument } from './types';\n","import { createHash } from 'node:crypto';\nimport { canonicalStringify } from '../signing/canonical';\n\n// Computes the sha256 hex digest of a value's canonical JSON idempotency key for catalog snapshots\nexport function hashSnapshot(value: unknown): string {\n return createHash('sha256').update(canonicalStringify(value), 'utf8').digest('hex');\n}\n","// Serializes a value as deterministic JSON: object keys recursively sorted, arrays keep their order\nexport function canonicalStringify(value: unknown): string {\n return JSON.stringify(sortKeysDeep(value));\n}\n\n// Recursively rebuilds objects with sorted keys so JSON.stringify output is order-independent\nfunction sortKeysDeep(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeysDeep);\n if (value !== null && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(record).sort()) sorted[key] = sortKeysDeep(record[key]);\n return sorted;\n }\n return value;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;ACAA,yBAA2B;;;ACCpB,SAASA,mBAAmBC,OAAc;AAC/C,SAAOC,KAAKC,UAAUC,aAAaH,KAAAA,CAAAA;AACrC;AAFgBD;AAKhB,SAASI,aAAaH,OAAc;AAClC,MAAII,MAAMC,QAAQL,KAAAA,EAAQ,QAAOA,MAAMM,IAAIH,YAAAA;AAC3C,MAAIH,UAAU,QAAQ,OAAOA,UAAU,UAAU;AAC/C,UAAMO,SAASP;AACf,UAAMQ,SAAkC,CAAC;AACzC,eAAWC,OAAOC,OAAOC,KAAKJ,MAAAA,EAAQK,KAAI,EAAIJ,QAAOC,GAAAA,IAAON,aAAaI,OAAOE,GAAAA,CAAI;AACpF,WAAOD;EACT;AACA,SAAOR;AACT;AATSG;;;ADFF,SAASU,aAAaC,OAAc;AACzC,aAAOC,+BAAW,QAAA,EAAUC,OAAOC,mBAAmBH,KAAAA,GAAQ,MAAA,EAAQI,OAAO,KAAA;AAC/E;AAFgBL;","names":["canonicalStringify","value","JSON","stringify","sortKeysDeep","Array","isArray","map","record","sorted","key","Object","keys","sort","hashSnapshot","value","createHash","update","canonicalStringify","digest"]}
@@ -1,12 +1,8 @@
1
1
  import { V as VersionSnapshot } from './types-DQRwj5rr.cjs';
2
+ export { S as SignedDocument } from './document-BoS0NIbf.cjs';
2
3
 
3
- declare function canonicalStringify(value: unknown): string;
4
4
  declare function hashSnapshot(value: unknown): string;
5
5
 
6
- interface SignedDocument<T> {
7
- payload: T;
8
- signature: string;
9
- }
10
6
  interface CatalogLicense {
11
7
  deploymentId: string;
12
8
  version: string;
@@ -22,11 +18,4 @@ interface OrgEntitlement {
22
18
  issuedAt: string;
23
19
  }
24
20
 
25
- declare function generateLicenseKeyPair(): {
26
- privateKey: string;
27
- publicKey: string;
28
- };
29
- declare function signDocument<T>(payload: T, privateKeyBase64: string): SignedDocument<T>;
30
- declare function verifyDocument<T>(doc: SignedDocument<T>, publicKeyBase64: string): boolean;
31
-
32
- export { type CatalogLicense, type OrgEntitlement, type SignedDocument, canonicalStringify, generateLicenseKeyPair, hashSnapshot, signDocument, verifyDocument };
21
+ export { type CatalogLicense, type OrgEntitlement, hashSnapshot };
package/dist/license.d.ts CHANGED
@@ -1,12 +1,8 @@
1
1
  import { V as VersionSnapshot } from './types-DQRwj5rr.js';
2
+ export { S as SignedDocument } from './document-BoS0NIbf.js';
2
3
 
3
- declare function canonicalStringify(value: unknown): string;
4
4
  declare function hashSnapshot(value: unknown): string;
5
5
 
6
- interface SignedDocument<T> {
7
- payload: T;
8
- signature: string;
9
- }
10
6
  interface CatalogLicense {
11
7
  deploymentId: string;
12
8
  version: string;
@@ -22,11 +18,4 @@ interface OrgEntitlement {
22
18
  issuedAt: string;
23
19
  }
24
20
 
25
- declare function generateLicenseKeyPair(): {
26
- privateKey: string;
27
- publicKey: string;
28
- };
29
- declare function signDocument<T>(payload: T, privateKeyBase64: string): SignedDocument<T>;
30
- declare function verifyDocument<T>(doc: SignedDocument<T>, publicKeyBase64: string): boolean;
31
-
32
- export { type CatalogLicense, type OrgEntitlement, type SignedDocument, canonicalStringify, generateLicenseKeyPair, hashSnapshot, signDocument, verifyDocument };
21
+ export { type CatalogLicense, type OrgEntitlement, hashSnapshot };
package/dist/license.js CHANGED
@@ -1,16 +1,14 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
- // src/license/canonical.ts
4
+ // src/license/hash.ts
5
5
  import { createHash } from "crypto";
6
+
7
+ // src/signing/canonical.ts
6
8
  function canonicalStringify(value) {
7
9
  return JSON.stringify(sortKeysDeep(value));
8
10
  }
9
11
  __name(canonicalStringify, "canonicalStringify");
10
- function hashSnapshot(value) {
11
- return createHash("sha256").update(canonicalStringify(value), "utf8").digest("hex");
12
- }
13
- __name(hashSnapshot, "hashSnapshot");
14
12
  function sortKeysDeep(value) {
15
13
  if (Array.isArray(value)) return value.map(sortKeysDeep);
16
14
  if (value !== null && typeof value === "object") {
@@ -23,53 +21,12 @@ function sortKeysDeep(value) {
23
21
  }
24
22
  __name(sortKeysDeep, "sortKeysDeep");
25
23
 
26
- // src/license/signing.ts
27
- import { createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify } from "crypto";
28
- function generateLicenseKeyPair() {
29
- const { privateKey, publicKey } = generateKeyPairSync("ed25519");
30
- return {
31
- privateKey: privateKey.export({
32
- type: "pkcs8",
33
- format: "der"
34
- }).toString("base64"),
35
- publicKey: publicKey.export({
36
- type: "spki",
37
- format: "der"
38
- }).toString("base64")
39
- };
40
- }
41
- __name(generateLicenseKeyPair, "generateLicenseKeyPair");
42
- function signDocument(payload, privateKeyBase64) {
43
- const key = createPrivateKey({
44
- key: Buffer.from(privateKeyBase64, "base64"),
45
- format: "der",
46
- type: "pkcs8"
47
- });
48
- const signature = sign(null, Buffer.from(canonicalStringify(payload), "utf8"), key).toString("base64");
49
- return {
50
- payload,
51
- signature
52
- };
53
- }
54
- __name(signDocument, "signDocument");
55
- function verifyDocument(doc, publicKeyBase64) {
56
- try {
57
- const key = createPublicKey({
58
- key: Buffer.from(publicKeyBase64, "base64"),
59
- format: "der",
60
- type: "spki"
61
- });
62
- return verify(null, Buffer.from(canonicalStringify(doc.payload), "utf8"), key, Buffer.from(doc.signature, "base64"));
63
- } catch {
64
- return false;
65
- }
24
+ // src/license/hash.ts
25
+ function hashSnapshot(value) {
26
+ return createHash("sha256").update(canonicalStringify(value), "utf8").digest("hex");
66
27
  }
67
- __name(verifyDocument, "verifyDocument");
28
+ __name(hashSnapshot, "hashSnapshot");
68
29
  export {
69
- canonicalStringify,
70
- generateLicenseKeyPair,
71
- hashSnapshot,
72
- signDocument,
73
- verifyDocument
30
+ hashSnapshot
74
31
  };
75
32
  //# sourceMappingURL=license.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/license/canonical.ts","../src/license/signing.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\n\n// Serializes a value as deterministic JSON: object keys recursively sorted, arrays keep their order\nexport function canonicalStringify(value: unknown): string {\n return JSON.stringify(sortKeysDeep(value));\n}\n\n// Computes the sha256 hex digest of a value's canonical JSON\nexport function hashSnapshot(value: unknown): string {\n return createHash('sha256').update(canonicalStringify(value), 'utf8').digest('hex');\n}\n\n// Recursively rebuilds objects with sorted keys so JSON.stringify output is order-independent\nfunction sortKeysDeep(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeysDeep);\n if (value !== null && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(record).sort()) sorted[key] = sortKeysDeep(record[key]);\n return sorted;\n }\n return value;\n}\n","import { createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify } from 'node:crypto';\nimport { canonicalStringify } from './canonical';\nimport type { SignedDocument } from './types';\n\n// Generates an Ed25519 key pair as base64 DER strings (pkcs8 private / spki public)\nexport function generateLicenseKeyPair(): { privateKey: string; publicKey: string } {\n const { privateKey, publicKey } = generateKeyPairSync('ed25519');\n return {\n privateKey: privateKey.export({ type: 'pkcs8', format: 'der' }).toString('base64'),\n publicKey: publicKey.export({ type: 'spki', format: 'der' }).toString('base64'),\n };\n}\n\n// Signs a payload's canonical JSON with an Ed25519 private key (base64 pkcs8 DER)\nexport function signDocument<T>(payload: T, privateKeyBase64: string): SignedDocument<T> {\n const key = createPrivateKey({ key: Buffer.from(privateKeyBase64, 'base64'), format: 'der', type: 'pkcs8' });\n const signature = sign(null, Buffer.from(canonicalStringify(payload), 'utf8'), key).toString('base64');\n return { payload, signature };\n}\n\n// Verifies a signed document against an Ed25519 public key (base64 spki DER); malformed input ⇒ false\nexport function verifyDocument<T>(doc: SignedDocument<T>, publicKeyBase64: string): boolean {\n try {\n const key = createPublicKey({ key: Buffer.from(publicKeyBase64, 'base64'), format: 'der', type: 'spki' });\n return verify(\n null,\n Buffer.from(canonicalStringify(doc.payload), 'utf8'),\n key,\n Buffer.from(doc.signature, 'base64'),\n );\n } catch {\n return false;\n }\n}\n"],"mappings":";;;;AAAA,SAASA,kBAAkB;AAGpB,SAASC,mBAAmBC,OAAc;AAC/C,SAAOC,KAAKC,UAAUC,aAAaH,KAAAA,CAAAA;AACrC;AAFgBD;AAKT,SAASK,aAAaJ,OAAc;AACzC,SAAOK,WAAW,QAAA,EAAUC,OAAOP,mBAAmBC,KAAAA,GAAQ,MAAA,EAAQO,OAAO,KAAA;AAC/E;AAFgBH;AAKhB,SAASD,aAAaH,OAAc;AAClC,MAAIQ,MAAMC,QAAQT,KAAAA,EAAQ,QAAOA,MAAMU,IAAIP,YAAAA;AAC3C,MAAIH,UAAU,QAAQ,OAAOA,UAAU,UAAU;AAC/C,UAAMW,SAASX;AACf,UAAMY,SAAkC,CAAC;AACzC,eAAWC,OAAOC,OAAOC,KAAKJ,MAAAA,EAAQK,KAAI,EAAIJ,QAAOC,GAAAA,IAAOV,aAAaQ,OAAOE,GAAAA,CAAI;AACpF,WAAOD;EACT;AACA,SAAOZ;AACT;AATSG;;;ACbT,SAASc,kBAAkBC,iBAAiBC,qBAAqBC,MAAMC,cAAc;AAK9E,SAASC,yBAAAA;AACd,QAAM,EAAEC,YAAYC,UAAS,IAAKC,oBAAoB,SAAA;AACtD,SAAO;IACLF,YAAYA,WAAWG,OAAO;MAAEC,MAAM;MAASC,QAAQ;IAAM,CAAA,EAAGC,SAAS,QAAA;IACzEL,WAAWA,UAAUE,OAAO;MAAEC,MAAM;MAAQC,QAAQ;IAAM,CAAA,EAAGC,SAAS,QAAA;EACxE;AACF;AANgBP;AAST,SAASQ,aAAgBC,SAAYC,kBAAwB;AAClE,QAAMC,MAAMC,iBAAiB;IAAED,KAAKE,OAAOC,KAAKJ,kBAAkB,QAAA;IAAWJ,QAAQ;IAAOD,MAAM;EAAQ,CAAA;AAC1G,QAAMU,YAAYC,KAAK,MAAMH,OAAOC,KAAKG,mBAAmBR,OAAAA,GAAU,MAAA,GAASE,GAAAA,EAAKJ,SAAS,QAAA;AAC7F,SAAO;IAAEE;IAASM;EAAU;AAC9B;AAJgBP;AAOT,SAASU,eAAkBC,KAAwBC,iBAAuB;AAC/E,MAAI;AACF,UAAMT,MAAMU,gBAAgB;MAAEV,KAAKE,OAAOC,KAAKM,iBAAiB,QAAA;MAAWd,QAAQ;MAAOD,MAAM;IAAO,CAAA;AACvG,WAAOiB,OACL,MACAT,OAAOC,KAAKG,mBAAmBE,IAAIV,OAAO,GAAG,MAAA,GAC7CE,KACAE,OAAOC,KAAKK,IAAIJ,WAAW,QAAA,CAAA;EAE/B,QAAQ;AACN,WAAO;EACT;AACF;AAZgBG;","names":["createHash","canonicalStringify","value","JSON","stringify","sortKeysDeep","hashSnapshot","createHash","update","digest","Array","isArray","map","record","sorted","key","Object","keys","sort","createPrivateKey","createPublicKey","generateKeyPairSync","sign","verify","generateLicenseKeyPair","privateKey","publicKey","generateKeyPairSync","export","type","format","toString","signDocument","payload","privateKeyBase64","key","createPrivateKey","Buffer","from","signature","sign","canonicalStringify","verifyDocument","doc","publicKeyBase64","createPublicKey","verify"]}
1
+ {"version":3,"sources":["../src/license/hash.ts","../src/signing/canonical.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { canonicalStringify } from '../signing/canonical';\n\n// Computes the sha256 hex digest of a value's canonical JSON idempotency key for catalog snapshots\nexport function hashSnapshot(value: unknown): string {\n return createHash('sha256').update(canonicalStringify(value), 'utf8').digest('hex');\n}\n","// Serializes a value as deterministic JSON: object keys recursively sorted, arrays keep their order\nexport function canonicalStringify(value: unknown): string {\n return JSON.stringify(sortKeysDeep(value));\n}\n\n// Recursively rebuilds objects with sorted keys so JSON.stringify output is order-independent\nfunction sortKeysDeep(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeysDeep);\n if (value !== null && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(record).sort()) sorted[key] = sortKeysDeep(record[key]);\n return sorted;\n }\n return value;\n}\n"],"mappings":";;;;AAAA,SAASA,kBAAkB;;;ACCpB,SAASC,mBAAmBC,OAAc;AAC/C,SAAOC,KAAKC,UAAUC,aAAaH,KAAAA,CAAAA;AACrC;AAFgBD;AAKhB,SAASI,aAAaH,OAAc;AAClC,MAAII,MAAMC,QAAQL,KAAAA,EAAQ,QAAOA,MAAMM,IAAIH,YAAAA;AAC3C,MAAIH,UAAU,QAAQ,OAAOA,UAAU,UAAU;AAC/C,UAAMO,SAASP;AACf,UAAMQ,SAAkC,CAAC;AACzC,eAAWC,OAAOC,OAAOC,KAAKJ,MAAAA,EAAQK,KAAI,EAAIJ,QAAOC,GAAAA,IAAON,aAAaI,OAAOE,GAAAA,CAAI;AACpF,WAAOD;EACT;AACA,SAAOR;AACT;AATSG;;;ADFF,SAASU,aAAaC,OAAc;AACzC,SAAOC,WAAW,QAAA,EAAUC,OAAOC,mBAAmBH,KAAAA,GAAQ,MAAA,EAAQI,OAAO,KAAA;AAC/E;AAFgBL;","names":["createHash","canonicalStringify","value","JSON","stringify","sortKeysDeep","Array","isArray","map","record","sorted","key","Object","keys","sort","hashSnapshot","value","createHash","update","canonicalStringify","digest"]}
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/signing/index.ts
22
+ var signing_exports = {};
23
+ __export(signing_exports, {
24
+ buildRequestCanonical: () => buildRequestCanonical,
25
+ canonicalStringify: () => canonicalStringify,
26
+ generateSigningKeyPair: () => generateSigningKeyPair,
27
+ signDocument: () => signDocument,
28
+ signRequestHeaders: () => signRequestHeaders,
29
+ verifyDocument: () => verifyDocument,
30
+ verifySignedRequest: () => verifySignedRequest
31
+ });
32
+ module.exports = __toCommonJS(signing_exports);
33
+
34
+ // src/signing/canonical.ts
35
+ function canonicalStringify(value) {
36
+ return JSON.stringify(sortKeysDeep(value));
37
+ }
38
+ __name(canonicalStringify, "canonicalStringify");
39
+ function sortKeysDeep(value) {
40
+ if (Array.isArray(value)) return value.map(sortKeysDeep);
41
+ if (value !== null && typeof value === "object") {
42
+ const record = value;
43
+ const sorted = {};
44
+ for (const key of Object.keys(record).sort()) sorted[key] = sortKeysDeep(record[key]);
45
+ return sorted;
46
+ }
47
+ return value;
48
+ }
49
+ __name(sortKeysDeep, "sortKeysDeep");
50
+
51
+ // src/signing/document.ts
52
+ var import_node_crypto = require("crypto");
53
+ function generateSigningKeyPair() {
54
+ const { privateKey, publicKey } = (0, import_node_crypto.generateKeyPairSync)("ed25519");
55
+ return {
56
+ privateKey: privateKey.export({
57
+ type: "pkcs8",
58
+ format: "der"
59
+ }).toString("base64"),
60
+ publicKey: publicKey.export({
61
+ type: "spki",
62
+ format: "der"
63
+ }).toString("base64")
64
+ };
65
+ }
66
+ __name(generateSigningKeyPair, "generateSigningKeyPair");
67
+ function signDocument(payload, privateKeyBase64) {
68
+ const key = (0, import_node_crypto.createPrivateKey)({
69
+ key: Buffer.from(privateKeyBase64, "base64"),
70
+ format: "der",
71
+ type: "pkcs8"
72
+ });
73
+ const signature = (0, import_node_crypto.sign)(null, Buffer.from(canonicalStringify(payload), "utf8"), key).toString("base64");
74
+ return {
75
+ payload,
76
+ signature
77
+ };
78
+ }
79
+ __name(signDocument, "signDocument");
80
+ function verifyDocument(doc, publicKeyBase64) {
81
+ try {
82
+ const key = (0, import_node_crypto.createPublicKey)({
83
+ key: Buffer.from(publicKeyBase64, "base64"),
84
+ format: "der",
85
+ type: "spki"
86
+ });
87
+ return (0, import_node_crypto.verify)(null, Buffer.from(canonicalStringify(doc.payload), "utf8"), key, Buffer.from(doc.signature, "base64"));
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+ __name(verifyDocument, "verifyDocument");
93
+
94
+ // src/signing/request.ts
95
+ var import_node_crypto2 = require("crypto");
96
+ function buildRequestCanonical(input) {
97
+ const bodyHash = (0, import_node_crypto2.createHash)("sha256").update(input.body ?? "").digest("hex");
98
+ return [
99
+ input.method.toUpperCase(),
100
+ input.path,
101
+ input.orgId ?? "",
102
+ bodyHash,
103
+ String(input.timestamp)
104
+ ].join("\n");
105
+ }
106
+ __name(buildRequestCanonical, "buildRequestCanonical");
107
+ function signRequestHeaders(input, privateKeyBase64) {
108
+ const timestamp = Math.floor(Date.now() / 1e3);
109
+ const canonical = buildRequestCanonical({
110
+ ...input,
111
+ timestamp
112
+ });
113
+ const key = (0, import_node_crypto2.createPrivateKey)({
114
+ key: Buffer.from(privateKeyBase64, "base64"),
115
+ format: "der",
116
+ type: "pkcs8"
117
+ });
118
+ const signature = (0, import_node_crypto2.sign)(null, Buffer.from(canonical, "utf8"), key).toString("base64");
119
+ return {
120
+ "x-timestamp": String(timestamp),
121
+ "x-signature": signature
122
+ };
123
+ }
124
+ __name(signRequestHeaders, "signRequestHeaders");
125
+ function verifySignedRequest(input) {
126
+ try {
127
+ const timestamp = Number(input.timestamp);
128
+ if (!Number.isFinite(timestamp)) return false;
129
+ const maxSkew = input.maxSkewSeconds ?? 300;
130
+ if (Math.abs(Math.floor(Date.now() / 1e3) - timestamp) > maxSkew) return false;
131
+ const canonical = buildRequestCanonical({
132
+ method: input.method,
133
+ path: input.path,
134
+ orgId: input.orgId,
135
+ body: input.rawBody,
136
+ timestamp
137
+ });
138
+ const key = (0, import_node_crypto2.createPublicKey)({
139
+ key: Buffer.from(input.publicKey, "base64"),
140
+ format: "der",
141
+ type: "spki"
142
+ });
143
+ return (0, import_node_crypto2.verify)(null, Buffer.from(canonical, "utf8"), key, Buffer.from(input.signature, "base64"));
144
+ } catch {
145
+ return false;
146
+ }
147
+ }
148
+ __name(verifySignedRequest, "verifySignedRequest");
149
+ // Annotate the CommonJS export names for ESM import in node:
150
+ 0 && (module.exports = {
151
+ buildRequestCanonical,
152
+ canonicalStringify,
153
+ generateSigningKeyPair,
154
+ signDocument,
155
+ signRequestHeaders,
156
+ verifyDocument,
157
+ verifySignedRequest
158
+ });
159
+ //# sourceMappingURL=signing.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/signing/index.ts","../src/signing/canonical.ts","../src/signing/document.ts","../src/signing/request.ts"],"sourcesContent":["// Signing module — Ed25519 primitives: keypairs, canonical-JSON document signing, and signed control-plane requests\nexport { canonicalStringify } from './canonical';\nexport { generateSigningKeyPair, type SignedDocument, signDocument, verifyDocument } from './document';\nexport {\n buildRequestCanonical,\n type RequestCanonicalInput,\n type SignRequestInput,\n signRequestHeaders,\n type VerifySignedRequestInput,\n verifySignedRequest,\n} from './request';\n","// Serializes a value as deterministic JSON: object keys recursively sorted, arrays keep their order\nexport function canonicalStringify(value: unknown): string {\n return JSON.stringify(sortKeysDeep(value));\n}\n\n// Recursively rebuilds objects with sorted keys so JSON.stringify output is order-independent\nfunction sortKeysDeep(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeysDeep);\n if (value !== null && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(record).sort()) sorted[key] = sortKeysDeep(record[key]);\n return sorted;\n }\n return value;\n}\n","import { createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify } from 'node:crypto';\nimport { canonicalStringify } from './canonical';\n\nexport interface SignedDocument<T> {\n payload: T;\n signature: string;\n}\n\n// Generates an Ed25519 key pair as base64 DER strings (pkcs8 private / spki public)\nexport function generateSigningKeyPair(): { privateKey: string; publicKey: string } {\n const { privateKey, publicKey } = generateKeyPairSync('ed25519');\n return {\n privateKey: privateKey.export({ type: 'pkcs8', format: 'der' }).toString('base64'),\n publicKey: publicKey.export({ type: 'spki', format: 'der' }).toString('base64'),\n };\n}\n\n// Signs a payload's canonical JSON with an Ed25519 private key (base64 pkcs8 DER)\nexport function signDocument<T>(payload: T, privateKeyBase64: string): SignedDocument<T> {\n const key = createPrivateKey({ key: Buffer.from(privateKeyBase64, 'base64'), format: 'der', type: 'pkcs8' });\n const signature = sign(null, Buffer.from(canonicalStringify(payload), 'utf8'), key).toString('base64');\n return { payload, signature };\n}\n\n// Verifies a signed document against an Ed25519 public key (base64 spki DER); malformed input ⇒ false\nexport function verifyDocument<T>(doc: SignedDocument<T>, publicKeyBase64: string): boolean {\n try {\n const key = createPublicKey({ key: Buffer.from(publicKeyBase64, 'base64'), format: 'der', type: 'spki' });\n return verify(\n null,\n Buffer.from(canonicalStringify(doc.payload), 'utf8'),\n key,\n Buffer.from(doc.signature, 'base64'),\n );\n } catch {\n return false;\n }\n}\n","import { createHash, createPrivateKey, createPublicKey, sign, verify } from 'node:crypto';\n\nexport interface RequestCanonicalInput {\n method: string;\n path: string;\n orgId?: string;\n body?: string | Buffer;\n timestamp: number;\n}\n\nexport interface SignRequestInput {\n method: string;\n path: string;\n orgId?: string;\n body?: string | Buffer;\n}\n\nexport interface VerifySignedRequestInput {\n method: string;\n path: string;\n orgId?: string;\n rawBody?: string | Buffer;\n timestamp: string | number;\n signature: string;\n publicKey: string;\n maxSkewSeconds?: number;\n}\n\n// Builds the canonical string signed for a control-plane request: METHOD\\npath\\norgId\\nsha256hex(body)\\ntimestamp\nexport function buildRequestCanonical(input: RequestCanonicalInput): string {\n const bodyHash = createHash('sha256')\n .update(input.body ?? '')\n .digest('hex');\n return [input.method.toUpperCase(), input.path, input.orgId ?? '', bodyHash, String(input.timestamp)].join('\\n');\n}\n\n// Signs a request with an Ed25519 private key (base64 pkcs8 DER), stamping the current unix time\nexport function signRequestHeaders(\n input: SignRequestInput,\n privateKeyBase64: string,\n): { 'x-timestamp': string; 'x-signature': string } {\n const timestamp = Math.floor(Date.now() / 1000);\n const canonical = buildRequestCanonical({ ...input, timestamp });\n const key = createPrivateKey({ key: Buffer.from(privateKeyBase64, 'base64'), format: 'der', type: 'pkcs8' });\n const signature = sign(null, Buffer.from(canonical, 'utf8'), key).toString('base64');\n return { 'x-timestamp': String(timestamp), 'x-signature': signature };\n}\n\n// Verifies a signed request (signature + timestamp skew) against an Ed25519 public key; malformed input ⇒ false\nexport function verifySignedRequest(input: VerifySignedRequestInput): boolean {\n try {\n const timestamp = Number(input.timestamp);\n if (!Number.isFinite(timestamp)) return false;\n const maxSkew = input.maxSkewSeconds ?? 300;\n if (Math.abs(Math.floor(Date.now() / 1000) - timestamp) > maxSkew) return false;\n const canonical = buildRequestCanonical({\n method: input.method,\n path: input.path,\n orgId: input.orgId,\n body: input.rawBody,\n timestamp,\n });\n const key = createPublicKey({ key: Buffer.from(input.publicKey, 'base64'), format: 'der', type: 'spki' });\n return verify(null, Buffer.from(canonical, 'utf8'), key, Buffer.from(input.signature, 'base64'));\n } catch {\n return false;\n }\n}\n"],"mappings":"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","names":["canonicalStringify","value","JSON","stringify","sortKeysDeep","Array","isArray","map","record","sorted","key","Object","keys","sort","generateSigningKeyPair","privateKey","publicKey","generateKeyPairSync","export","type","format","toString","signDocument","payload","privateKeyBase64","key","createPrivateKey","Buffer","from","signature","sign","canonicalStringify","verifyDocument","doc","publicKeyBase64","createPublicKey","verify","import_node_crypto","buildRequestCanonical","input","bodyHash","createHash","update","body","digest","method","toUpperCase","path","orgId","String","timestamp","join","signRequestHeaders","privateKeyBase64","Math","floor","Date","now","canonical","key","createPrivateKey","Buffer","from","format","type","signature","sign","toString","verifySignedRequest","Number","isFinite","maxSkew","maxSkewSeconds","abs","rawBody","createPublicKey","publicKey","verify"]}
@@ -0,0 +1,35 @@
1
+ export { S as SignedDocument, g as generateSigningKeyPair, s as signDocument, v as verifyDocument } from './document-BoS0NIbf.cjs';
2
+
3
+ declare function canonicalStringify(value: unknown): string;
4
+
5
+ interface RequestCanonicalInput {
6
+ method: string;
7
+ path: string;
8
+ orgId?: string;
9
+ body?: string | Buffer;
10
+ timestamp: number;
11
+ }
12
+ interface SignRequestInput {
13
+ method: string;
14
+ path: string;
15
+ orgId?: string;
16
+ body?: string | Buffer;
17
+ }
18
+ interface VerifySignedRequestInput {
19
+ method: string;
20
+ path: string;
21
+ orgId?: string;
22
+ rawBody?: string | Buffer;
23
+ timestamp: string | number;
24
+ signature: string;
25
+ publicKey: string;
26
+ maxSkewSeconds?: number;
27
+ }
28
+ declare function buildRequestCanonical(input: RequestCanonicalInput): string;
29
+ declare function signRequestHeaders(input: SignRequestInput, privateKeyBase64: string): {
30
+ 'x-timestamp': string;
31
+ 'x-signature': string;
32
+ };
33
+ declare function verifySignedRequest(input: VerifySignedRequestInput): boolean;
34
+
35
+ export { type RequestCanonicalInput, type SignRequestInput, type VerifySignedRequestInput, buildRequestCanonical, canonicalStringify, signRequestHeaders, verifySignedRequest };
@@ -0,0 +1,35 @@
1
+ export { S as SignedDocument, g as generateSigningKeyPair, s as signDocument, v as verifyDocument } from './document-BoS0NIbf.js';
2
+
3
+ declare function canonicalStringify(value: unknown): string;
4
+
5
+ interface RequestCanonicalInput {
6
+ method: string;
7
+ path: string;
8
+ orgId?: string;
9
+ body?: string | Buffer;
10
+ timestamp: number;
11
+ }
12
+ interface SignRequestInput {
13
+ method: string;
14
+ path: string;
15
+ orgId?: string;
16
+ body?: string | Buffer;
17
+ }
18
+ interface VerifySignedRequestInput {
19
+ method: string;
20
+ path: string;
21
+ orgId?: string;
22
+ rawBody?: string | Buffer;
23
+ timestamp: string | number;
24
+ signature: string;
25
+ publicKey: string;
26
+ maxSkewSeconds?: number;
27
+ }
28
+ declare function buildRequestCanonical(input: RequestCanonicalInput): string;
29
+ declare function signRequestHeaders(input: SignRequestInput, privateKeyBase64: string): {
30
+ 'x-timestamp': string;
31
+ 'x-signature': string;
32
+ };
33
+ declare function verifySignedRequest(input: VerifySignedRequestInput): boolean;
34
+
35
+ export { type RequestCanonicalInput, type SignRequestInput, type VerifySignedRequestInput, buildRequestCanonical, canonicalStringify, signRequestHeaders, verifySignedRequest };
@@ -0,0 +1,128 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/signing/canonical.ts
5
+ function canonicalStringify(value) {
6
+ return JSON.stringify(sortKeysDeep(value));
7
+ }
8
+ __name(canonicalStringify, "canonicalStringify");
9
+ function sortKeysDeep(value) {
10
+ if (Array.isArray(value)) return value.map(sortKeysDeep);
11
+ if (value !== null && typeof value === "object") {
12
+ const record = value;
13
+ const sorted = {};
14
+ for (const key of Object.keys(record).sort()) sorted[key] = sortKeysDeep(record[key]);
15
+ return sorted;
16
+ }
17
+ return value;
18
+ }
19
+ __name(sortKeysDeep, "sortKeysDeep");
20
+
21
+ // src/signing/document.ts
22
+ import { createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify } from "crypto";
23
+ function generateSigningKeyPair() {
24
+ const { privateKey, publicKey } = generateKeyPairSync("ed25519");
25
+ return {
26
+ privateKey: privateKey.export({
27
+ type: "pkcs8",
28
+ format: "der"
29
+ }).toString("base64"),
30
+ publicKey: publicKey.export({
31
+ type: "spki",
32
+ format: "der"
33
+ }).toString("base64")
34
+ };
35
+ }
36
+ __name(generateSigningKeyPair, "generateSigningKeyPair");
37
+ function signDocument(payload, privateKeyBase64) {
38
+ const key = createPrivateKey({
39
+ key: Buffer.from(privateKeyBase64, "base64"),
40
+ format: "der",
41
+ type: "pkcs8"
42
+ });
43
+ const signature = sign(null, Buffer.from(canonicalStringify(payload), "utf8"), key).toString("base64");
44
+ return {
45
+ payload,
46
+ signature
47
+ };
48
+ }
49
+ __name(signDocument, "signDocument");
50
+ function verifyDocument(doc, publicKeyBase64) {
51
+ try {
52
+ const key = createPublicKey({
53
+ key: Buffer.from(publicKeyBase64, "base64"),
54
+ format: "der",
55
+ type: "spki"
56
+ });
57
+ return verify(null, Buffer.from(canonicalStringify(doc.payload), "utf8"), key, Buffer.from(doc.signature, "base64"));
58
+ } catch {
59
+ return false;
60
+ }
61
+ }
62
+ __name(verifyDocument, "verifyDocument");
63
+
64
+ // src/signing/request.ts
65
+ import { createHash, createPrivateKey as createPrivateKey2, createPublicKey as createPublicKey2, sign as sign2, verify as verify2 } from "crypto";
66
+ function buildRequestCanonical(input) {
67
+ const bodyHash = createHash("sha256").update(input.body ?? "").digest("hex");
68
+ return [
69
+ input.method.toUpperCase(),
70
+ input.path,
71
+ input.orgId ?? "",
72
+ bodyHash,
73
+ String(input.timestamp)
74
+ ].join("\n");
75
+ }
76
+ __name(buildRequestCanonical, "buildRequestCanonical");
77
+ function signRequestHeaders(input, privateKeyBase64) {
78
+ const timestamp = Math.floor(Date.now() / 1e3);
79
+ const canonical = buildRequestCanonical({
80
+ ...input,
81
+ timestamp
82
+ });
83
+ const key = createPrivateKey2({
84
+ key: Buffer.from(privateKeyBase64, "base64"),
85
+ format: "der",
86
+ type: "pkcs8"
87
+ });
88
+ const signature = sign2(null, Buffer.from(canonical, "utf8"), key).toString("base64");
89
+ return {
90
+ "x-timestamp": String(timestamp),
91
+ "x-signature": signature
92
+ };
93
+ }
94
+ __name(signRequestHeaders, "signRequestHeaders");
95
+ function verifySignedRequest(input) {
96
+ try {
97
+ const timestamp = Number(input.timestamp);
98
+ if (!Number.isFinite(timestamp)) return false;
99
+ const maxSkew = input.maxSkewSeconds ?? 300;
100
+ if (Math.abs(Math.floor(Date.now() / 1e3) - timestamp) > maxSkew) return false;
101
+ const canonical = buildRequestCanonical({
102
+ method: input.method,
103
+ path: input.path,
104
+ orgId: input.orgId,
105
+ body: input.rawBody,
106
+ timestamp
107
+ });
108
+ const key = createPublicKey2({
109
+ key: Buffer.from(input.publicKey, "base64"),
110
+ format: "der",
111
+ type: "spki"
112
+ });
113
+ return verify2(null, Buffer.from(canonical, "utf8"), key, Buffer.from(input.signature, "base64"));
114
+ } catch {
115
+ return false;
116
+ }
117
+ }
118
+ __name(verifySignedRequest, "verifySignedRequest");
119
+ export {
120
+ buildRequestCanonical,
121
+ canonicalStringify,
122
+ generateSigningKeyPair,
123
+ signDocument,
124
+ signRequestHeaders,
125
+ verifyDocument,
126
+ verifySignedRequest
127
+ };
128
+ //# sourceMappingURL=signing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/signing/canonical.ts","../src/signing/document.ts","../src/signing/request.ts"],"sourcesContent":["// Serializes a value as deterministic JSON: object keys recursively sorted, arrays keep their order\nexport function canonicalStringify(value: unknown): string {\n return JSON.stringify(sortKeysDeep(value));\n}\n\n// Recursively rebuilds objects with sorted keys so JSON.stringify output is order-independent\nfunction sortKeysDeep(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeysDeep);\n if (value !== null && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(record).sort()) sorted[key] = sortKeysDeep(record[key]);\n return sorted;\n }\n return value;\n}\n","import { createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify } from 'node:crypto';\nimport { canonicalStringify } from './canonical';\n\nexport interface SignedDocument<T> {\n payload: T;\n signature: string;\n}\n\n// Generates an Ed25519 key pair as base64 DER strings (pkcs8 private / spki public)\nexport function generateSigningKeyPair(): { privateKey: string; publicKey: string } {\n const { privateKey, publicKey } = generateKeyPairSync('ed25519');\n return {\n privateKey: privateKey.export({ type: 'pkcs8', format: 'der' }).toString('base64'),\n publicKey: publicKey.export({ type: 'spki', format: 'der' }).toString('base64'),\n };\n}\n\n// Signs a payload's canonical JSON with an Ed25519 private key (base64 pkcs8 DER)\nexport function signDocument<T>(payload: T, privateKeyBase64: string): SignedDocument<T> {\n const key = createPrivateKey({ key: Buffer.from(privateKeyBase64, 'base64'), format: 'der', type: 'pkcs8' });\n const signature = sign(null, Buffer.from(canonicalStringify(payload), 'utf8'), key).toString('base64');\n return { payload, signature };\n}\n\n// Verifies a signed document against an Ed25519 public key (base64 spki DER); malformed input ⇒ false\nexport function verifyDocument<T>(doc: SignedDocument<T>, publicKeyBase64: string): boolean {\n try {\n const key = createPublicKey({ key: Buffer.from(publicKeyBase64, 'base64'), format: 'der', type: 'spki' });\n return verify(\n null,\n Buffer.from(canonicalStringify(doc.payload), 'utf8'),\n key,\n Buffer.from(doc.signature, 'base64'),\n );\n } catch {\n return false;\n }\n}\n","import { createHash, createPrivateKey, createPublicKey, sign, verify } from 'node:crypto';\n\nexport interface RequestCanonicalInput {\n method: string;\n path: string;\n orgId?: string;\n body?: string | Buffer;\n timestamp: number;\n}\n\nexport interface SignRequestInput {\n method: string;\n path: string;\n orgId?: string;\n body?: string | Buffer;\n}\n\nexport interface VerifySignedRequestInput {\n method: string;\n path: string;\n orgId?: string;\n rawBody?: string | Buffer;\n timestamp: string | number;\n signature: string;\n publicKey: string;\n maxSkewSeconds?: number;\n}\n\n// Builds the canonical string signed for a control-plane request: METHOD\\npath\\norgId\\nsha256hex(body)\\ntimestamp\nexport function buildRequestCanonical(input: RequestCanonicalInput): string {\n const bodyHash = createHash('sha256')\n .update(input.body ?? '')\n .digest('hex');\n return [input.method.toUpperCase(), input.path, input.orgId ?? '', bodyHash, String(input.timestamp)].join('\\n');\n}\n\n// Signs a request with an Ed25519 private key (base64 pkcs8 DER), stamping the current unix time\nexport function signRequestHeaders(\n input: SignRequestInput,\n privateKeyBase64: string,\n): { 'x-timestamp': string; 'x-signature': string } {\n const timestamp = Math.floor(Date.now() / 1000);\n const canonical = buildRequestCanonical({ ...input, timestamp });\n const key = createPrivateKey({ key: Buffer.from(privateKeyBase64, 'base64'), format: 'der', type: 'pkcs8' });\n const signature = sign(null, Buffer.from(canonical, 'utf8'), key).toString('base64');\n return { 'x-timestamp': String(timestamp), 'x-signature': signature };\n}\n\n// Verifies a signed request (signature + timestamp skew) against an Ed25519 public key; malformed input ⇒ false\nexport function verifySignedRequest(input: VerifySignedRequestInput): boolean {\n try {\n const timestamp = Number(input.timestamp);\n if (!Number.isFinite(timestamp)) return false;\n const maxSkew = input.maxSkewSeconds ?? 300;\n if (Math.abs(Math.floor(Date.now() / 1000) - timestamp) > maxSkew) return false;\n const canonical = buildRequestCanonical({\n method: input.method,\n path: input.path,\n orgId: input.orgId,\n body: input.rawBody,\n timestamp,\n });\n const key = createPublicKey({ key: Buffer.from(input.publicKey, 'base64'), format: 'der', type: 'spki' });\n return verify(null, Buffer.from(canonical, 'utf8'), key, Buffer.from(input.signature, 'base64'));\n } catch {\n return false;\n }\n}\n"],"mappings":"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","names":["canonicalStringify","value","JSON","stringify","sortKeysDeep","Array","isArray","map","record","sorted","key","Object","keys","sort","createPrivateKey","createPublicKey","generateKeyPairSync","sign","verify","generateSigningKeyPair","privateKey","publicKey","generateKeyPairSync","export","type","format","toString","signDocument","payload","privateKeyBase64","key","createPrivateKey","Buffer","from","signature","sign","canonicalStringify","verifyDocument","doc","publicKeyBase64","createPublicKey","verify","createHash","createPrivateKey","createPublicKey","sign","verify","buildRequestCanonical","input","bodyHash","createHash","update","body","digest","method","toUpperCase","path","orgId","String","timestamp","join","signRequestHeaders","privateKeyBase64","Math","floor","Date","now","canonical","key","createPrivateKey","Buffer","from","format","type","signature","sign","toString","verifySignedRequest","Number","isFinite","maxSkew","maxSkewSeconds","abs","rawBody","createPublicKey","publicKey","verify"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vritti/api-sdk",
3
3
  "type": "module",
4
- "version": "0.3.2",
4
+ "version": "0.3.3",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -126,6 +126,16 @@
126
126
  "default": "./dist/license.cjs"
127
127
  }
128
128
  },
129
+ "./signing": {
130
+ "import": {
131
+ "types": "./dist/signing.d.ts",
132
+ "default": "./dist/signing.js"
133
+ },
134
+ "require": {
135
+ "types": "./dist/signing.d.cts",
136
+ "default": "./dist/signing.cjs"
137
+ }
138
+ },
129
139
  "./cache": {
130
140
  "import": {
131
141
  "types": "./dist/cache.d.ts",