@opengeni/sdk 3.1.2 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/artifacts.js +3 -3
  2. package/dist/browser.js +1 -1
  3. package/dist/chat/index.js +4 -4
  4. package/dist/{chunk-NEM5N6C6.js → chunk-JKG75TTU.js} +35 -1
  5. package/dist/chunk-JKG75TTU.js.map +1 -0
  6. package/dist/{chunk-YDVPI7WT.js → chunk-JP62FZSI.js} +2 -2
  7. package/dist/chunk-KGEABAID.js +71 -0
  8. package/dist/chunk-KGEABAID.js.map +1 -0
  9. package/dist/{chunk-S3D75WSQ.js → chunk-N2I422X4.js} +2 -2
  10. package/dist/{chunk-JXXCTW5W.js → chunk-PBVUAXSU.js} +2 -2
  11. package/dist/{chunk-OAKHWFSV.js → chunk-PDU6EU2M.js} +2 -2
  12. package/dist/{chunk-RJHCBZF7.js → chunk-VT4YM4XQ.js} +8 -68
  13. package/dist/{chunk-RJHCBZF7.js.map → chunk-VT4YM4XQ.js.map} +1 -1
  14. package/dist/core.js +2 -2
  15. package/dist/document-authority.js +2 -2
  16. package/dist/external-vault-receiver.d.ts +203 -0
  17. package/dist/external-vault-receiver.js +564 -0
  18. package/dist/external-vault-receiver.js.map +1 -0
  19. package/dist/index.js +13 -11
  20. package/dist/index.js.map +1 -1
  21. package/dist/site-bridge-host.js +2 -2
  22. package/dist/site-browser-runtime.gen.d.ts +1 -1
  23. package/dist/site-document.js +1 -1
  24. package/dist/site-document.js.map +1 -1
  25. package/dist/site.js +2 -2
  26. package/dist/vault-types.d.ts +91 -3
  27. package/dist/vaults-api.d.ts +9 -1
  28. package/dist/workspace-integrations.js +11 -9
  29. package/package.json +7 -3
  30. package/src/external-vault-receiver.ts +914 -0
  31. package/src/site-browser-runtime.gen.ts +1 -1
  32. package/src/vault-types.ts +88 -2
  33. package/src/vaults-api.ts +51 -0
  34. package/dist/chunk-NEM5N6C6.js.map +0 -1
  35. /package/dist/{chunk-YDVPI7WT.js.map → chunk-JP62FZSI.js.map} +0 -0
  36. /package/dist/{chunk-S3D75WSQ.js.map → chunk-N2I422X4.js.map} +0 -0
  37. /package/dist/{chunk-JXXCTW5W.js.map → chunk-PBVUAXSU.js.map} +0 -0
  38. /package/dist/{chunk-OAKHWFSV.js.map → chunk-PDU6EU2M.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  OpenGeniClient
3
- } from "./chunk-NEM5N6C6.js";
3
+ } from "./chunk-JKG75TTU.js";
4
4
 
5
5
  // src/document-authority-client.ts
6
6
  var OpenGeniDocumentAuthorityClient = class extends OpenGeniClient {
@@ -147,4 +147,4 @@ var OpenGeniDocumentAuthorityClient = class extends OpenGeniClient {
147
147
  export {
148
148
  OpenGeniDocumentAuthorityClient
149
149
  };
150
- //# sourceMappingURL=chunk-YDVPI7WT.js.map
150
+ //# sourceMappingURL=chunk-JP62FZSI.js.map
@@ -0,0 +1,71 @@
1
+ // ../contracts/src/workspace-integration-wire.ts
2
+ var WORKSPACE_WEBHOOK_EVENT_TYPES = [
3
+ "turn.completed",
4
+ "turn.failed",
5
+ "turn.cancelled",
6
+ "session.status.changed",
7
+ "session.requiresAction",
8
+ "session.humanInput.requested",
9
+ "session.notification.posted",
10
+ "session.notification.withdrawn",
11
+ "usage.threshold_reached",
12
+ "usage.exhausted",
13
+ "usage.period_reset"
14
+ ];
15
+ var OPENGENI_WEBHOOK_TEST_EVENT_TYPE = "webhook.test";
16
+ var OPENGENI_TEST_REQUEST_NIL_ID = "00000000-0000-0000-0000-000000000000";
17
+ var OPENGENI_SIGNATURE_HEADER = "OpenGeni-Signature";
18
+ var OPENGENI_EVENT_ID_HEADER = "OpenGeni-Event-Id";
19
+ var OPENGENI_DELIVERY_ID_HEADER = "OpenGeni-Delivery-Id";
20
+ var OPENGENI_SIGNATURE_TOLERANCE_SECONDS = 300;
21
+ var encoder = new TextEncoder();
22
+ async function hmacSha256Hex(secret, message) {
23
+ const key = await crypto.subtle.importKey(
24
+ "raw",
25
+ encoder.encode(secret),
26
+ { name: "HMAC", hash: "SHA-256" },
27
+ false,
28
+ ["sign"]
29
+ );
30
+ const signature = new Uint8Array(await crypto.subtle.sign("HMAC", key, encoder.encode(message)));
31
+ return Array.from(signature, (byte) => byte.toString(16).padStart(2, "0")).join("");
32
+ }
33
+ function constantTimeEqualHex(left, right) {
34
+ if (left.length !== right.length) return false;
35
+ let difference = 0;
36
+ for (let index = 0; index < left.length; index += 1) {
37
+ difference |= left.charCodeAt(index) ^ right.charCodeAt(index);
38
+ }
39
+ return difference === 0;
40
+ }
41
+ async function signOpenGeniPayload(secret, body, timestampSeconds = Math.floor(Date.now() / 1e3)) {
42
+ return `t=${timestampSeconds},v1=${await hmacSha256Hex(secret, `${timestampSeconds}.${body}`)}`;
43
+ }
44
+ async function verifyOpenGeniSignature(input) {
45
+ if (!input.signature) return false;
46
+ let timestamp = null;
47
+ const candidates = [];
48
+ for (const part of input.signature.split(",")) {
49
+ const [key, value] = part.trim().split("=", 2);
50
+ if (key === "t" && value && /^\d{1,12}$/.test(value)) timestamp = Number(value);
51
+ if (key === "v1" && value && /^[0-9a-f]{64}$/.test(value)) candidates.push(value);
52
+ }
53
+ if (timestamp === null || candidates.length === 0) return false;
54
+ const now = input.nowSeconds ?? Math.floor(Date.now() / 1e3);
55
+ const tolerance = input.toleranceSeconds ?? OPENGENI_SIGNATURE_TOLERANCE_SECONDS;
56
+ if (Math.abs(now - timestamp) > tolerance) return false;
57
+ const expected = await hmacSha256Hex(input.secret, `${timestamp}.${input.body}`);
58
+ return candidates.some((candidate) => constantTimeEqualHex(candidate, expected));
59
+ }
60
+
61
+ export {
62
+ WORKSPACE_WEBHOOK_EVENT_TYPES,
63
+ OPENGENI_WEBHOOK_TEST_EVENT_TYPE,
64
+ OPENGENI_TEST_REQUEST_NIL_ID,
65
+ OPENGENI_SIGNATURE_HEADER,
66
+ OPENGENI_EVENT_ID_HEADER,
67
+ OPENGENI_DELIVERY_ID_HEADER,
68
+ signOpenGeniPayload,
69
+ verifyOpenGeniSignature
70
+ };
71
+ //# sourceMappingURL=chunk-KGEABAID.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../contracts/src/workspace-integration-wire.ts"],"sourcesContent":["/**\n * Dependency-free wire constants and the OpenGeni-Signature scheme shared by\n * workspace webhooks and credential providers. Kept free of zod so browser and\n * React Native bundles can verify signatures without the schema runtime.\n */\n\nexport const WORKSPACE_WEBHOOK_EVENT_TYPES = [\n \"turn.completed\",\n \"turn.failed\",\n \"turn.cancelled\",\n \"session.status.changed\",\n \"session.requiresAction\",\n \"session.humanInput.requested\",\n \"session.notification.posted\",\n \"session.notification.withdrawn\",\n \"usage.threshold_reached\",\n \"usage.exhausted\",\n \"usage.period_reset\",\n] as const;\n\n/**\n * Sent only when an administrator presses \"Send test event\". It is never a\n * subscribable type: every endpoint can receive it, and a receiver that does\n * not care acknowledges it with any 2xx.\n */\nexport const OPENGENI_WEBHOOK_TEST_EVENT_TYPE = \"webhook.test\";\n\n/**\n * The session, turn and attempt ids of a credential-provider test request\n * (`purpose: \"test\"`). A test is not a run, so no real ids exist.\n */\nexport const OPENGENI_TEST_REQUEST_NIL_ID = \"00000000-0000-0000-0000-000000000000\";\n\nexport const OPENGENI_SIGNATURE_HEADER = \"OpenGeni-Signature\";\nexport const OPENGENI_EVENT_ID_HEADER = \"OpenGeni-Event-Id\";\nexport const OPENGENI_DELIVERY_ID_HEADER = \"OpenGeni-Delivery-Id\";\nexport const OPENGENI_SIGNATURE_TOLERANCE_SECONDS = 300;\n\nconst encoder = new TextEncoder();\n\nasync function hmacSha256Hex(secret: string, message: string): Promise<string> {\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n const signature = new Uint8Array(await crypto.subtle.sign(\"HMAC\", key, encoder.encode(message)));\n return Array.from(signature, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nfunction constantTimeEqualHex(left: string, right: string): boolean {\n if (left.length !== right.length) return false;\n let difference = 0;\n for (let index = 0; index < left.length; index += 1) {\n difference |= left.charCodeAt(index) ^ right.charCodeAt(index);\n }\n return difference === 0;\n}\n\n/**\n * `OpenGeni-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, \"<t>.<body>\")>`.\n * The timestamp is signed so a captured request cannot be replayed later.\n */\nexport async function signOpenGeniPayload(\n secret: string,\n body: string,\n timestampSeconds = Math.floor(Date.now() / 1000),\n): Promise<string> {\n return `t=${timestampSeconds},v1=${await hmacSha256Hex(secret, `${timestampSeconds}.${body}`)}`;\n}\n\nexport type VerifyOpenGeniSignatureInput = {\n secret: string;\n /** The exact raw request body, before JSON parsing. */\n body: string;\n /** The `OpenGeni-Signature` header value. */\n signature: string | null | undefined;\n toleranceSeconds?: number;\n nowSeconds?: number;\n};\n\nexport async function verifyOpenGeniSignature(\n input: VerifyOpenGeniSignatureInput,\n): Promise<boolean> {\n if (!input.signature) return false;\n let timestamp: number | null = null;\n const candidates: string[] = [];\n for (const part of input.signature.split(\",\")) {\n const [key, value] = part.trim().split(\"=\", 2);\n if (key === \"t\" && value && /^\\d{1,12}$/.test(value)) timestamp = Number(value);\n if (key === \"v1\" && value && /^[0-9a-f]{64}$/.test(value)) candidates.push(value);\n }\n if (timestamp === null || candidates.length === 0) return false;\n const now = input.nowSeconds ?? Math.floor(Date.now() / 1000);\n const tolerance = input.toleranceSeconds ?? OPENGENI_SIGNATURE_TOLERANCE_SECONDS;\n if (Math.abs(now - timestamp) > tolerance) return false;\n const expected = await hmacSha256Hex(input.secret, `${timestamp}.${input.body}`);\n return candidates.some((candidate) => constantTimeEqualHex(candidate, expected));\n}\n"],"mappings":";AAMO,IAAM,gCAAgC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAOO,IAAM,mCAAmC;AAMzC,IAAM,+BAA+B;AAErC,IAAM,4BAA4B;AAClC,IAAM,2BAA2B;AACjC,IAAM,8BAA8B;AACpC,IAAM,uCAAuC;AAEpD,IAAM,UAAU,IAAI,YAAY;AAEhC,eAAe,cAAc,QAAgB,SAAkC;AAC7E,QAAM,MAAM,MAAM,OAAO,OAAO;AAAA,IAC9B;AAAA,IACA,QAAQ,OAAO,MAAM;AAAA,IACrB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,IAChC;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AACA,QAAM,YAAY,IAAI,WAAW,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,OAAO,CAAC,CAAC;AAC/F,SAAO,MAAM,KAAK,WAAW,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AACpF;AAEA,SAAS,qBAAqB,MAAc,OAAwB;AAClE,MAAI,KAAK,WAAW,MAAM,OAAQ,QAAO;AACzC,MAAI,aAAa;AACjB,WAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,GAAG;AACnD,kBAAc,KAAK,WAAW,KAAK,IAAI,MAAM,WAAW,KAAK;AAAA,EAC/D;AACA,SAAO,eAAe;AACxB;AAMA,eAAsB,oBACpB,QACA,MACA,mBAAmB,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,GAC9B;AACjB,SAAO,KAAK,gBAAgB,OAAO,MAAM,cAAc,QAAQ,GAAG,gBAAgB,IAAI,IAAI,EAAE,CAAC;AAC/F;AAYA,eAAsB,wBACpB,OACkB;AAClB,MAAI,CAAC,MAAM,UAAW,QAAO;AAC7B,MAAI,YAA2B;AAC/B,QAAM,aAAuB,CAAC;AAC9B,aAAW,QAAQ,MAAM,UAAU,MAAM,GAAG,GAAG;AAC7C,UAAM,CAAC,KAAK,KAAK,IAAI,KAAK,KAAK,EAAE,MAAM,KAAK,CAAC;AAC7C,QAAI,QAAQ,OAAO,SAAS,aAAa,KAAK,KAAK,EAAG,aAAY,OAAO,KAAK;AAC9E,QAAI,QAAQ,QAAQ,SAAS,iBAAiB,KAAK,KAAK,EAAG,YAAW,KAAK,KAAK;AAAA,EAClF;AACA,MAAI,cAAc,QAAQ,WAAW,WAAW,EAAG,QAAO;AAC1D,QAAM,MAAM,MAAM,cAAc,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAC5D,QAAM,YAAY,MAAM,oBAAoB;AAC5C,MAAI,KAAK,IAAI,MAAM,SAAS,IAAI,UAAW,QAAO;AAClD,QAAM,WAAW,MAAM,cAAc,MAAM,QAAQ,GAAG,SAAS,IAAI,MAAM,IAAI,EAAE;AAC/E,SAAO,WAAW,KAAK,CAAC,cAAc,qBAAqB,WAAW,QAAQ,CAAC;AACjF;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  OpenGeniClient
3
- } from "./chunk-OAKHWFSV.js";
3
+ } from "./chunk-PDU6EU2M.js";
4
4
 
5
5
  // src/embedding-client.ts
6
6
  function hasStaticHeader(options, names) {
@@ -337,4 +337,4 @@ export {
337
337
  EMPTY_FINAL_REPLY_NOTICE,
338
338
  turnCompletedWithEmptyFinalReply
339
339
  };
340
- //# sourceMappingURL=chunk-S3D75WSQ.js.map
340
+ //# sourceMappingURL=chunk-N2I422X4.js.map
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-P7UWKORG.js";
5
5
  import {
6
6
  OpenGeniClient
7
- } from "./chunk-NEM5N6C6.js";
7
+ } from "./chunk-JKG75TTU.js";
8
8
  import {
9
9
  OpenGeniApiError
10
10
  } from "./chunk-7EWT3PV6.js";
@@ -1389,4 +1389,4 @@ export {
1389
1389
  sanitizeOpenGeniSiteToolCallRequest,
1390
1390
  sanitizeOpenGeniSiteToolInvokeRequest
1391
1391
  };
1392
- //# sourceMappingURL=chunk-JXXCTW5W.js.map
1392
+ //# sourceMappingURL=chunk-PBVUAXSU.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  OpenGeniDocumentAuthorityClient
3
- } from "./chunk-YDVPI7WT.js";
3
+ } from "./chunk-JP62FZSI.js";
4
4
 
5
5
  // src/artifact-client.ts
6
6
  var OpenGeniClient = class extends OpenGeniDocumentAuthorityClient {
@@ -121,4 +121,4 @@ var OpenGeniClient = class extends OpenGeniDocumentAuthorityClient {
121
121
  export {
122
122
  OpenGeniClient
123
123
  };
124
- //# sourceMappingURL=chunk-OAKHWFSV.js.map
124
+ //# sourceMappingURL=chunk-PDU6EU2M.js.map
@@ -1,62 +1,10 @@
1
- // ../contracts/src/workspace-integration-wire.ts
2
- var WORKSPACE_WEBHOOK_EVENT_TYPES = [
3
- "turn.completed",
4
- "turn.failed",
5
- "turn.cancelled",
6
- "session.status.changed",
7
- "session.requiresAction",
8
- "session.humanInput.requested",
9
- "session.notification.posted",
10
- "session.notification.withdrawn",
11
- "usage.threshold_reached",
12
- "usage.exhausted",
13
- "usage.period_reset"
14
- ];
15
- var OPENGENI_WEBHOOK_TEST_EVENT_TYPE = "webhook.test";
16
- var OPENGENI_TEST_REQUEST_NIL_ID = "00000000-0000-0000-0000-000000000000";
17
- var OPENGENI_SIGNATURE_HEADER = "OpenGeni-Signature";
18
- var OPENGENI_EVENT_ID_HEADER = "OpenGeni-Event-Id";
19
- var OPENGENI_DELIVERY_ID_HEADER = "OpenGeni-Delivery-Id";
20
- var OPENGENI_SIGNATURE_TOLERANCE_SECONDS = 300;
21
- var encoder = new TextEncoder();
22
- async function hmacSha256Hex(secret, message) {
23
- const key = await crypto.subtle.importKey(
24
- "raw",
25
- encoder.encode(secret),
26
- { name: "HMAC", hash: "SHA-256" },
27
- false,
28
- ["sign"]
29
- );
30
- const signature = new Uint8Array(await crypto.subtle.sign("HMAC", key, encoder.encode(message)));
31
- return Array.from(signature, (byte) => byte.toString(16).padStart(2, "0")).join("");
32
- }
33
- function constantTimeEqualHex(left, right) {
34
- if (left.length !== right.length) return false;
35
- let difference = 0;
36
- for (let index = 0; index < left.length; index += 1) {
37
- difference |= left.charCodeAt(index) ^ right.charCodeAt(index);
38
- }
39
- return difference === 0;
40
- }
41
- async function signOpenGeniPayload(secret, body, timestampSeconds = Math.floor(Date.now() / 1e3)) {
42
- return `t=${timestampSeconds},v1=${await hmacSha256Hex(secret, `${timestampSeconds}.${body}`)}`;
43
- }
44
- async function verifyOpenGeniSignature(input) {
45
- if (!input.signature) return false;
46
- let timestamp = null;
47
- const candidates = [];
48
- for (const part of input.signature.split(",")) {
49
- const [key, value] = part.trim().split("=", 2);
50
- if (key === "t" && value && /^\d{1,12}$/.test(value)) timestamp = Number(value);
51
- if (key === "v1" && value && /^[0-9a-f]{64}$/.test(value)) candidates.push(value);
52
- }
53
- if (timestamp === null || candidates.length === 0) return false;
54
- const now = input.nowSeconds ?? Math.floor(Date.now() / 1e3);
55
- const tolerance = input.toleranceSeconds ?? OPENGENI_SIGNATURE_TOLERANCE_SECONDS;
56
- if (Math.abs(now - timestamp) > tolerance) return false;
57
- const expected = await hmacSha256Hex(input.secret, `${timestamp}.${input.body}`);
58
- return candidates.some((candidate) => constantTimeEqualHex(candidate, expected));
59
- }
1
+ import {
2
+ OPENGENI_DELIVERY_ID_HEADER,
3
+ OPENGENI_EVENT_ID_HEADER,
4
+ OPENGENI_SIGNATURE_HEADER,
5
+ OPENGENI_WEBHOOK_TEST_EVENT_TYPE,
6
+ verifyOpenGeniSignature
7
+ } from "./chunk-KGEABAID.js";
60
8
 
61
9
  // src/workspace-integrations.ts
62
10
  var OpenGeniSignatureError = class extends Error {
@@ -236,14 +184,6 @@ async function getWorkspaceInheritedIntegrations(client, workspaceId) {
236
184
  }
237
185
 
238
186
  export {
239
- WORKSPACE_WEBHOOK_EVENT_TYPES,
240
- OPENGENI_WEBHOOK_TEST_EVENT_TYPE,
241
- OPENGENI_TEST_REQUEST_NIL_ID,
242
- OPENGENI_SIGNATURE_HEADER,
243
- OPENGENI_EVENT_ID_HEADER,
244
- OPENGENI_DELIVERY_ID_HEADER,
245
- signOpenGeniPayload,
246
- verifyOpenGeniSignature,
247
187
  OpenGeniSignatureError,
248
188
  verifyWebhookEvent,
249
189
  verifyCredentialProviderRequest,
@@ -267,4 +207,4 @@ export {
267
207
  testWorkspaceCredentialProvider,
268
208
  getWorkspaceInheritedIntegrations
269
209
  };
270
- //# sourceMappingURL=chunk-RJHCBZF7.js.map
210
+ //# sourceMappingURL=chunk-VT4YM4XQ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../contracts/src/workspace-integration-wire.ts","../src/workspace-integrations.ts"],"sourcesContent":["/**\n * Dependency-free wire constants and the OpenGeni-Signature scheme shared by\n * workspace webhooks and credential providers. Kept free of zod so browser and\n * React Native bundles can verify signatures without the schema runtime.\n */\n\nexport const WORKSPACE_WEBHOOK_EVENT_TYPES = [\n \"turn.completed\",\n \"turn.failed\",\n \"turn.cancelled\",\n \"session.status.changed\",\n \"session.requiresAction\",\n \"session.humanInput.requested\",\n \"session.notification.posted\",\n \"session.notification.withdrawn\",\n \"usage.threshold_reached\",\n \"usage.exhausted\",\n \"usage.period_reset\",\n] as const;\n\n/**\n * Sent only when an administrator presses \"Send test event\". It is never a\n * subscribable type: every endpoint can receive it, and a receiver that does\n * not care acknowledges it with any 2xx.\n */\nexport const OPENGENI_WEBHOOK_TEST_EVENT_TYPE = \"webhook.test\";\n\n/**\n * The session, turn and attempt ids of a credential-provider test request\n * (`purpose: \"test\"`). A test is not a run, so no real ids exist.\n */\nexport const OPENGENI_TEST_REQUEST_NIL_ID = \"00000000-0000-0000-0000-000000000000\";\n\nexport const OPENGENI_SIGNATURE_HEADER = \"OpenGeni-Signature\";\nexport const OPENGENI_EVENT_ID_HEADER = \"OpenGeni-Event-Id\";\nexport const OPENGENI_DELIVERY_ID_HEADER = \"OpenGeni-Delivery-Id\";\nexport const OPENGENI_SIGNATURE_TOLERANCE_SECONDS = 300;\n\nconst encoder = new TextEncoder();\n\nasync function hmacSha256Hex(secret: string, message: string): Promise<string> {\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n const signature = new Uint8Array(await crypto.subtle.sign(\"HMAC\", key, encoder.encode(message)));\n return Array.from(signature, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nfunction constantTimeEqualHex(left: string, right: string): boolean {\n if (left.length !== right.length) return false;\n let difference = 0;\n for (let index = 0; index < left.length; index += 1) {\n difference |= left.charCodeAt(index) ^ right.charCodeAt(index);\n }\n return difference === 0;\n}\n\n/**\n * `OpenGeni-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, \"<t>.<body>\")>`.\n * The timestamp is signed so a captured request cannot be replayed later.\n */\nexport async function signOpenGeniPayload(\n secret: string,\n body: string,\n timestampSeconds = Math.floor(Date.now() / 1000),\n): Promise<string> {\n return `t=${timestampSeconds},v1=${await hmacSha256Hex(secret, `${timestampSeconds}.${body}`)}`;\n}\n\nexport type VerifyOpenGeniSignatureInput = {\n secret: string;\n /** The exact raw request body, before JSON parsing. */\n body: string;\n /** The `OpenGeni-Signature` header value. */\n signature: string | null | undefined;\n toleranceSeconds?: number;\n nowSeconds?: number;\n};\n\nexport async function verifyOpenGeniSignature(\n input: VerifyOpenGeniSignatureInput,\n): Promise<boolean> {\n if (!input.signature) return false;\n let timestamp: number | null = null;\n const candidates: string[] = [];\n for (const part of input.signature.split(\",\")) {\n const [key, value] = part.trim().split(\"=\", 2);\n if (key === \"t\" && value && /^\\d{1,12}$/.test(value)) timestamp = Number(value);\n if (key === \"v1\" && value && /^[0-9a-f]{64}$/.test(value)) candidates.push(value);\n }\n if (timestamp === null || candidates.length === 0) return false;\n const now = input.nowSeconds ?? Math.floor(Date.now() / 1000);\n const tolerance = input.toleranceSeconds ?? OPENGENI_SIGNATURE_TOLERANCE_SECONDS;\n if (Math.abs(now - timestamp) > tolerance) return false;\n const expected = await hmacSha256Hex(input.secret, `${timestamp}.${input.body}`);\n return candidates.some((candidate) => constantTimeEqualHex(candidate, expected));\n}\n","import {\n OPENGENI_DELIVERY_ID_HEADER,\n OPENGENI_EVENT_ID_HEADER,\n OPENGENI_SIGNATURE_HEADER,\n OPENGENI_WEBHOOK_TEST_EVENT_TYPE,\n verifyOpenGeniSignature,\n} from \"@opengeni/contracts/workspace-integration-wire\";\nimport type { CredentialProviderRequest, WorkspaceWebhookEvent } from \"@opengeni/contracts\";\nimport type { OpenGeniClient } from \"./client\";\nimport type {\n CreateOrganizationWebhookRequest,\n CreateOrganizationWebhookResponse,\n GetOrganizationCredentialProviderResponse,\n ListOrganizationWebhookDeliveriesResponse,\n ListOrganizationWebhooksResponse,\n OrganizationWebhook,\n OrganizationWebhookDelivery,\n PutOrganizationCredentialProviderRequest,\n PutOrganizationCredentialProviderResponse,\n RotateWorkspaceCredentialProviderSecretResponse,\n RotateOrganizationCredentialProviderSecretResponse,\n RotateWorkspaceWebhookSecretResponse,\n RotateOrganizationWebhookSecretResponse,\n TestWorkspaceCredentialProviderResponse,\n TestWorkspaceWebhookResponse,\n UpdateOrganizationWebhookRequest,\n WorkspaceInheritedIntegrationsResponse,\n WorkspaceWebhook,\n} from \"@opengeni/contracts\";\n\nexport type {\n CreateOrganizationWebhookRequest,\n CreateOrganizationWebhookResponse,\n CreateWorkspaceWebhookRequest,\n CreateWorkspaceWebhookResponse,\n CredentialProviderRequest,\n CredentialProviderInitiatorContext,\n CredentialProviderResponse,\n CredentialProviderMcpHeaders,\n CredentialProviderMcpMaterial,\n GetOrganizationCredentialProviderResponse,\n GetWorkspaceCredentialProviderResponse,\n InitiatingHuman,\n IntegrationEndpointTestResult,\n IntegrationWorkspaceFilter,\n ListOrganizationWebhookDeliveriesResponse,\n ListOrganizationWebhooksResponse,\n ListWorkspaceWebhookDeliveriesResponse,\n ListWorkspaceWebhooksResponse,\n PutWorkspaceCredentialProviderRequest,\n PutWorkspaceCredentialProviderResponse,\n PutOrganizationCredentialProviderRequest,\n PutOrganizationCredentialProviderResponse,\n RotateWorkspaceCredentialProviderSecretResponse,\n RotateOrganizationCredentialProviderSecretResponse,\n RotateWorkspaceWebhookSecretResponse,\n RotateOrganizationWebhookSecretResponse,\n TestWorkspaceCredentialProviderResponse,\n TestWorkspaceWebhookResponse,\n OrganizationCredentialProvider,\n OrganizationWebhook,\n OrganizationWebhookDelivery,\n UpdateOrganizationWebhookRequest,\n UpdateWorkspaceWebhookRequest,\n WorkspaceCredentialProvider,\n WorkspaceInheritedIntegrationsResponse,\n WorkspaceTestWebhookEvent,\n WorkspaceWebhook,\n WorkspaceWebhookDelivery,\n WorkspaceWebhookEvent,\n WorkspaceWebhookEventType,\n SessionWorkspaceWebhookEvent,\n WorkspaceUsageWebhookEvent,\n} from \"@opengeni/contracts\";\nexport {\n OPENGENI_DELIVERY_ID_HEADER,\n OPENGENI_EVENT_ID_HEADER,\n OPENGENI_SIGNATURE_HEADER,\n OPENGENI_TEST_REQUEST_NIL_ID,\n OPENGENI_WEBHOOK_TEST_EVENT_TYPE,\n WORKSPACE_WEBHOOK_EVENT_TYPES,\n signOpenGeniPayload,\n verifyOpenGeniSignature,\n} from \"@opengeni/contracts/workspace-integration-wire\";\n\nexport type WorkspaceSandboxImages = { images: string[]; selected: string | null };\n\nexport class OpenGeniSignatureError extends Error {\n constructor() {\n super(\"Opengeni signature verification failed\");\n this.name = \"OpenGeniSignatureError\";\n }\n}\n\ntype SignedRequest = {\n /** The exact raw request body. Parse it only after verification. */\n body: string;\n headers: Headers | Record<string, string | string[] | undefined>;\n secret: string;\n toleranceSeconds?: number;\n};\n\nfunction header(headers: SignedRequest[\"headers\"], name: string): string | null {\n if (headers instanceof Headers) return headers.get(name);\n const wanted = name.toLowerCase();\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === wanted) {\n return Array.isArray(value) ? (value[0] ?? null) : (value ?? null);\n }\n }\n return null;\n}\n\nasync function verifiedObject(input: SignedRequest): Promise<Record<string, unknown>> {\n const valid = await verifyOpenGeniSignature({\n secret: input.secret,\n body: input.body,\n signature: header(input.headers, OPENGENI_SIGNATURE_HEADER),\n ...(input.toleranceSeconds !== undefined ? { toleranceSeconds: input.toleranceSeconds } : {}),\n });\n if (!valid) throw new OpenGeniSignatureError();\n const parsed: unknown = JSON.parse(input.body);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new OpenGeniSignatureError();\n }\n return parsed as Record<string, unknown>;\n}\n\n/**\n * Verify and parse one webhook delivery. Delivery is at least once: dedupe on\n * `event.id` (also sent as the `OpenGeni-Event-Id` header). A `webhook.test`\n * event (from \"Send test event\") names no session: acknowledge it with 2xx.\n */\nexport async function verifyWebhookEvent(input: SignedRequest): Promise<{\n event: WorkspaceWebhookEvent;\n deliveryId: string | null;\n}> {\n const event = await verifiedObject(input);\n const usageEvent = typeof event.type === \"string\" && event.type.startsWith(\"usage.\");\n const lane = event.lane === undefined ? \"workspace\" : event.lane;\n if (\n typeof event.id !== \"string\" ||\n typeof event.type !== \"string\" ||\n typeof event.workspaceId !== \"string\" ||\n (lane !== \"workspace\" && lane !== \"organization\") ||\n (usageEvent && lane !== \"workspace\") ||\n !(\n typeof event.sessionId === \"string\" ||\n ((event.sessionId === null || event.sessionId === undefined) &&\n [\n \"usage.threshold_reached\",\n \"usage.exhausted\",\n \"usage.period_reset\",\n OPENGENI_WEBHOOK_TEST_EVENT_TYPE,\n ].includes(event.type))\n )\n ) {\n throw new OpenGeniSignatureError();\n }\n return {\n event: { ...event, lane } as WorkspaceWebhookEvent,\n deliveryId: header(input.headers, OPENGENI_DELIVERY_ID_HEADER),\n };\n}\n\n/**\n * Verify the exact bytes and parse a provider request, including its frozen\n * initiatorContext when sent by an upgraded worker. Provenance grants no access.\n */\nexport async function verifyCredentialProviderRequest(\n input: SignedRequest,\n): Promise<CredentialProviderRequest> {\n const parsed = await verifiedObject(input);\n if (parsed.type !== \"credentials.request\" || typeof parsed.workspaceId !== \"string\") {\n throw new OpenGeniSignatureError();\n }\n return parsed as CredentialProviderRequest;\n}\n\n/** Identity header names, for receivers that log or dedupe. */\nexport const OPENGENI_WEBHOOK_HEADERS = {\n signature: OPENGENI_SIGNATURE_HEADER,\n eventId: OPENGENI_EVENT_ID_HEADER,\n deliveryId: OPENGENI_DELIVERY_ID_HEADER,\n} as const;\n\n/** Server-side integration administration is opt-in, outside the eager browser client. */\nexport async function getOrganizationCredentialProvider(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n): Promise<GetOrganizationCredentialProviderResponse> {\n return client.requestJson(\n \"GET\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/credential-provider`,\n );\n}\n\n/** Replace configuration; explicit filter required. Store the first returned signing secret. */\nexport async function putOrganizationCredentialProvider(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n request: PutOrganizationCredentialProviderRequest,\n): Promise<PutOrganizationCredentialProviderResponse> {\n return client.requestJson(\n \"PUT\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/credential-provider`,\n request,\n );\n}\n\nexport async function deleteOrganizationCredentialProvider(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n): Promise<void> {\n await client.requestJson<void>(\n \"DELETE\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/credential-provider`,\n undefined,\n {},\n { responseType: \"void\" },\n );\n}\n\nexport async function listOrganizationWebhooks(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n): Promise<ListOrganizationWebhooksResponse> {\n return client.requestJson(\n \"GET\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks`,\n );\n}\n\n/** Create a webhook and return its signing secret once. */\nexport async function createOrganizationWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n request: CreateOrganizationWebhookRequest,\n): Promise<CreateOrganizationWebhookResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks`,\n request,\n );\n}\n\nexport async function getOrganizationWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n): Promise<OrganizationWebhook> {\n return client.requestJson(\n \"GET\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}`,\n );\n}\n\nexport async function updateOrganizationWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n request: UpdateOrganizationWebhookRequest,\n): Promise<OrganizationWebhook> {\n return client.requestJson(\n \"PATCH\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}`,\n request,\n );\n}\n\nexport async function deleteOrganizationWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n): Promise<void> {\n await client.requestJson<void>(\n \"DELETE\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}`,\n undefined,\n {},\n { responseType: \"void\" },\n );\n}\n\nexport async function listOrganizationWebhookDeliveries(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n options: { limit?: number } = {},\n): Promise<ListOrganizationWebhookDeliveriesResponse> {\n return client.requestJson(\n \"GET\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}/deliveries`,\n undefined,\n options.limit !== undefined ? { limit: String(options.limit) } : {},\n );\n}\n\n/** Requeue a settled delivery with a fresh attempt budget. */\nexport async function redeliverOrganizationWebhookDelivery(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n deliveryId: string,\n): Promise<OrganizationWebhookDelivery> {\n return client.requestJson(\n \"POST\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}/deliveries/${encodeURIComponent(deliveryId)}/redeliver`,\n );\n}\n\nexport async function getWorkspaceWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n webhookId: string,\n): Promise<WorkspaceWebhook> {\n return client.requestJson(\"GET\", `/v1/workspaces/${workspaceId}/webhooks/${webhookId}`);\n}\n\n/** Rotate immediately. Store the new secret; the old signing secret stops working. */\nexport async function rotateWorkspaceCredentialProviderSecret(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n): Promise<RotateWorkspaceCredentialProviderSecretResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/credential-provider/rotate-secret`,\n );\n}\n\nexport async function rotateOrganizationCredentialProviderSecret(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n): Promise<RotateOrganizationCredentialProviderSecretResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/credential-provider/rotate-secret`,\n );\n}\n\nexport async function rotateOrganizationWebhookSecret(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n): Promise<RotateOrganizationWebhookSecretResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}/rotate-secret`,\n );\n}\n\nexport async function rotateWorkspaceWebhookSecret(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n webhookId: string,\n): Promise<RotateWorkspaceWebhookSecretResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/webhooks/${encodeURIComponent(webhookId)}/rotate-secret`,\n );\n}\n\n/**\n * Send one signed `webhook.test` event to a workspace webhook now and return\n * what the endpoint answered. Nothing is queued or retried.\n */\nexport async function testWorkspaceWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n webhookId: string,\n): Promise<TestWorkspaceWebhookResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/webhooks/${encodeURIComponent(webhookId)}/test`,\n );\n}\n\n/**\n * Send one signed `purpose: \"test\"` request to the credential provider this\n * workspace's runs use (its own, else the organization's). Only the names of\n * returned credentials come back, never their values.\n */\nexport async function testWorkspaceCredentialProvider(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n): Promise<TestWorkspaceCredentialProviderResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/credential-provider/test`,\n );\n}\n\n/** Organization registrations that reach this workspace. Workspace administrators only. */\nexport async function getWorkspaceInheritedIntegrations(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n): Promise<WorkspaceInheritedIntegrationsResponse> {\n return client.requestJson(\n \"GET\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/inherited-integrations`,\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/workspace-integrations.ts"],"sourcesContent":["import {\n OPENGENI_DELIVERY_ID_HEADER,\n OPENGENI_EVENT_ID_HEADER,\n OPENGENI_SIGNATURE_HEADER,\n OPENGENI_WEBHOOK_TEST_EVENT_TYPE,\n verifyOpenGeniSignature,\n} from \"@opengeni/contracts/workspace-integration-wire\";\nimport type { CredentialProviderRequest, WorkspaceWebhookEvent } from \"@opengeni/contracts\";\nimport type { OpenGeniClient } from \"./client\";\nimport type {\n CreateOrganizationWebhookRequest,\n CreateOrganizationWebhookResponse,\n GetOrganizationCredentialProviderResponse,\n ListOrganizationWebhookDeliveriesResponse,\n ListOrganizationWebhooksResponse,\n OrganizationWebhook,\n OrganizationWebhookDelivery,\n PutOrganizationCredentialProviderRequest,\n PutOrganizationCredentialProviderResponse,\n RotateWorkspaceCredentialProviderSecretResponse,\n RotateOrganizationCredentialProviderSecretResponse,\n RotateWorkspaceWebhookSecretResponse,\n RotateOrganizationWebhookSecretResponse,\n TestWorkspaceCredentialProviderResponse,\n TestWorkspaceWebhookResponse,\n UpdateOrganizationWebhookRequest,\n WorkspaceInheritedIntegrationsResponse,\n WorkspaceWebhook,\n} from \"@opengeni/contracts\";\n\nexport type {\n CreateOrganizationWebhookRequest,\n CreateOrganizationWebhookResponse,\n CreateWorkspaceWebhookRequest,\n CreateWorkspaceWebhookResponse,\n CredentialProviderRequest,\n CredentialProviderInitiatorContext,\n CredentialProviderResponse,\n CredentialProviderMcpHeaders,\n CredentialProviderMcpMaterial,\n GetOrganizationCredentialProviderResponse,\n GetWorkspaceCredentialProviderResponse,\n InitiatingHuman,\n IntegrationEndpointTestResult,\n IntegrationWorkspaceFilter,\n ListOrganizationWebhookDeliveriesResponse,\n ListOrganizationWebhooksResponse,\n ListWorkspaceWebhookDeliveriesResponse,\n ListWorkspaceWebhooksResponse,\n PutWorkspaceCredentialProviderRequest,\n PutWorkspaceCredentialProviderResponse,\n PutOrganizationCredentialProviderRequest,\n PutOrganizationCredentialProviderResponse,\n RotateWorkspaceCredentialProviderSecretResponse,\n RotateOrganizationCredentialProviderSecretResponse,\n RotateWorkspaceWebhookSecretResponse,\n RotateOrganizationWebhookSecretResponse,\n TestWorkspaceCredentialProviderResponse,\n TestWorkspaceWebhookResponse,\n OrganizationCredentialProvider,\n OrganizationWebhook,\n OrganizationWebhookDelivery,\n UpdateOrganizationWebhookRequest,\n UpdateWorkspaceWebhookRequest,\n WorkspaceCredentialProvider,\n WorkspaceInheritedIntegrationsResponse,\n WorkspaceTestWebhookEvent,\n WorkspaceWebhook,\n WorkspaceWebhookDelivery,\n WorkspaceWebhookEvent,\n WorkspaceWebhookEventType,\n SessionWorkspaceWebhookEvent,\n WorkspaceUsageWebhookEvent,\n} from \"@opengeni/contracts\";\nexport {\n OPENGENI_DELIVERY_ID_HEADER,\n OPENGENI_EVENT_ID_HEADER,\n OPENGENI_SIGNATURE_HEADER,\n OPENGENI_TEST_REQUEST_NIL_ID,\n OPENGENI_WEBHOOK_TEST_EVENT_TYPE,\n WORKSPACE_WEBHOOK_EVENT_TYPES,\n signOpenGeniPayload,\n verifyOpenGeniSignature,\n} from \"@opengeni/contracts/workspace-integration-wire\";\n\nexport type WorkspaceSandboxImages = { images: string[]; selected: string | null };\n\nexport class OpenGeniSignatureError extends Error {\n constructor() {\n super(\"Opengeni signature verification failed\");\n this.name = \"OpenGeniSignatureError\";\n }\n}\n\ntype SignedRequest = {\n /** The exact raw request body. Parse it only after verification. */\n body: string;\n headers: Headers | Record<string, string | string[] | undefined>;\n secret: string;\n toleranceSeconds?: number;\n};\n\nfunction header(headers: SignedRequest[\"headers\"], name: string): string | null {\n if (headers instanceof Headers) return headers.get(name);\n const wanted = name.toLowerCase();\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === wanted) {\n return Array.isArray(value) ? (value[0] ?? null) : (value ?? null);\n }\n }\n return null;\n}\n\nasync function verifiedObject(input: SignedRequest): Promise<Record<string, unknown>> {\n const valid = await verifyOpenGeniSignature({\n secret: input.secret,\n body: input.body,\n signature: header(input.headers, OPENGENI_SIGNATURE_HEADER),\n ...(input.toleranceSeconds !== undefined ? { toleranceSeconds: input.toleranceSeconds } : {}),\n });\n if (!valid) throw new OpenGeniSignatureError();\n const parsed: unknown = JSON.parse(input.body);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new OpenGeniSignatureError();\n }\n return parsed as Record<string, unknown>;\n}\n\n/**\n * Verify and parse one webhook delivery. Delivery is at least once: dedupe on\n * `event.id` (also sent as the `OpenGeni-Event-Id` header). A `webhook.test`\n * event (from \"Send test event\") names no session: acknowledge it with 2xx.\n */\nexport async function verifyWebhookEvent(input: SignedRequest): Promise<{\n event: WorkspaceWebhookEvent;\n deliveryId: string | null;\n}> {\n const event = await verifiedObject(input);\n const usageEvent = typeof event.type === \"string\" && event.type.startsWith(\"usage.\");\n const lane = event.lane === undefined ? \"workspace\" : event.lane;\n if (\n typeof event.id !== \"string\" ||\n typeof event.type !== \"string\" ||\n typeof event.workspaceId !== \"string\" ||\n (lane !== \"workspace\" && lane !== \"organization\") ||\n (usageEvent && lane !== \"workspace\") ||\n !(\n typeof event.sessionId === \"string\" ||\n ((event.sessionId === null || event.sessionId === undefined) &&\n [\n \"usage.threshold_reached\",\n \"usage.exhausted\",\n \"usage.period_reset\",\n OPENGENI_WEBHOOK_TEST_EVENT_TYPE,\n ].includes(event.type))\n )\n ) {\n throw new OpenGeniSignatureError();\n }\n return {\n event: { ...event, lane } as WorkspaceWebhookEvent,\n deliveryId: header(input.headers, OPENGENI_DELIVERY_ID_HEADER),\n };\n}\n\n/**\n * Verify the exact bytes and parse a provider request, including its frozen\n * initiatorContext when sent by an upgraded worker. Provenance grants no access.\n */\nexport async function verifyCredentialProviderRequest(\n input: SignedRequest,\n): Promise<CredentialProviderRequest> {\n const parsed = await verifiedObject(input);\n if (parsed.type !== \"credentials.request\" || typeof parsed.workspaceId !== \"string\") {\n throw new OpenGeniSignatureError();\n }\n return parsed as CredentialProviderRequest;\n}\n\n/** Identity header names, for receivers that log or dedupe. */\nexport const OPENGENI_WEBHOOK_HEADERS = {\n signature: OPENGENI_SIGNATURE_HEADER,\n eventId: OPENGENI_EVENT_ID_HEADER,\n deliveryId: OPENGENI_DELIVERY_ID_HEADER,\n} as const;\n\n/** Server-side integration administration is opt-in, outside the eager browser client. */\nexport async function getOrganizationCredentialProvider(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n): Promise<GetOrganizationCredentialProviderResponse> {\n return client.requestJson(\n \"GET\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/credential-provider`,\n );\n}\n\n/** Replace configuration; explicit filter required. Store the first returned signing secret. */\nexport async function putOrganizationCredentialProvider(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n request: PutOrganizationCredentialProviderRequest,\n): Promise<PutOrganizationCredentialProviderResponse> {\n return client.requestJson(\n \"PUT\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/credential-provider`,\n request,\n );\n}\n\nexport async function deleteOrganizationCredentialProvider(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n): Promise<void> {\n await client.requestJson<void>(\n \"DELETE\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/credential-provider`,\n undefined,\n {},\n { responseType: \"void\" },\n );\n}\n\nexport async function listOrganizationWebhooks(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n): Promise<ListOrganizationWebhooksResponse> {\n return client.requestJson(\n \"GET\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks`,\n );\n}\n\n/** Create a webhook and return its signing secret once. */\nexport async function createOrganizationWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n request: CreateOrganizationWebhookRequest,\n): Promise<CreateOrganizationWebhookResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks`,\n request,\n );\n}\n\nexport async function getOrganizationWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n): Promise<OrganizationWebhook> {\n return client.requestJson(\n \"GET\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}`,\n );\n}\n\nexport async function updateOrganizationWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n request: UpdateOrganizationWebhookRequest,\n): Promise<OrganizationWebhook> {\n return client.requestJson(\n \"PATCH\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}`,\n request,\n );\n}\n\nexport async function deleteOrganizationWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n): Promise<void> {\n await client.requestJson<void>(\n \"DELETE\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}`,\n undefined,\n {},\n { responseType: \"void\" },\n );\n}\n\nexport async function listOrganizationWebhookDeliveries(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n options: { limit?: number } = {},\n): Promise<ListOrganizationWebhookDeliveriesResponse> {\n return client.requestJson(\n \"GET\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}/deliveries`,\n undefined,\n options.limit !== undefined ? { limit: String(options.limit) } : {},\n );\n}\n\n/** Requeue a settled delivery with a fresh attempt budget. */\nexport async function redeliverOrganizationWebhookDelivery(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n deliveryId: string,\n): Promise<OrganizationWebhookDelivery> {\n return client.requestJson(\n \"POST\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}/deliveries/${encodeURIComponent(deliveryId)}/redeliver`,\n );\n}\n\nexport async function getWorkspaceWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n webhookId: string,\n): Promise<WorkspaceWebhook> {\n return client.requestJson(\"GET\", `/v1/workspaces/${workspaceId}/webhooks/${webhookId}`);\n}\n\n/** Rotate immediately. Store the new secret; the old signing secret stops working. */\nexport async function rotateWorkspaceCredentialProviderSecret(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n): Promise<RotateWorkspaceCredentialProviderSecretResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/credential-provider/rotate-secret`,\n );\n}\n\nexport async function rotateOrganizationCredentialProviderSecret(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n): Promise<RotateOrganizationCredentialProviderSecretResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/credential-provider/rotate-secret`,\n );\n}\n\nexport async function rotateOrganizationWebhookSecret(\n client: Pick<OpenGeniClient, \"requestJson\">,\n organizationId: string,\n webhookId: string,\n): Promise<RotateOrganizationWebhookSecretResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/organizations/${encodeURIComponent(organizationId)}/webhooks/${encodeURIComponent(webhookId)}/rotate-secret`,\n );\n}\n\nexport async function rotateWorkspaceWebhookSecret(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n webhookId: string,\n): Promise<RotateWorkspaceWebhookSecretResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/webhooks/${encodeURIComponent(webhookId)}/rotate-secret`,\n );\n}\n\n/**\n * Send one signed `webhook.test` event to a workspace webhook now and return\n * what the endpoint answered. Nothing is queued or retried.\n */\nexport async function testWorkspaceWebhook(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n webhookId: string,\n): Promise<TestWorkspaceWebhookResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/webhooks/${encodeURIComponent(webhookId)}/test`,\n );\n}\n\n/**\n * Send one signed `purpose: \"test\"` request to the credential provider this\n * workspace's runs use (its own, else the organization's). Only the names of\n * returned credentials come back, never their values.\n */\nexport async function testWorkspaceCredentialProvider(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n): Promise<TestWorkspaceCredentialProviderResponse> {\n return client.requestJson(\n \"POST\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/credential-provider/test`,\n );\n}\n\n/** Organization registrations that reach this workspace. Workspace administrators only. */\nexport async function getWorkspaceInheritedIntegrations(\n client: Pick<OpenGeniClient, \"requestJson\">,\n workspaceId: string,\n): Promise<WorkspaceInheritedIntegrationsResponse> {\n return client.requestJson(\n \"GET\",\n `/v1/workspaces/${encodeURIComponent(workspaceId)}/inherited-integrations`,\n );\n}\n"],"mappings":"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","names":[]}
package/dist/core.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  OpenGeniDocumentAuthorityClient
3
- } from "./chunk-YDVPI7WT.js";
3
+ } from "./chunk-JP62FZSI.js";
4
4
  import {
5
5
  resolveWorkspaceVoiceInputEnabled
6
6
  } from "./chunk-GZQSWAKD.js";
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-P7UWKORG.js";
12
12
  import {
13
13
  parseDeprecationNotice
14
- } from "./chunk-NEM5N6C6.js";
14
+ } from "./chunk-JKG75TTU.js";
15
15
  import "./chunk-VPVMLM7Q.js";
16
16
  import "./chunk-4AHR4KGA.js";
17
17
  import {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  OpenGeniDocumentAuthorityClient
3
- } from "./chunk-YDVPI7WT.js";
4
- import "./chunk-NEM5N6C6.js";
3
+ } from "./chunk-JP62FZSI.js";
4
+ import "./chunk-JKG75TTU.js";
5
5
  import "./chunk-VPVMLM7Q.js";
6
6
  import "./chunk-4AHR4KGA.js";
7
7
  import "./chunk-KADZ5PGG.js";
@@ -0,0 +1,203 @@
1
+ import { VaultProviderWireFreshness, VaultProviderWireRequest, type VaultProviderWireAuthority, type VaultProviderWireErrorCode, type VaultProviderWireOperationName, type VaultProviderWirePage, type VaultProviderWireProvider, type VaultProviderWireResult, type VaultProviderWireWriteItem } from "@opengeni/contracts/vault-provider-wire";
2
+ export { VAULT_PROVIDER_WIRE_ERROR_CODES, VAULT_PROVIDER_WIRE_LIMITS, VAULT_PROVIDER_WIRE_RESPONSE_SIGNATURE_HEADER, VAULT_PROVIDER_WIRE_VERSION, vaultProviderWireResponseKey, } from "@opengeni/contracts/vault-provider-wire";
3
+ export type { VaultProviderWireAuthority, VaultProviderWireDescribeResult, VaultProviderWireErrorCode, VaultProviderWireFieldMeta, VaultProviderWireFieldValue, VaultProviderWireFreshness, VaultProviderWireItemMeta, VaultProviderWireOperation, VaultProviderWireOperationName, VaultProviderWirePage, VaultProviderWireProvider, VaultProviderWireRequest, VaultProviderWireResponse, VaultProviderWireResult, VaultProviderWireVault, VaultProviderWireWriteField, VaultProviderWireWriteItem, } from "@opengeni/contracts/vault-provider-wire";
4
+ /** A definite, safe receiver failure. Its message is never sent to Opengeni. */
5
+ export declare class ExternalVaultReceiverError extends Error {
6
+ readonly code: VaultProviderWireErrorCode;
7
+ readonly retryAfterMs: number | null;
8
+ readonly freshness: VaultProviderWireFreshness | null;
9
+ constructor(code: VaultProviderWireErrorCode, options?: {
10
+ retryAfterMs?: number;
11
+ freshness?: VaultProviderWireFreshness;
12
+ message?: string;
13
+ });
14
+ }
15
+ export interface ExternalVaultReceiverConnection<TConnection> {
16
+ provider: VaultProviderWireProvider;
17
+ /**
18
+ * Accepted signing secrets: the current one first, then a previous one
19
+ * during rotation. Responses are signed with the secret that verified.
20
+ */
21
+ signingSecrets: readonly string[];
22
+ /** When set, requests for any other Opengeni account are refused. */
23
+ accountId?: string;
24
+ /** When set, requests for a connection owned by another workspace are refused. */
25
+ connectionWorkspaceId?: string;
26
+ /** Host data for this connection: its fixed inventory scope, not a user. */
27
+ context: TConnection;
28
+ }
29
+ export type ExternalVaultMutationClaim = {
30
+ state: "claimed";
31
+ } | {
32
+ state: "completed";
33
+ result: unknown;
34
+ }
35
+ /** In flight, or uncertain after a failure: report an unknown outcome. */
36
+ | {
37
+ state: "pending";
38
+ }
39
+ /** Same key, different operation or caller. */
40
+ | {
41
+ state: "mismatch";
42
+ };
43
+ /**
44
+ * Caller-owned replay and idempotency storage. Use durable shared storage
45
+ * (for example a database table with unique keys) when the receiver runs in
46
+ * more than one process or must survive restarts.
47
+ */
48
+ export interface ExternalVaultReceiverStore {
49
+ /** Atomically record a request id. False when it was already recorded. */
50
+ rememberRequest(input: {
51
+ connectionId: string;
52
+ requestId: string;
53
+ expiresAt: Date;
54
+ }): Promise<boolean>;
55
+ /** Atomically claim a mutation key, or report its existing state. */
56
+ claimMutation(input: {
57
+ connectionId: string;
58
+ idempotencyKey: string;
59
+ digest: string;
60
+ expiresAt: Date;
61
+ }): Promise<ExternalVaultMutationClaim>;
62
+ /** Record the metadata-only result of a confirmed mutation. */
63
+ completeMutation(input: {
64
+ connectionId: string;
65
+ idempotencyKey: string;
66
+ digest: string;
67
+ result: unknown;
68
+ }): Promise<void>;
69
+ /** The handler definitely changed nothing: allow the key to be claimed again. */
70
+ releaseMutation(input: {
71
+ connectionId: string;
72
+ idempotencyKey: string;
73
+ digest: string;
74
+ }): Promise<void>;
75
+ }
76
+ export interface ExternalVaultHandlerOutput<R> {
77
+ result: R;
78
+ freshness?: VaultProviderWireFreshness | null;
79
+ }
80
+ type ReadContext = {
81
+ forceRefresh: boolean;
82
+ cacheEpoch: string | null;
83
+ };
84
+ export interface ExternalVaultCallContext<TConnection, TPrincipal> {
85
+ connectionId: string;
86
+ connection: TConnection;
87
+ /** The host principal returned by `authorize` for this exact request. */
88
+ principal: TPrincipal;
89
+ authority: VaultProviderWireAuthority;
90
+ requestId: string;
91
+ signal?: AbortSignal;
92
+ }
93
+ /**
94
+ * Inventory handlers receive the connection, not the acting principal: one
95
+ * connection has one fixed inventory, so listings must not vary by subject.
96
+ */
97
+ export interface ExternalVaultInventoryContext<TConnection> {
98
+ connectionId: string;
99
+ connection: TConnection;
100
+ requestId: string;
101
+ signal?: AbortSignal;
102
+ }
103
+ export interface ExternalVaultReceiverHandlers<TConnection, TPrincipal> {
104
+ describe(ctx: ExternalVaultInventoryContext<TConnection>): Promise<ExternalVaultHandlerOutput<VaultProviderWireResult<"describe">>>;
105
+ /** Deliberate upstream refresh; omit when the store is always live. */
106
+ refresh?(ctx: ExternalVaultInventoryContext<TConnection>): Promise<ExternalVaultHandlerOutput<VaultProviderWireResult<"refresh">>>;
107
+ listVaults(ctx: ExternalVaultInventoryContext<TConnection>, input: {
108
+ page: VaultProviderWirePage;
109
+ } & ReadContext): Promise<ExternalVaultHandlerOutput<VaultProviderWireResult<"list_vaults">>>;
110
+ listItems(ctx: ExternalVaultInventoryContext<TConnection>, input: {
111
+ externalVaultId: string;
112
+ page: VaultProviderWirePage;
113
+ } & ReadContext): Promise<ExternalVaultHandlerOutput<VaultProviderWireResult<"list_items">>>;
114
+ readFields(ctx: ExternalVaultCallContext<TConnection, TPrincipal>, input: {
115
+ externalVaultId: string;
116
+ externalItemId: string;
117
+ externalFieldIds: readonly string[];
118
+ } & ReadContext): Promise<ExternalVaultHandlerOutput<VaultProviderWireResult<"read_fields">>>;
119
+ /** Omit when the connection is read-only. Throw only definite failures. */
120
+ writeItem?(ctx: ExternalVaultCallContext<TConnection, TPrincipal>, input: {
121
+ externalVaultId: string;
122
+ item: VaultProviderWireWriteItem;
123
+ idempotencyKey: string;
124
+ }): Promise<ExternalVaultHandlerOutput<VaultProviderWireResult<"write_item">>>;
125
+ archiveItem?(ctx: ExternalVaultCallContext<TConnection, TPrincipal>, input: {
126
+ externalVaultId: string;
127
+ externalItemId: string;
128
+ idempotencyKey: string;
129
+ }): Promise<ExternalVaultHandlerOutput<VaultProviderWireResult<"archive_item">>>;
130
+ }
131
+ export interface ExternalVaultAuthorizeInput<TConnection> {
132
+ connectionId: string;
133
+ connection: TConnection;
134
+ authority: VaultProviderWireAuthority;
135
+ operation: {
136
+ op: VaultProviderWireOperationName;
137
+ externalVaultId?: string;
138
+ externalItemId?: string;
139
+ };
140
+ requestId: string;
141
+ }
142
+ export interface ExternalVaultReceiverOptions<TConnection, TPrincipal> {
143
+ /** Unknown connections are indistinguishable from bad signatures. */
144
+ resolveConnection(connectionId: string): Promise<ExternalVaultReceiverConnection<TConnection> | null>;
145
+ /**
146
+ * Map Opengeni's native account/workspace/subject to the host tenant and
147
+ * user and recheck access for this operation. Return null to refuse.
148
+ * Called for every request, including inventory reads.
149
+ */
150
+ authorize(input: ExternalVaultAuthorizeInput<TConnection>): Promise<TPrincipal | null>;
151
+ handlers: ExternalVaultReceiverHandlers<TConnection, TPrincipal>;
152
+ store: ExternalVaultReceiverStore;
153
+ /** How long mutation results stay replayable. Default 24 hours. */
154
+ mutationRetentionMs?: number;
155
+ now?: () => number;
156
+ /** Host diagnostics. Never forward these errors to Opengeni. */
157
+ onError?(event: {
158
+ stage: "authorize" | "handler" | "store" | "output";
159
+ op: VaultProviderWireOperationName;
160
+ connectionId: string;
161
+ error: unknown;
162
+ }): void;
163
+ }
164
+ export interface ExternalVaultReceiverHttpRequest {
165
+ /** The exact raw request body; parse nothing before calling `handle`. */
166
+ body: string;
167
+ headers: Headers | Record<string, string | string[] | undefined>;
168
+ signal?: AbortSignal;
169
+ }
170
+ export interface ExternalVaultReceiverHttpResponse {
171
+ status: number;
172
+ headers: Record<string, string>;
173
+ body: string;
174
+ }
175
+ export interface ExternalVaultReceiver {
176
+ handle(request: ExternalVaultReceiverHttpRequest): Promise<ExternalVaultReceiverHttpResponse>;
177
+ /** Fetch-style adapter: POST only, bounded body, then `handle`. */
178
+ fetch(request: Request): Promise<Response>;
179
+ }
180
+ /**
181
+ * Keyed digest of one mutation's exact scope: connection, provider, trusted
182
+ * caller tuple and operation (without its idempotency key). Keyed so the
183
+ * store never holds a plain hash of submitted secret values.
184
+ */
185
+ export declare function externalVaultMutationDigest(input: {
186
+ signingSecret: string;
187
+ request: VaultProviderWireRequest;
188
+ }): Promise<string>;
189
+ /** Mirrors Opengeni's secret-name rule: usable item/field names from upstream titles. */
190
+ export declare function safeExternalVaultName(raw: string, fallback?: string): string;
191
+ /** A safe field name, unique case-insensitively within `taken` (which it updates). */
192
+ export declare function uniqueExternalVaultFieldName(raw: string, taken: Set<string>, fallback?: string): string;
193
+ /**
194
+ * Process-local store for tests, development and a single-process bridge
195
+ * that accepts losing replay/idempotency memory on restart. It is not durable.
196
+ */
197
+ export declare function createInMemoryExternalVaultReceiverStore(options?: {
198
+ maxEntries?: number;
199
+ now?: () => number;
200
+ }): ExternalVaultReceiverStore & {
201
+ size(): number;
202
+ };
203
+ export declare function createExternalVaultReceiver<TConnection, TPrincipal>(options: ExternalVaultReceiverOptions<TConnection, TPrincipal>): ExternalVaultReceiver;