@vess-id/ai-identity 0.11.0 → 0.12.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.
Files changed (32) hide show
  1. package/README.md +0 -16
  2. package/dist/client.d.ts +0 -14
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/index.d.mts +342 -153
  5. package/dist/index.d.ts +2 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +164 -204
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +150 -203
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/internal-signature/__tests__/canonical.spec.d.ts +2 -0
  12. package/dist/internal-signature/__tests__/canonical.spec.d.ts.map +1 -0
  13. package/dist/internal-signature/__tests__/signer-roundtrip.spec.d.ts +2 -0
  14. package/dist/internal-signature/__tests__/signer-roundtrip.spec.d.ts.map +1 -0
  15. package/dist/internal-signature/__tests__/signer.spec.d.ts +2 -0
  16. package/dist/internal-signature/__tests__/signer.spec.d.ts.map +1 -0
  17. package/dist/internal-signature/canonical.d.ts +80 -0
  18. package/dist/internal-signature/canonical.d.ts.map +1 -0
  19. package/dist/internal-signature/index.d.ts +17 -0
  20. package/dist/internal-signature/index.d.ts.map +1 -0
  21. package/dist/internal-signature/signer.d.ts +76 -0
  22. package/dist/internal-signature/signer.d.ts.map +1 -0
  23. package/dist/registry/index.d.ts +2 -0
  24. package/dist/registry/index.d.ts.map +1 -1
  25. package/dist/registry/reauth-constants.d.ts +33 -0
  26. package/dist/registry/reauth-constants.d.ts.map +1 -0
  27. package/dist/vp/kb-jwt-builder.d.ts +89 -0
  28. package/dist/vp/kb-jwt-builder.d.ts.map +1 -0
  29. package/dist/vp/vp-manager.d.ts.map +1 -1
  30. package/package.json +20 -26
  31. package/dist/memory/memory-manager.d.ts +0 -77
  32. package/dist/memory/memory-manager.d.ts.map +0 -1
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=canonical.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.spec.d.ts","sourceRoot":"","sources":["../../../src/internal-signature/__tests__/canonical.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=signer-roundtrip.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer-roundtrip.spec.d.ts","sourceRoot":"","sources":["../../../src/internal-signature/__tests__/signer-roundtrip.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=signer.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.spec.d.ts","sourceRoot":"","sources":["../../../src/internal-signature/__tests__/signer.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * P1-A14a-1 / Threat Model S4 — canonical-string + signature-header
3
+ * helpers for HMAC body signing of internal HTTP requests.
4
+ *
5
+ * Pure module: no NestJS, no I/O, no side effects. SDK is the
6
+ * single source of truth (P1-A14a-2d) — api / remote-mcp /
7
+ * slack-bot all import from `@vess-id/ai-identity`.
8
+ *
9
+ * Header format (Q1 = A, Stripe-style versioned):
10
+ * X-Internal-Signature: v1=<keyId>:<unixSeconds>:<base64(hmac)>
11
+ *
12
+ * Canonical string (Q2 = A, no header inclusion):
13
+ * ${METHOD.toUpperCase()}\n${path}\n${unixSeconds}\n${sha256Hex(rawBody)}
14
+ *
15
+ * Replay window (Q3 = A): 300 seconds — enforced by the api guard,
16
+ * not here. This module is responsible for *constructing* the
17
+ * canonical string and *parsing* the header; freshness is policy.
18
+ */
19
+ export declare const SIGNATURE_HEADER = "x-internal-signature";
20
+ export declare const SIGNATURE_VERSION_PREFIX = "v1=";
21
+ /**
22
+ * SHA-256 hex digest of an arbitrary buffer or string. Hex (not
23
+ * base64) so the canonical string is URL-safe and grep-friendly in
24
+ * logs if a future debug session ever needs to reconstruct it
25
+ * server-side.
26
+ */
27
+ export declare function sha256Hex(input: Buffer | string): string;
28
+ /**
29
+ * Build the canonical string that gets HMAC'd. The components are
30
+ * separated by `\n` because no legitimate input contains `\n` (the
31
+ * method is uppercase ASCII, the path is URL-encoded by the caller,
32
+ * the timestamp is digits, the body hash is hex). Using `\n` as
33
+ * separator avoids ambiguity that delimiters like `:` would
34
+ * introduce when the path contains a colon.
35
+ *
36
+ * Whitespace is NOT trimmed — input must be exactly what will land
37
+ * on the wire. Caller controls case and encoding.
38
+ */
39
+ export declare function buildCanonicalString(args: {
40
+ method: string;
41
+ path: string;
42
+ unixSeconds: number;
43
+ rawBody: Buffer | string;
44
+ }): string;
45
+ /** Shape of a parsed `X-Internal-Signature` header. */
46
+ export interface ParsedSignature {
47
+ /** Identifier of the signing key (e.g. `'mcp-v2'`). */
48
+ keyId: string;
49
+ /** Unix epoch seconds at signing time. */
50
+ unixSeconds: number;
51
+ /** Base64-encoded HMAC-SHA256 digest. */
52
+ signature: string;
53
+ }
54
+ /**
55
+ * Parse a `X-Internal-Signature` header value. Returns `null` for
56
+ * any malformed shape rather than throwing — the api guard converts
57
+ * `null` to a `401 Unauthorized` so a malformed header never
58
+ * triggers a `500`.
59
+ *
60
+ * Accepted: `v1=<keyId>:<digits>:<base64>`
61
+ *
62
+ * Defensive checks:
63
+ * - Must start with `v1=` (Q1: explicit version prefix)
64
+ * - keyId / signature must be non-empty after split
65
+ * - timestamp must parse to a finite, non-negative integer
66
+ * - keyId must be ASCII identifier-safe ([A-Za-z0-9_-]+) so a
67
+ * malicious header cannot smuggle control chars or whitespace
68
+ * into log lines / metric labels
69
+ * - signature must be valid base64 (only base64 alphabet chars)
70
+ */
71
+ export declare function parseSignatureHeader(headerValue: string | undefined): ParsedSignature | null;
72
+ /**
73
+ * Format a ParsedSignature back into a header string. Round-trips
74
+ * with `parseSignatureHeader` for any validly-shaped input.
75
+ *
76
+ * Used by the signing side (HTTP client). Keeping it next to the
77
+ * parser pins the format in one place.
78
+ */
79
+ export declare function formatSignatureHeader(parsed: ParsedSignature): string;
80
+ //# sourceMappingURL=canonical.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../../src/internal-signature/canonical.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,eAAO,MAAM,gBAAgB,yBAAyB,CAAA;AACtD,eAAO,MAAM,wBAAwB,QAAQ,CAAA;AAE7C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAExD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;CACzB,GAAG,MAAM,CAGT;AAED,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;IACb,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAA;IACnB,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,eAAe,GAAG,IAAI,CA4B5F;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAErE"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Public API of `@vess-id/ai-identity/internal-signature` (P1-A14a-2d).
3
+ *
4
+ * Re-exported via the SDK barrel (`packages/sdk/src/index.ts`) so
5
+ * consumers can write:
6
+ *
7
+ * import { signRequest, SIGNATURE_HEADER } from '@vess-id/ai-identity'
8
+ *
9
+ * SDK is the single source of truth — api / remote-mcp / slack-bot
10
+ * all import from here. The api side keeps verifier-only types
11
+ * (`HmacKeyset`, `InternalSignatureGuard`) in
12
+ * `packages/api/src/common/internal-signature/` so the SDK avoids
13
+ * a NestJS dependency.
14
+ */
15
+ export { buildCanonicalString, formatSignatureHeader, parseSignatureHeader, sha256Hex, SIGNATURE_HEADER, SIGNATURE_VERSION_PREFIX, type ParsedSignature, } from './canonical';
16
+ export { signRequest, MIN_SIGNER_KEY_BYTES, type InternalHmacSignerKey, type SignRequestArgs, } from './signer';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/internal-signature/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,SAAS,EACT,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,GACrB,MAAM,UAAU,CAAA"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * P1-A14a-2d — pure HMAC signer for outbound /api/internal/**
3
+ * requests. Lives in SDK so remote-mcp and slack-bot (both of which
4
+ * already depend on `@vess-id/ai-identity`) can attach
5
+ * `X-Internal-Signature` to every request without dragging the
6
+ * api package into their dependency graph.
7
+ *
8
+ * Pure (no I/O, no Nest). Mirrors the `utils/crypto.ts` profile:
9
+ * the only Node-builtin used is `crypto.createHmac`.
10
+ *
11
+ * Pairing with the verifier
12
+ * -------------------------
13
+ * The verifier (api side, `HmacKeyset.verify` →
14
+ * `buildCanonicalString` → constant-time compare) reads the same
15
+ * `buildCanonicalString` from this module by construction. As long
16
+ * as both sides pass the same `(method, path, unixSeconds, rawBody)`
17
+ * the HMACs match by definition.
18
+ *
19
+ * Body bytes
20
+ * ----------
21
+ * The caller MUST pass the exact bytes that go on the wire as
22
+ * `rawBody`. Re-running `JSON.stringify(...)` on each side would
23
+ * risk a byte mismatch (object key order is implementation-defined
24
+ * in spec, even though V8 preserves insertion order in practice).
25
+ * The api-client `makeRequest` helper computes `JSON.stringify`
26
+ * once, hands the same string to both `signRequest` and `fetch`.
27
+ */
28
+ /**
29
+ * Minimum signer key length in raw bytes. 32 bytes = 256 bits
30
+ * matches HMAC-SHA256's natural block size and the verifier's
31
+ * `MIN_KEY_BYTES`. A truncated env var (accidental newline,
32
+ * copy-paste error) is the realistic failure mode this guards
33
+ * against.
34
+ */
35
+ export declare const MIN_SIGNER_KEY_BYTES = 32;
36
+ export interface InternalHmacSignerKey {
37
+ /** Stable identifier for the key, e.g. `'mcp-v1'`. Embedded in
38
+ * the X-Internal-Signature header so the verifier can pick the
39
+ * right key. Must match `/^[A-Za-z0-9_-]+$/`. */
40
+ keyId: string;
41
+ /** Raw HMAC secret. >= MIN_SIGNER_KEY_BYTES bytes. */
42
+ secret: Buffer;
43
+ }
44
+ export interface SignRequestArgs {
45
+ /** HTTP method. Will be upper-cased by `buildCanonicalString`,
46
+ * but callers should pass the uppercase form they use on the
47
+ * wire so signer and `fetch()` stay in lockstep. */
48
+ method: string;
49
+ /** URL path with query string already stripped (verifier does
50
+ * `request.originalUrl?.split('?')[0]`; signer must mirror).
51
+ * Path encoding (e.g. `%2F` vs `/`) is caller's responsibility
52
+ * — the canonical string treats them as different bytes. */
53
+ path: string;
54
+ /** Wire bytes. The same string/buffer passed to `fetch({body})`
55
+ * must be passed here — `JSON.stringify` runs ONCE per request
56
+ * in the caller. */
57
+ rawBody: Buffer | string;
58
+ /** Optional fixed timestamp for testing. Defaults to
59
+ * `Math.floor(Date.now() / 1000)`. */
60
+ unixSeconds?: number;
61
+ }
62
+ /**
63
+ * Sign an outbound request and return a fully-formatted
64
+ * `X-Internal-Signature` header value. The caller sets the header
65
+ * on the outbound request directly:
66
+ *
67
+ * ```ts
68
+ * headers[SIGNATURE_HEADER] = signRequest(key, { method, path, rawBody })
69
+ * ```
70
+ *
71
+ * Throws if key material is invalid (bad keyId or short secret) —
72
+ * surfacing misconfiguration loudly at request time rather than
73
+ * silently producing a header the verifier will reject.
74
+ */
75
+ export declare function signRequest(key: InternalHmacSignerKey, args: SignRequestArgs): string;
76
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/internal-signature/signer.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAA;AAEtC,MAAM,WAAW,qBAAqB;IACpC;;sDAEkD;IAClD,KAAK,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,eAAe;IAC9B;;yDAEqD;IACrD,MAAM,EAAE,MAAM,CAAA;IACd;;;iEAG6D;IAC7D,IAAI,EAAE,MAAM,CAAA;IACZ;;yBAEqB;IACrB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB;2CACuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,qBAAqB,EAAE,IAAI,EAAE,eAAe,GAAG,MAAM,CAgBrF"}
@@ -6,4 +6,6 @@ export { CanonicalProvider, AnyProvider, CANONICAL_PROVIDERS, PROVIDER_ALIASES,
6
6
  export { RESOURCE_TYPES, UnifiedResourceType, LEGACY_RESOURCE_TYPE_MAP, resolveResourceType, } from './resource-types';
7
7
  export { canonicalizeAction, getActionAliases, getAllActionForms, isActionEquivalent, } from './action-aliases';
8
8
  export { VALID_MCP_ACTIONS, VALID_MCP_TOOLS, getAllValidMcpActionNames, getValidMcpActionNames, normalizeMcpActionName, } from './action-normalizer';
9
+ export { REAUTH_REQUIRED_ACTION, GATEWAY_ERROR_CODE, } from './reauth-constants';
10
+ export type { GatewayErrorCode } from './reauth-constants';
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,eAAe,EACf,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,eAAe,GAChB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,SAAS,EACT,sBAAsB,EACtB,0BAA0B,EAC1B,4BAA4B,EAC5B,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAC1B,cAAc,wBAAwB,CAAA;AAGtC,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,eAAe,GAChB,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,eAAe,EACf,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,eAAe,GAChB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,SAAS,EACT,sBAAsB,EACtB,0BAA0B,EAC1B,4BAA4B,EAC5B,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAC1B,cAAc,wBAAwB,CAAA;AAGtC,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,eAAe,GAChB,MAAM,aAAa,CAAA;AAGpB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EACL,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Cross-package constants for the reauth pipeline.
3
+ *
4
+ * These string literals are contract-level identifiers shared between:
5
+ * - api (`tool-auth.service.ts`, `token-refresh.service.ts`)
6
+ * - remote-mcp (`mcp-format-result.ts`)
7
+ * - agentd (`gateway-client.ts`, `credential-errors.ts`, `execution-engine.ts`)
8
+ *
9
+ * Hard-coding them at each site made typo bugs silent. Centralizing here
10
+ * means any renames surface as a compile error on every import site.
11
+ */
12
+ /**
13
+ * Value for `ToolInvokeResponse.metadata.action` when the api signals a
14
+ * revoked/expired OAuth token. Consumers branch on this to render a reauth
15
+ * prompt (Slack DM card, CLI authUrl, etc.) instead of treating the response
16
+ * as a normal error.
17
+ */
18
+ export declare const REAUTH_REQUIRED_ACTION: "reauth_required";
19
+ /**
20
+ * Error codes emitted by agentd's `gateway-client.invokeTool` to classify
21
+ * failure modes for the ExecutionEngine to branch on. Kept as a const object
22
+ * rather than an enum so it serializes cleanly across the wire and in logs.
23
+ */
24
+ export declare const GATEWAY_ERROR_CODE: {
25
+ /** Upstream OAuth token is revoked — the user must re-auth at the SaaS provider. */
26
+ readonly REAUTH_REQUIRED: "REAUTH_REQUIRED";
27
+ /** Local VC/VP is invalid (expired, malformed, signature mismatch). Try VC reissuance. */
28
+ readonly CREDENTIAL_INVALID: "CREDENTIAL_INVALID";
29
+ /** VC allowed a different resource than the request targeted. Try a new approval. */
30
+ readonly RESOURCE_MISMATCH: "RESOURCE_MISMATCH";
31
+ };
32
+ export type GatewayErrorCode = (typeof GATEWAY_ERROR_CODE)[keyof typeof GATEWAY_ERROR_CODE];
33
+ //# sourceMappingURL=reauth-constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reauth-constants.d.ts","sourceRoot":"","sources":["../../src/registry/reauth-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAG,iBAA0B,CAAA;AAEhE;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;IAC7B,oFAAoF;;IAEpF,0FAA0F;;IAE1F,qFAAqF;;CAE7E,CAAA;AAEV,MAAM,MAAM,gBAAgB,GAC1B,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAA"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Single source of truth for Key Binding JWT (KB-JWT) issuance shared across
3
+ * the AIdentity stack. Four production code paths build KB-JWTs and they
4
+ * MUST stay byte-for-byte equivalent so a presentation built on one side is
5
+ * accepted by the verifier on the other:
6
+ *
7
+ * - SDK clients via `VPManager.create()` (this package)
8
+ * - API service via `packages/api/src/vp/vp-creation.service.ts`
9
+ * - Remote MCP via `packages/remote-mcp/src/services/vp-creation.service.ts`
10
+ * - agentd (`@vess-id/vess`) via `VPBuilder.buildVP()`
11
+ * (`packages/agentd/src/wallet/vp-builder.ts`)
12
+ *
13
+ * Historically each path had its own copy of this logic. PR #391 (the
14
+ * commit that made `exp` REQUIRED on the verifier side) updated only two of
15
+ * the three issuer paths known at the time; the SDK was missed and every
16
+ * SDK-built VP started failing at verification time. The follow-up
17
+ * consolidation (commit 02b169aa) brought the SDK in line, but agentd —
18
+ * which had its own KB-JWT literal in `wallet/vp-builder.ts` — was not
19
+ * recognized as a fourth issuer. Staging then rejected every VP from
20
+ * `@vess-id/vess` agentd alpha builds with `KB-JWT missing exp` until the
21
+ * agentd hotfix (this commit's cohort) wired its VPBuilder through
22
+ * `buildKbJwtPayload()`. This module exists so that a future verifier
23
+ * change cannot drift from the issuer side: any update lands in one place
24
+ * and all four paths inherit it.
25
+ */
26
+ /**
27
+ * Default KB-JWT lifetime in seconds. Mirrors the cap enforced by the API's
28
+ * `KeyBindingVerifierService.MAX_KB_JWT_LIFETIME_SECONDS` (also 300).
29
+ *
30
+ * The KB-JWT `exp` is the smaller of:
31
+ * - `iat + KB_JWT_DEFAULT_LIFETIME_SECONDS`
32
+ * - the parent VC's `exp` (so the bearer's freshness window cannot outlive
33
+ * the underlying credential's validity, which is itself bounded by
34
+ * `grant.expiresAt` at issuance time).
35
+ */
36
+ export declare const KB_JWT_DEFAULT_LIFETIME_SECONDS = 300;
37
+ export interface KbJwtPayload {
38
+ iss: string;
39
+ aud: string;
40
+ nonce: string;
41
+ iat: number;
42
+ exp: number;
43
+ }
44
+ export interface BuildKbJwtPayloadArgs {
45
+ /** Holder DID — becomes the KB-JWT `iss` claim. */
46
+ holderDid: string;
47
+ /** Verifier audience (URL or hostname). Will be normalized via {@link normalizeDomain}. */
48
+ audience: string;
49
+ /** Verifier-supplied nonce / challenge. */
50
+ nonce: string;
51
+ /** The parent SD-JWT VC string. Its `exp` (if any) caps the KB-JWT lifetime. */
52
+ vcCredential: string;
53
+ }
54
+ export interface BuildKbJwtPayloadDeps {
55
+ /** Returns the current time in milliseconds. Defaults to `Date.now`. */
56
+ now?: () => number;
57
+ }
58
+ /**
59
+ * Build a Key Binding JWT payload for an SD-JWT VC presentation.
60
+ *
61
+ * Throws when the parent VC is already expired (`vc.exp <= now`). The error
62
+ * message intentionally contains the substring `"VC has expired"` so that
63
+ * downstream catchers (notably remote-mcp's `isCredentialInvalidError`) can
64
+ * detect a stale-credential condition and trigger a re-approval flow rather
65
+ * than surface an opaque issuance failure to the user.
66
+ */
67
+ export declare function buildKbJwtPayload(args: BuildKbJwtPayloadArgs, deps?: BuildKbJwtPayloadDeps): KbJwtPayload;
68
+ /**
69
+ * Best-effort read of the VC's `exp` claim from the SD-JWT outer payload.
70
+ * Returns undefined when the VC is malformed, missing exp, or the field is
71
+ * not a number — callers fall back to {@link KB_JWT_DEFAULT_LIFETIME_SECONDS}
72
+ * in that case so issuance does not break for VCs without an explicit expiry.
73
+ */
74
+ export declare function readVcExpSeconds(sdJwtVc: string): number | undefined;
75
+ /**
76
+ * Normalize a domain string for consistent use as a JWT `aud` claim.
77
+ *
78
+ * The API verifier compares the KB-JWT `aud` against the expected domain by
79
+ * exact string match, so issuer and verifier must agree on the canonical
80
+ * form. We delegate to the URL parser, which strips paths and lowercases
81
+ * the host, then return the resulting `origin`.
82
+ *
83
+ * Inputs without a scheme are assumed to be hostnames; `localhost` (with or
84
+ * without a port) defaults to `http://`, everything else to `https://`. If
85
+ * URL parsing fails, the input is returned unchanged so a caller can still
86
+ * detect the mismatch downstream rather than silently swallowing a typo.
87
+ */
88
+ export declare function normalizeDomain(domain: string): string;
89
+ //# sourceMappingURL=kb-jwt-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kb-jwt-builder.d.ts","sourceRoot":"","sources":["../../src/vp/kb-jwt-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,+BAA+B,MAAM,CAAA;AAElD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,qBAAqB;IACpC,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAA;IACjB,2FAA2F;IAC3F,QAAQ,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,qBAAqB,EAC3B,IAAI,GAAE,qBAA0B,GAC/B,YAAY,CAqBd;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUpE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAgBtD"}
@@ -1 +1 @@
1
- {"version":3,"file":"vp-manager.d.ts","sourceRoot":"","sources":["../../src/vp/vp-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAK/C,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAAY;gBAElB,UAAU,CAAC,EAAE,UAAU;IAMnC;;;OAGG;IACG,MAAM,CACV,GAAG,EAAE,MAAM,EAAE,EAAE,6BAA6B;IAC5C,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,EAAE,MAAM,CAAA;QACjB,MAAM,EAAE,MAAM,CAAA;QACd,OAAO,CAAC,EAAE,MAAM,CAAA;KACjB,GACA,OAAO,CAAC,MAAM,CAAC;IA8ClB;;OAEG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QACP,iBAAiB,EAAE,MAAM,CAAA;QACzB,cAAc,EAAE,MAAM,CAAA;QACtB,cAAc,CAAC,EAAE,MAAM,CAAA;KACxB,GACA,OAAO,CAAC,sBAAsB,CAAC;IAwClC;;OAEG;IACH,aAAa,CACX,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,eAAe,CAAC,EAAE,GAAG,CAAA;KACtB,GACA,SAAS;IAQZ;;OAEG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;CAehD"}
1
+ {"version":3,"file":"vp-manager.d.ts","sourceRoot":"","sources":["../../src/vp/vp-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAM/C,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAAY;gBAElB,UAAU,CAAC,EAAE,UAAU;IAMnC;;;OAGG;IACG,MAAM,CACV,GAAG,EAAE,MAAM,EAAE,EAAE,6BAA6B;IAC5C,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,EAAE,MAAM,CAAA;QACjB,MAAM,EAAE,MAAM,CAAA;QACd,OAAO,CAAC,EAAE,MAAM,CAAA;KACjB,GACA,OAAO,CAAC,MAAM,CAAC;IA6ClB;;OAEG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QACP,iBAAiB,EAAE,MAAM,CAAA;QACzB,cAAc,EAAE,MAAM,CAAA;QACtB,cAAc,CAAC,EAAE,MAAM,CAAA;KACxB,GACA,OAAO,CAAC,sBAAsB,CAAC;IAwClC;;OAEG;IACH,aAAa,CACX,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,eAAe,CAAC,EAAE,GAAG,CAAA;KACtB,GACA,SAAS;IAQZ;;OAEG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;CAehD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vess-id/ai-identity",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "TypeScript SDK for AI Identity Layer",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -21,40 +21,34 @@
21
21
  "url": "https://github.com/cvoxelprotocol/aidentity.git",
22
22
  "directory": "packages/sdk"
23
23
  },
24
- "scripts": {
25
- "build": "tsup && tsc --declaration --emitDeclarationOnly --outDir dist",
26
- "dev": "tsup --watch",
27
- "test": "jest",
28
- "typecheck": "tsc --noEmit",
29
- "clean": "rm -rf dist node_modules",
30
- "semantic-release": "semantic-release"
31
- },
32
24
  "dependencies": {
33
25
  "@sd-jwt/crypto-nodejs": "^0.15.0",
34
26
  "@sd-jwt/sd-jwt-vc": "^0.15.1",
35
27
  "@sd-jwt/types": "^0.15.0",
36
- "ajv": "^8.17.1",
28
+ "ajv": "^8.18.0",
37
29
  "ajv-formats": "^3.0.1",
38
- "jose": "^5.1.0",
39
- "uuid": "^9.0.0"
30
+ "jose": "^5.10.0",
31
+ "uuid": "^9.0.1"
40
32
  },
41
33
  "devDependencies": {
42
- "@types/jest": "^29.5.0",
43
- "@types/node": "^20.10.0",
44
- "@types/uuid": "^9.0.0",
34
+ "@types/jest": "^29.5.14",
35
+ "@types/node": "^20.19.39",
36
+ "@types/uuid": "^9.0.8",
45
37
  "jest": "^29.7.0",
46
- "ts-jest": "^29.1.0",
47
- "tsup": "^8.0.0",
48
- "typescript": "^5.3.0",
49
- "@semantic-release/commit-analyzer": "^13.0.1",
50
- "@semantic-release/github": "^12.0.6",
51
- "@semantic-release/npm": "^13.0.0",
52
- "@semantic-release/release-notes-generator": "^14.1.0",
53
- "conventional-changelog-conventionalcommits": "^9.3.0",
54
- "semantic-release": "^25.0.3"
38
+ "ts-jest": "^29.4.9",
39
+ "tsup": "^8.5.1",
40
+ "typescript": "^5.9.3"
55
41
  },
56
42
  "publishConfig": {
57
43
  "access": "public"
58
44
  },
59
- "license": "MIT"
60
- }
45
+ "license": "MIT",
46
+ "scripts": {
47
+ "build": "tsup && tsc --declaration --emitDeclarationOnly --outDir dist",
48
+ "dev": "tsup --watch --no-clean",
49
+ "test": "jest",
50
+ "typecheck": "tsc --noEmit",
51
+ "clean": "rm -rf dist node_modules",
52
+ "assert:publish-surface": "node scripts/assert-publish-surface.js"
53
+ }
54
+ }
@@ -1,77 +0,0 @@
1
- import { VPManager } from '../vp/vp-manager';
2
- /**
3
- * NOTE: MemoryManager is currently DORMANT (as of 2026-03-29).
4
- * The API memory endpoints exist but are not actively called in production.
5
- * The server-side implementation (InMemoryProvider) is volatile and not shared across instances.
6
- * Do not rely on this in production until a persistent backend is introduced.
7
- */
8
- export interface MemoryDocument {
9
- id: string;
10
- namespace: string;
11
- content: string;
12
- metadata?: Record<string, any>;
13
- embedding?: number[];
14
- createdAt: string;
15
- updatedAt: string;
16
- }
17
- export interface MemoryQuery {
18
- query: string;
19
- namespace?: string;
20
- limit?: number;
21
- filter?: Record<string, any>;
22
- includeEmbedding?: boolean;
23
- }
24
- export interface MemoryQueryResult {
25
- documents: MemoryDocument[];
26
- scores?: number[];
27
- total: number;
28
- }
29
- export declare class MemoryManager {
30
- private vpManager;
31
- private proxyApiUrl;
32
- constructor(vpManager?: VPManager);
33
- /**
34
- * Write a document to memory
35
- */
36
- write(content: string, options: {
37
- namespace: string;
38
- metadata?: Record<string, any>;
39
- vcs: string[];
40
- holderDid: string;
41
- }): Promise<MemoryDocument>;
42
- /**
43
- * Query memory with vector search
44
- */
45
- query(query: string, options: {
46
- namespace?: string;
47
- limit?: number;
48
- filter?: Record<string, any>;
49
- vcs: string[];
50
- holderDid: string;
51
- }): Promise<MemoryQueryResult>;
52
- /**
53
- * Delete a document from memory
54
- */
55
- delete(documentId: string, options: {
56
- namespace: string;
57
- vcs: string[];
58
- holderDid: string;
59
- }): Promise<void>;
60
- /**
61
- * List documents in a namespace
62
- */
63
- list(options: {
64
- namespace: string;
65
- limit?: number;
66
- offset?: number;
67
- vcs: string[];
68
- holderDid: string;
69
- }): Promise<MemoryQueryResult>;
70
- /**
71
- * Check if VCs authorize memory access
72
- */
73
- checkAuthorization(vcs: string[], action: 'read' | 'write' | 'delete', resource: string): Promise<boolean>;
74
- private matchResource;
75
- private generateChallenge;
76
- }
77
- //# sourceMappingURL=memory-manager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory-manager.d.ts","sourceRoot":"","sources":["../../src/memory/memory-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAG5C;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,cAAc,EAAE,CAAA;IAC3B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,WAAW,CAAQ;gBAEf,SAAS,CAAC,EAAE,SAAS;IAMjC;;OAEG;IACG,KAAK,CACT,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAA;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC9B,GAAG,EAAE,MAAM,EAAE,CAAA;QACb,SAAS,EAAE,MAAM,CAAA;KAClB,GACA,OAAO,CAAC,cAAc,CAAC;IAkC1B;;OAEG;IACG,KAAK,CACT,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QACP,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;QAC5B,GAAG,EAAE,MAAM,EAAE,CAAA;QACb,SAAS,EAAE,MAAM,CAAA;KAClB,GACA,OAAO,CAAC,iBAAiB,CAAC;IA0C7B;;OAEG;IACG,MAAM,CACV,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAA;QACjB,GAAG,EAAE,MAAM,EAAE,CAAA;QACb,SAAS,EAAE,MAAM,CAAA;KAClB,GACA,OAAO,CAAC,IAAI,CAAC;IA8BhB;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE;QAClB,SAAS,EAAE,MAAM,CAAA;QACjB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,GAAG,EAAE,MAAM,EAAE,CAAA;QACb,SAAS,EAAE,MAAM,CAAA;KAClB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAoC9B;;OAEG;IACG,kBAAkB,CACtB,GAAG,EAAE,MAAM,EAAE,EACb,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,EACnC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC;IAwBnB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,iBAAiB;CAG1B"}