@indorania/contracts 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -0
- package/dist/common.d.ts +144 -0
- package/dist/common.d.ts.map +1 -0
- package/dist/common.js +162 -0
- package/dist/common.js.map +1 -0
- package/dist/constitution/index.d.ts +9 -0
- package/dist/constitution/index.d.ts.map +1 -0
- package/dist/constitution/index.js +9 -0
- package/dist/constitution/index.js.map +1 -0
- package/dist/constitution/openapi.d.ts +23 -0
- package/dist/constitution/openapi.d.ts.map +1 -0
- package/dist/constitution/openapi.js +375 -0
- package/dist/constitution/openapi.js.map +1 -0
- package/dist/constitution/report.d.ts +63 -0
- package/dist/constitution/report.d.ts.map +1 -0
- package/dist/constitution/report.js +73 -0
- package/dist/constitution/report.js.map +1 -0
- package/dist/constitution/tables.d.ts +53 -0
- package/dist/constitution/tables.d.ts.map +1 -0
- package/dist/constitution/tables.js +96 -0
- package/dist/constitution/tables.js.map +1 -0
- package/dist/constitution/words.d.ts +39 -0
- package/dist/constitution/words.d.ts.map +1 -0
- package/dist/constitution/words.js +126 -0
- package/dist/constitution/words.js.map +1 -0
- package/dist/document.d.ts +12 -0
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +106 -0
- package/dist/document.js.map +1 -0
- package/dist/domain-error.d.ts +14 -0
- package/dist/domain-error.d.ts.map +1 -0
- package/dist/domain-error.js +23 -0
- package/dist/domain-error.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/op.d.ts +92 -0
- package/dist/op.d.ts.map +1 -0
- package/dist/op.js +113 -0
- package/dist/op.js.map +1 -0
- package/dist/routes/asks.d.ts +77 -0
- package/dist/routes/asks.d.ts.map +1 -0
- package/dist/routes/asks.js +182 -0
- package/dist/routes/asks.js.map +1 -0
- package/dist/routes/backup.d.ts +12 -0
- package/dist/routes/backup.d.ts.map +1 -0
- package/dist/routes/backup.js +63 -0
- package/dist/routes/backup.js.map +1 -0
- package/dist/routes/capabilities.d.ts +67 -0
- package/dist/routes/capabilities.d.ts.map +1 -0
- package/dist/routes/capabilities.js +88 -0
- package/dist/routes/capabilities.js.map +1 -0
- package/dist/routes/entitlements.d.ts +137 -0
- package/dist/routes/entitlements.d.ts.map +1 -0
- package/dist/routes/entitlements.js +101 -0
- package/dist/routes/entitlements.js.map +1 -0
- package/dist/routes/guest.d.ts +57 -0
- package/dist/routes/guest.d.ts.map +1 -0
- package/dist/routes/guest.js +140 -0
- package/dist/routes/guest.js.map +1 -0
- package/dist/routes/integration.d.ts +187 -0
- package/dist/routes/integration.d.ts.map +1 -0
- package/dist/routes/integration.js +243 -0
- package/dist/routes/integration.js.map +1 -0
- package/dist/routes/meta.d.ts +50 -0
- package/dist/routes/meta.d.ts.map +1 -0
- package/dist/routes/meta.js +90 -0
- package/dist/routes/meta.js.map +1 -0
- package/dist/routes/organisations.d.ts +121 -0
- package/dist/routes/organisations.d.ts.map +1 -0
- package/dist/routes/organisations.js +175 -0
- package/dist/routes/organisations.js.map +1 -0
- package/dist/routes/presentations.d.ts +95 -0
- package/dist/routes/presentations.d.ts.map +1 -0
- package/dist/routes/presentations.js +121 -0
- package/dist/routes/presentations.js.map +1 -0
- package/dist/routes/sessions.d.ts +180 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +240 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/standing.d.ts +24 -0
- package/dist/routes/standing.d.ts.map +1 -0
- package/dist/routes/standing.js +74 -0
- package/dist/routes/standing.js.map +1 -0
- package/dist/routes/thank-yous.d.ts +30 -0
- package/dist/routes/thank-yous.d.ts.map +1 -0
- package/dist/routes/thank-yous.js +139 -0
- package/dist/routes/thank-yous.js.map +1 -0
- package/dist/versions.d.ts +46 -0
- package/dist/versions.d.ts.map +1 -0
- package/dist/versions.js +54 -0
- package/dist/versions.js.map +1 -0
- package/dist/webhooks.d.ts +55 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +76 -0
- package/dist/webhooks.js.map +1 -0
- package/dist/zod.d.ts +3 -0
- package/dist/zod.d.ts.map +1 -0
- package/dist/zod.js +7 -0
- package/dist/zod.js.map +1 -0
- package/node/kernel-esm.mjs +27 -0
- package/node/register.mjs +5 -0
- package/openapi/2026-09-25.json +6959 -0
- package/openapi/versions.json +10 -0
- package/package.json +49 -0
package/dist/versions.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dated API versions — the Stripe pattern (ECOSYSTEM d47(h): "platform API versioning").
|
|
3
|
+
*
|
|
4
|
+
* - The URL carries the major (`/v1`, architecture §10); the header `Indorania-Version: YYYY-MM-DD`
|
|
5
|
+
* carries the dated version. Resolution: the header, else the caller's pinned version (an
|
|
6
|
+
* organisation's or an integration's), else `400 version_required`.
|
|
7
|
+
* - Every organisation and every integration is pinned to one version. Webhooks reach a receiver
|
|
8
|
+
* rendered in its pin.
|
|
9
|
+
* - A version is a **preview** until it is released — the founder publishes `@indorania/contracts`,
|
|
10
|
+
* or a member first vendors its OpenAPI file (founder decision, PL-4, 2026-09-25). Until then it
|
|
11
|
+
* may be corrected in place. Once released, it changes by addition only; anything else is a new
|
|
12
|
+
* dated version whose `changes` translate between the two.
|
|
13
|
+
* - The handlers speak the latest version. Requests travel **up** through every change after the
|
|
14
|
+
* caller's version, oldest first; responses and webhook payloads travel **down**, newest first.
|
|
15
|
+
*/
|
|
16
|
+
export const VERSION_HEADER = "indorania-version";
|
|
17
|
+
export const VERSION_PATTERN = "^\\d{4}-\\d{2}-\\d{2}$";
|
|
18
|
+
/** Oldest first. The last entry is the version the handlers speak. */
|
|
19
|
+
export const VERSIONS = [
|
|
20
|
+
{ id: "2026-09-25", status: "preview", changes: [] },
|
|
21
|
+
];
|
|
22
|
+
export function latestVersion(versions = VERSIONS) {
|
|
23
|
+
const last = versions.at(-1);
|
|
24
|
+
if (!last)
|
|
25
|
+
throw new Error("the version registry is empty");
|
|
26
|
+
return last;
|
|
27
|
+
}
|
|
28
|
+
export function findVersion(id, versions = VERSIONS) {
|
|
29
|
+
return versions.find((v) => v.id === id);
|
|
30
|
+
}
|
|
31
|
+
/** The changes between `from` (exclusive) and the latest version, oldest first. */
|
|
32
|
+
function changesAfter(from, versions) {
|
|
33
|
+
const index = versions.findIndex((v) => v.id === from);
|
|
34
|
+
if (index < 0)
|
|
35
|
+
throw new Error(`unknown API version ${from}`);
|
|
36
|
+
return versions.slice(index + 1).flatMap((v) => v.changes);
|
|
37
|
+
}
|
|
38
|
+
/** A request body written for version `from`, translated up to the latest version. */
|
|
39
|
+
export function translateRequest(from, operationId, body, versions = VERSIONS) {
|
|
40
|
+
return changesAfter(from, versions).reduce((b, change) => (change.up ? change.up(operationId, b) : b), body);
|
|
41
|
+
}
|
|
42
|
+
/** A response body from the latest version, translated down to version `to`. */
|
|
43
|
+
export function translateResponse(to, operationId, status, body, versions = VERSIONS) {
|
|
44
|
+
return [...changesAfter(to, versions)]
|
|
45
|
+
.reverse()
|
|
46
|
+
.reduce((b, change) => (change.down ? change.down(operationId, status, b) : b), body);
|
|
47
|
+
}
|
|
48
|
+
/** A webhook payload's `data` from the latest version, translated down to the receiver's pin. */
|
|
49
|
+
export function translateEvent(to, type, data, versions = VERSIONS) {
|
|
50
|
+
return [...changesAfter(to, versions)]
|
|
51
|
+
.reverse()
|
|
52
|
+
.reduce((d, change) => (change.downEvent ? change.downEvent(type, d) : d), data);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=versions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versions.js","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAuBH,MAAM,CAAC,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAClD,MAAM,CAAC,MAAM,eAAe,GAAG,wBAAwB,CAAC;AAExD,sEAAsE;AACtE,MAAM,CAAC,MAAM,QAAQ,GAA0B;IAC7C,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE;CACrD,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,WAAkC,QAAQ;IACtE,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAU,EAAE,WAAkC,QAAQ;IAChF,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,mFAAmF;AACnF,SAAS,YAAY,CAAC,IAAY,EAAE,QAA+B;IACjE,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;IACvD,IAAI,KAAK,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IAC9D,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAC7D,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,WAAmB,EACnB,IAAa,EACb,WAAkC,QAAQ;IAE1C,OAAO,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAC/G,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,iBAAiB,CAC/B,EAAU,EACV,WAAmB,EACnB,MAAc,EACd,IAAa,EACb,WAAkC,QAAQ;IAE1C,OAAO,CAAC,GAAG,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;SACnC,OAAO,EAAE;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAC1F,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,cAAc,CAC5B,EAAU,EACV,IAAY,EACZ,IAAa,EACb,WAAkC,QAAQ;IAE1C,OAAO,CAAC,GAAG,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;SACnC,OAAO,EAAE;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AACrF,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@indorania/contracts/webhooks` — the reference signer and verifier for webhooks in both
|
|
3
|
+
* directions: the platform's to an integration, and an integration's to the platform.
|
|
4
|
+
*
|
|
5
|
+
* Standard Webhooks 1.0.0, asymmetric scheme `v1a` (Ed25519):
|
|
6
|
+
* - headers `webhook-id`, `webhook-timestamp` (unix seconds), `webhook-signature`;
|
|
7
|
+
* - signed content `${id}.${timestamp}.${body}`, over the body's exact bytes;
|
|
8
|
+
* - `webhook-signature` is a space-separated list of `v1a,<base64 signature>` — two during a key
|
|
9
|
+
* rotation — and a message verifies if any one verifies under any current key;
|
|
10
|
+
* - a timestamp more than 300 seconds from the receiver's clock is refused;
|
|
11
|
+
* - `webhook-id` is the idempotency key: a receiver processes each id once.
|
|
12
|
+
* Uses WebCrypto only, so it runs in Node 22, Deno, Bun, Workers and browsers.
|
|
13
|
+
*/
|
|
14
|
+
export declare const WEBHOOK_TOLERANCE_SEC = 300;
|
|
15
|
+
/** The payload structure Standard Webhooks recommends. `data` is rendered in the receiver's pinned version. */
|
|
16
|
+
export interface WebhookEvent<T = unknown> {
|
|
17
|
+
readonly type: string;
|
|
18
|
+
/** ISO 8601. */
|
|
19
|
+
readonly timestamp: string;
|
|
20
|
+
readonly data: T;
|
|
21
|
+
}
|
|
22
|
+
export interface WebhookHeaders {
|
|
23
|
+
readonly "webhook-id": string;
|
|
24
|
+
readonly "webhook-timestamp": string;
|
|
25
|
+
readonly "webhook-signature": string;
|
|
26
|
+
}
|
|
27
|
+
export type WebhookFailure = "missing-header" | "malformed-timestamp" | "timestamp-out-of-tolerance" | "no-valid-signature";
|
|
28
|
+
export declare function signedContent(id: string, timestamp: string | number, body: string): string;
|
|
29
|
+
/** An Ed25519 public key for verifying: a JWK (`{kty: "OKP", crv: "Ed25519", x}`), or the raw 32 bytes. */
|
|
30
|
+
export declare function importVerifyKey(key: {
|
|
31
|
+
kty: "OKP";
|
|
32
|
+
crv: "Ed25519";
|
|
33
|
+
x: string;
|
|
34
|
+
} | Uint8Array<ArrayBuffer>): Promise<CryptoKey>;
|
|
35
|
+
/** Sign one message. Returns the `webhook-signature` header value. */
|
|
36
|
+
export declare function signWebhook(input: {
|
|
37
|
+
id: string;
|
|
38
|
+
timestamp: number;
|
|
39
|
+
body: string;
|
|
40
|
+
privateKey: CryptoKey;
|
|
41
|
+
}): Promise<string>;
|
|
42
|
+
/** Verify one message against the sender's current public keys. */
|
|
43
|
+
export declare function verifyWebhook(input: {
|
|
44
|
+
headers: Partial<WebhookHeaders>;
|
|
45
|
+
body: string;
|
|
46
|
+
keys: readonly CryptoKey[];
|
|
47
|
+
nowSec?: number;
|
|
48
|
+
toleranceSec?: number;
|
|
49
|
+
}): Promise<{
|
|
50
|
+
ok: true;
|
|
51
|
+
} | {
|
|
52
|
+
ok: false;
|
|
53
|
+
reason: WebhookFailure;
|
|
54
|
+
}>;
|
|
55
|
+
//# sourceMappingURL=webhooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAGzC,+GAA+G;AAC/G,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gBAAgB;IAChB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAED,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,qBAAqB,GAAG,4BAA4B,GAAG,oBAAoB,CAAC;AAoB5H,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1F;AAED,2GAA2G;AAC3G,wBAAsB,eAAe,CAAC,GAAG,EAAE;IAAE,GAAG,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,SAAS,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAGlI;AAED,sEAAsE;AACtE,wBAAsB,WAAW,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,SAAS,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAIhI;AAED,mEAAmE;AACnE,wBAAsB,aAAa,CAAC,KAAK,EAAE;IACzC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,CAAC,CAuBhE"}
|
package/dist/webhooks.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@indorania/contracts/webhooks` — the reference signer and verifier for webhooks in both
|
|
3
|
+
* directions: the platform's to an integration, and an integration's to the platform.
|
|
4
|
+
*
|
|
5
|
+
* Standard Webhooks 1.0.0, asymmetric scheme `v1a` (Ed25519):
|
|
6
|
+
* - headers `webhook-id`, `webhook-timestamp` (unix seconds), `webhook-signature`;
|
|
7
|
+
* - signed content `${id}.${timestamp}.${body}`, over the body's exact bytes;
|
|
8
|
+
* - `webhook-signature` is a space-separated list of `v1a,<base64 signature>` — two during a key
|
|
9
|
+
* rotation — and a message verifies if any one verifies under any current key;
|
|
10
|
+
* - a timestamp more than 300 seconds from the receiver's clock is refused;
|
|
11
|
+
* - `webhook-id` is the idempotency key: a receiver processes each id once.
|
|
12
|
+
* Uses WebCrypto only, so it runs in Node 22, Deno, Bun, Workers and browsers.
|
|
13
|
+
*/
|
|
14
|
+
export const WEBHOOK_TOLERANCE_SEC = 300;
|
|
15
|
+
const SCHEME = "v1a";
|
|
16
|
+
const encoder = new TextEncoder();
|
|
17
|
+
const VERIFY = ["verify"];
|
|
18
|
+
function toBase64(bytes) {
|
|
19
|
+
let binary = "";
|
|
20
|
+
for (const b of bytes)
|
|
21
|
+
binary += String.fromCharCode(b);
|
|
22
|
+
return btoa(binary);
|
|
23
|
+
}
|
|
24
|
+
function fromBase64(text) {
|
|
25
|
+
try {
|
|
26
|
+
const binary = atob(text.replace(/-/g, "+").replace(/_/g, "/"));
|
|
27
|
+
return Uint8Array.from(binary, (c) => c.charCodeAt(0));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function signedContent(id, timestamp, body) {
|
|
34
|
+
return `${id}.${timestamp}.${body}`;
|
|
35
|
+
}
|
|
36
|
+
/** An Ed25519 public key for verifying: a JWK (`{kty: "OKP", crv: "Ed25519", x}`), or the raw 32 bytes. */
|
|
37
|
+
export async function importVerifyKey(key) {
|
|
38
|
+
if (key instanceof Uint8Array)
|
|
39
|
+
return crypto.subtle.importKey("raw", key, { name: "Ed25519" }, false, VERIFY);
|
|
40
|
+
return crypto.subtle.importKey("jwk", { kty: key.kty, crv: key.crv, x: key.x }, { name: "Ed25519" }, false, VERIFY);
|
|
41
|
+
}
|
|
42
|
+
/** Sign one message. Returns the `webhook-signature` header value. */
|
|
43
|
+
export async function signWebhook(input) {
|
|
44
|
+
const content = encoder.encode(signedContent(input.id, input.timestamp, input.body));
|
|
45
|
+
const signature = new Uint8Array(await crypto.subtle.sign({ name: "Ed25519" }, input.privateKey, content));
|
|
46
|
+
return `${SCHEME},${toBase64(signature)}`;
|
|
47
|
+
}
|
|
48
|
+
/** Verify one message against the sender's current public keys. */
|
|
49
|
+
export async function verifyWebhook(input) {
|
|
50
|
+
const id = input.headers["webhook-id"];
|
|
51
|
+
const timestamp = input.headers["webhook-timestamp"];
|
|
52
|
+
const header = input.headers["webhook-signature"];
|
|
53
|
+
if (!id || !timestamp || !header)
|
|
54
|
+
return { ok: false, reason: "missing-header" };
|
|
55
|
+
if (!/^\d{1,12}$/.test(timestamp))
|
|
56
|
+
return { ok: false, reason: "malformed-timestamp" };
|
|
57
|
+
const now = input.nowSec ?? Math.floor(Date.now() / 1000);
|
|
58
|
+
if (Math.abs(now - Number(timestamp)) > (input.toleranceSec ?? WEBHOOK_TOLERANCE_SEC)) {
|
|
59
|
+
return { ok: false, reason: "timestamp-out-of-tolerance" };
|
|
60
|
+
}
|
|
61
|
+
const content = encoder.encode(signedContent(id, timestamp, input.body));
|
|
62
|
+
for (const entry of header.split(" ")) {
|
|
63
|
+
const [scheme, value] = entry.split(",", 2);
|
|
64
|
+
if (scheme !== SCHEME || !value)
|
|
65
|
+
continue;
|
|
66
|
+
const signature = fromBase64(value);
|
|
67
|
+
if (!signature || signature.length !== 64)
|
|
68
|
+
continue;
|
|
69
|
+
for (const key of input.keys) {
|
|
70
|
+
if (await crypto.subtle.verify({ name: "Ed25519" }, key, signature, content))
|
|
71
|
+
return { ok: true };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return { ok: false, reason: "no-valid-signature" };
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=webhooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"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"}
|
package/dist/zod.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,EAAE,CAAC,EAAE,CAAC"}
|
package/dist/zod.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// One Zod instance for the whole contract, extended once so `.openapi()` is available to the
|
|
2
|
+
// generator. Every module imports `z` from here, never from "zod" directly.
|
|
3
|
+
import { extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
extendZodWithOpenApi(z);
|
|
6
|
+
export { z };
|
|
7
|
+
//# sourceMappingURL=zod.js.map
|
package/dist/zod.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod.js","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,4EAA4E;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAExB,OAAO,EAAE,CAAC,EAAE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// A Node resolve hook for one defect in the published kernel, and nothing else.
|
|
2
|
+
//
|
|
3
|
+
// @kashscript/attest (0.1.8 and 0.2.0-alpha.1) and @kashscript/identity-core (0.3.1) ship
|
|
4
|
+
// ES modules whose relative imports carry no extension ("./constants"). Bundlers accept that;
|
|
5
|
+
// Node's own resolver refuses it with ERR_MODULE_NOT_FOUND, so no library entry of the kernel
|
|
6
|
+
// loads under plain Node (the attest CLI works only because it is bundled). Verified 2026-09-25.
|
|
7
|
+
//
|
|
8
|
+
// This hook retries a failed relative import (a missing extension, or a bare directory such as identity-server's "./witness") made *from inside an @kashscript package* with
|
|
9
|
+
// ".js", then "/index.js". Every other import resolves exactly as Node resolves it. Delete this
|
|
10
|
+
// file, and the --import flags that load it, once KashScript republishes with ".js" specifiers.
|
|
11
|
+
|
|
12
|
+
export async function resolve(specifier, context, nextResolve) {
|
|
13
|
+
try {
|
|
14
|
+
return await nextResolve(specifier, context);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
const fromKernel = context.parentURL?.includes("/node_modules/@kashscript/") ?? false;
|
|
17
|
+
if ((error?.code !== "ERR_MODULE_NOT_FOUND" && error?.code !== "ERR_UNSUPPORTED_DIR_IMPORT") || !fromKernel || !specifier.startsWith(".")) throw error;
|
|
18
|
+
for (const suffix of [".js", "/index.js"]) {
|
|
19
|
+
try {
|
|
20
|
+
return await nextResolve(specifier + suffix, context);
|
|
21
|
+
} catch {
|
|
22
|
+
// try the next form
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Load with `node --import @indorania/contracts/node/register` (or a relative path inside this
|
|
2
|
+
// package). It registers kernel-esm.mjs — see that file for why, and for when to delete both.
|
|
3
|
+
import { register } from "node:module";
|
|
4
|
+
|
|
5
|
+
register("./kernel-esm.mjs", import.meta.url);
|