@capxul/sdk 0.2.0-alpha.3 → 0.2.0-alpha.5

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 (45) hide show
  1. package/README.md +4 -266
  2. package/dist/InMemoryAuthCacheAdapter-BK-B_ERB.mjs +113 -0
  3. package/dist/InMemoryAuthCacheAdapter-BK-B_ERB.mjs.map +1 -0
  4. package/dist/index.d.mts +1263 -0
  5. package/dist/index.d.mts.map +1 -0
  6. package/dist/index.mjs +4740 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/dist/node/index.d.mts +55 -0
  9. package/dist/node/index.d.mts.map +1 -0
  10. package/dist/node/index.mjs +159 -0
  11. package/dist/node/index.mjs.map +1 -0
  12. package/dist/ports/safe-deployment.d.mts +2 -0
  13. package/dist/ports/safe-deployment.mjs +38 -0
  14. package/dist/ports/safe-deployment.mjs.map +1 -0
  15. package/dist/safe-deployment-Vni46k3t.d.mts +137 -0
  16. package/dist/safe-deployment-Vni46k3t.d.mts.map +1 -0
  17. package/dist/signer-oaYGfjDe.d.mts +142 -0
  18. package/dist/signer-oaYGfjDe.d.mts.map +1 -0
  19. package/package.json +37 -71
  20. package/CHANGELOG.md +0 -256
  21. package/LICENSE +0 -44
  22. package/dist/client-B_Z3ThFO.d.cts +0 -1484
  23. package/dist/client-pMBRFcsz.d.ts +0 -1484
  24. package/dist/client.cjs +0 -4324
  25. package/dist/client.d.cts +0 -6
  26. package/dist/client.d.ts +0 -6
  27. package/dist/client.js +0 -4322
  28. package/dist/errors-CwhCWGxm.d.ts +0 -70
  29. package/dist/errors-rqxuUhQP.d.cts +0 -70
  30. package/dist/errors.cjs +0 -35
  31. package/dist/errors.d.cts +0 -2
  32. package/dist/errors.d.ts +0 -2
  33. package/dist/errors.js +0 -31
  34. package/dist/index.cjs +0 -4626
  35. package/dist/index.d.cts +0 -571
  36. package/dist/index.d.ts +0 -571
  37. package/dist/index.js +0 -4585
  38. package/dist/next-action-CTGl8wpy.d.cts +0 -177
  39. package/dist/next-action-CTGl8wpy.d.ts +0 -177
  40. package/dist/types-Brucpq0Z.d.cts +0 -1191
  41. package/dist/types-V_D7qjxY.d.ts +0 -1191
  42. package/dist/webhooks.cjs +0 -118
  43. package/dist/webhooks.d.cts +0 -33
  44. package/dist/webhooks.d.ts +0 -33
  45. package/dist/webhooks.js +0 -116
package/dist/webhooks.cjs DELETED
@@ -1,118 +0,0 @@
1
- 'use strict';
2
-
3
- // src/errors.ts
4
- var CapxulError = class extends Error {
5
- code;
6
- details;
7
- operationId;
8
- correlationId;
9
- retryable;
10
- constructor(init) {
11
- super(
12
- init.message,
13
- init.cause !== void 0 ? { cause: init.cause } : void 0
14
- );
15
- this.name = "CapxulError";
16
- this.code = init.code;
17
- this.details = init.details;
18
- this.operationId = init.operationId;
19
- this.correlationId = init.correlationId;
20
- this.retryable = init.retryable;
21
- }
22
- };
23
-
24
- // ../config/src/timing.ts
25
- var WEBHOOK_FRESHNESS_WINDOW_MS = 5 * 60 * 1e3;
26
-
27
- // ../config/src/org-roles.ts
28
- function roleKeyFromLabel(label) {
29
- const bytes = new TextEncoder().encode(label);
30
- const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
31
- return "0x" + hex.padEnd(64, "0");
32
- }
33
- roleKeyFromLabel("OWNER");
34
- roleKeyFromLabel("FINANCE_MANAGER");
35
- roleKeyFromLabel("PAYMENTS_OPERATOR");
36
-
37
- // src/webhooks.ts
38
- async function verifyWebhook(request, secret, options) {
39
- if (!secret) {
40
- throw new CapxulError({
41
- code: "INVALID_INPUT",
42
- message: "A webhook signing secret is required."
43
- });
44
- }
45
- const timestamp = request.headers.get("x-capxul-timestamp");
46
- const signature = request.headers.get("x-capxul-signature");
47
- if (!timestamp || !signature) {
48
- return { valid: false, reason: "invalid_signature" };
49
- }
50
- const timestampMs = Number(timestamp);
51
- if (!Number.isFinite(timestampMs)) {
52
- return { valid: false, reason: "malformed" };
53
- }
54
- const freshnessWindowMs = options?.freshnessWindowMs ?? WEBHOOK_FRESHNESS_WINDOW_MS;
55
- if (Math.abs(Date.now() - timestampMs) > freshnessWindowMs) {
56
- return { valid: false, reason: "replay" };
57
- }
58
- const body = await request.text();
59
- const signatureHex = signature.startsWith("sha256=") ? signature.slice("sha256=".length) : signature;
60
- if (!/^[a-f0-9]{64}$/i.test(signatureHex)) {
61
- return { valid: false, reason: "invalid_signature" };
62
- }
63
- const validSignature = await verifyHmacSha256(
64
- secret,
65
- `${timestamp}.${body}`,
66
- signatureHex
67
- );
68
- if (!validSignature) {
69
- return { valid: false, reason: "invalid_signature" };
70
- }
71
- const parsed = parseWebhookEvent(body);
72
- if (!parsed) {
73
- return { valid: false, reason: "malformed" };
74
- }
75
- return { valid: true, event: parsed };
76
- }
77
- async function verifyHmacSha256(secret, message, signatureHex) {
78
- const encoder = new TextEncoder();
79
- const key = await crypto.subtle.importKey(
80
- "raw",
81
- encoder.encode(secret),
82
- { name: "HMAC", hash: "SHA-256" },
83
- false,
84
- ["verify"]
85
- );
86
- return await crypto.subtle.verify(
87
- "HMAC",
88
- key,
89
- hexToArrayBuffer(signatureHex),
90
- encoder.encode(message)
91
- );
92
- }
93
- function hexToArrayBuffer(hex) {
94
- const buffer = new ArrayBuffer(hex.length / 2);
95
- const bytes = new Uint8Array(buffer);
96
- for (let i = 0; i < bytes.length; i++) {
97
- bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
98
- }
99
- return buffer;
100
- }
101
- function parseWebhookEvent(body) {
102
- try {
103
- const parsed = JSON.parse(body);
104
- if (!isWebhookEvent(parsed)) return null;
105
- return parsed;
106
- } catch {
107
- return null;
108
- }
109
- }
110
- function isWebhookEvent(value) {
111
- if (!value || typeof value !== "object" || Array.isArray(value)) {
112
- return false;
113
- }
114
- const candidate = value;
115
- return typeof candidate.id === "string" && typeof candidate.type === "string" && typeof candidate.createdAt === "string" && (candidate.operationId === void 0 || typeof candidate.operationId === "string") && (candidate.correlationId === void 0 || typeof candidate.correlationId === "string") && !!candidate.data && typeof candidate.data === "object" && !Array.isArray(candidate.data);
116
- }
117
-
118
- exports.verifyWebhook = verifyWebhook;
@@ -1,33 +0,0 @@
1
- import { a2 as WebhookEvent } from './types-Brucpq0Z.cjs';
2
- import './next-action-CTGl8wpy.cjs';
3
-
4
- /**
5
- * Webhook verification primitive per CANON.md §4.41 +
6
- * `.claude/rules/webhook-security.md`.
7
- *
8
- * Verifies HMAC-SHA256 over the raw request body using
9
- * `crypto.subtle.verify` (timing-safe by default), checks freshness
10
- * against a configurable window, and returns a tagged-union result.
11
- *
12
- * Framework adapters (`@capxul/sdk-next`, future `@capxul/sdk-hono`)
13
- * wrap this primitive with HTTP handler glue. This file is the one
14
- * canonical crypto entry point.
15
- */
16
- type WebhookVerificationResult = {
17
- readonly valid: true;
18
- readonly event: WebhookEvent;
19
- } | {
20
- readonly valid: false;
21
- readonly reason: "invalid_signature" | "replay" | "malformed";
22
- };
23
- type WebhookVerificationOptions = {
24
- /**
25
- * Maximum age of a payload (based on `createdAt`) before it is
26
- * rejected as a replay. Defaults to 5 minutes
27
- * (`WEBHOOK_FRESHNESS_WINDOW_MS` in `@repo/config`).
28
- */
29
- readonly freshnessWindowMs?: number;
30
- };
31
- declare function verifyWebhook(request: Request, secret: string, options?: WebhookVerificationOptions): Promise<WebhookVerificationResult>;
32
-
33
- export { type WebhookVerificationOptions, type WebhookVerificationResult, verifyWebhook };
@@ -1,33 +0,0 @@
1
- import { a2 as WebhookEvent } from './types-V_D7qjxY.js';
2
- import './next-action-CTGl8wpy.js';
3
-
4
- /**
5
- * Webhook verification primitive per CANON.md §4.41 +
6
- * `.claude/rules/webhook-security.md`.
7
- *
8
- * Verifies HMAC-SHA256 over the raw request body using
9
- * `crypto.subtle.verify` (timing-safe by default), checks freshness
10
- * against a configurable window, and returns a tagged-union result.
11
- *
12
- * Framework adapters (`@capxul/sdk-next`, future `@capxul/sdk-hono`)
13
- * wrap this primitive with HTTP handler glue. This file is the one
14
- * canonical crypto entry point.
15
- */
16
- type WebhookVerificationResult = {
17
- readonly valid: true;
18
- readonly event: WebhookEvent;
19
- } | {
20
- readonly valid: false;
21
- readonly reason: "invalid_signature" | "replay" | "malformed";
22
- };
23
- type WebhookVerificationOptions = {
24
- /**
25
- * Maximum age of a payload (based on `createdAt`) before it is
26
- * rejected as a replay. Defaults to 5 minutes
27
- * (`WEBHOOK_FRESHNESS_WINDOW_MS` in `@repo/config`).
28
- */
29
- readonly freshnessWindowMs?: number;
30
- };
31
- declare function verifyWebhook(request: Request, secret: string, options?: WebhookVerificationOptions): Promise<WebhookVerificationResult>;
32
-
33
- export { type WebhookVerificationOptions, type WebhookVerificationResult, verifyWebhook };
package/dist/webhooks.js DELETED
@@ -1,116 +0,0 @@
1
- // src/errors.ts
2
- var CapxulError = class extends Error {
3
- code;
4
- details;
5
- operationId;
6
- correlationId;
7
- retryable;
8
- constructor(init) {
9
- super(
10
- init.message,
11
- init.cause !== void 0 ? { cause: init.cause } : void 0
12
- );
13
- this.name = "CapxulError";
14
- this.code = init.code;
15
- this.details = init.details;
16
- this.operationId = init.operationId;
17
- this.correlationId = init.correlationId;
18
- this.retryable = init.retryable;
19
- }
20
- };
21
-
22
- // ../config/src/timing.ts
23
- var WEBHOOK_FRESHNESS_WINDOW_MS = 5 * 60 * 1e3;
24
-
25
- // ../config/src/org-roles.ts
26
- function roleKeyFromLabel(label) {
27
- const bytes = new TextEncoder().encode(label);
28
- const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
29
- return "0x" + hex.padEnd(64, "0");
30
- }
31
- roleKeyFromLabel("OWNER");
32
- roleKeyFromLabel("FINANCE_MANAGER");
33
- roleKeyFromLabel("PAYMENTS_OPERATOR");
34
-
35
- // src/webhooks.ts
36
- async function verifyWebhook(request, secret, options) {
37
- if (!secret) {
38
- throw new CapxulError({
39
- code: "INVALID_INPUT",
40
- message: "A webhook signing secret is required."
41
- });
42
- }
43
- const timestamp = request.headers.get("x-capxul-timestamp");
44
- const signature = request.headers.get("x-capxul-signature");
45
- if (!timestamp || !signature) {
46
- return { valid: false, reason: "invalid_signature" };
47
- }
48
- const timestampMs = Number(timestamp);
49
- if (!Number.isFinite(timestampMs)) {
50
- return { valid: false, reason: "malformed" };
51
- }
52
- const freshnessWindowMs = options?.freshnessWindowMs ?? WEBHOOK_FRESHNESS_WINDOW_MS;
53
- if (Math.abs(Date.now() - timestampMs) > freshnessWindowMs) {
54
- return { valid: false, reason: "replay" };
55
- }
56
- const body = await request.text();
57
- const signatureHex = signature.startsWith("sha256=") ? signature.slice("sha256=".length) : signature;
58
- if (!/^[a-f0-9]{64}$/i.test(signatureHex)) {
59
- return { valid: false, reason: "invalid_signature" };
60
- }
61
- const validSignature = await verifyHmacSha256(
62
- secret,
63
- `${timestamp}.${body}`,
64
- signatureHex
65
- );
66
- if (!validSignature) {
67
- return { valid: false, reason: "invalid_signature" };
68
- }
69
- const parsed = parseWebhookEvent(body);
70
- if (!parsed) {
71
- return { valid: false, reason: "malformed" };
72
- }
73
- return { valid: true, event: parsed };
74
- }
75
- async function verifyHmacSha256(secret, message, signatureHex) {
76
- const encoder = new TextEncoder();
77
- const key = await crypto.subtle.importKey(
78
- "raw",
79
- encoder.encode(secret),
80
- { name: "HMAC", hash: "SHA-256" },
81
- false,
82
- ["verify"]
83
- );
84
- return await crypto.subtle.verify(
85
- "HMAC",
86
- key,
87
- hexToArrayBuffer(signatureHex),
88
- encoder.encode(message)
89
- );
90
- }
91
- function hexToArrayBuffer(hex) {
92
- const buffer = new ArrayBuffer(hex.length / 2);
93
- const bytes = new Uint8Array(buffer);
94
- for (let i = 0; i < bytes.length; i++) {
95
- bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
96
- }
97
- return buffer;
98
- }
99
- function parseWebhookEvent(body) {
100
- try {
101
- const parsed = JSON.parse(body);
102
- if (!isWebhookEvent(parsed)) return null;
103
- return parsed;
104
- } catch {
105
- return null;
106
- }
107
- }
108
- function isWebhookEvent(value) {
109
- if (!value || typeof value !== "object" || Array.isArray(value)) {
110
- return false;
111
- }
112
- const candidate = value;
113
- return typeof candidate.id === "string" && typeof candidate.type === "string" && typeof candidate.createdAt === "string" && (candidate.operationId === void 0 || typeof candidate.operationId === "string") && (candidate.correlationId === void 0 || typeof candidate.correlationId === "string") && !!candidate.data && typeof candidate.data === "object" && !Array.isArray(candidate.data);
114
- }
115
-
116
- export { verifyWebhook };