@kya-os/mcp 1.5.0 → 1.6.1

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 (92) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/dist/authz/accountability.d.ts +35 -0
  3. package/dist/authz/accountability.d.ts.map +1 -0
  4. package/dist/authz/accountability.js +28 -0
  5. package/dist/authz/accountability.js.map +1 -0
  6. package/dist/authz/adapter.d.ts +47 -0
  7. package/dist/authz/adapter.d.ts.map +1 -0
  8. package/dist/authz/adapter.js +10 -0
  9. package/dist/authz/adapter.js.map +1 -0
  10. package/dist/authz/examples/inmemory-oidc.d.ts +29 -0
  11. package/dist/authz/examples/inmemory-oidc.d.ts.map +1 -0
  12. package/dist/authz/examples/inmemory-oidc.js +68 -0
  13. package/dist/authz/examples/inmemory-oidc.js.map +1 -0
  14. package/dist/authz/index.d.ts +19 -0
  15. package/dist/authz/index.d.ts.map +1 -0
  16. package/dist/authz/index.js +19 -0
  17. package/dist/authz/index.js.map +1 -0
  18. package/dist/authz/oidc/authorize.d.ts +25 -0
  19. package/dist/authz/oidc/authorize.d.ts.map +1 -0
  20. package/dist/authz/oidc/authorize.js +24 -0
  21. package/dist/authz/oidc/authorize.js.map +1 -0
  22. package/dist/authz/oidc/metadata.d.ts +43 -0
  23. package/dist/authz/oidc/metadata.d.ts.map +1 -0
  24. package/dist/authz/oidc/metadata.js +32 -0
  25. package/dist/authz/oidc/metadata.js.map +1 -0
  26. package/dist/authz/oidc/oidc-adapter.d.ts +52 -0
  27. package/dist/authz/oidc/oidc-adapter.d.ts.map +1 -0
  28. package/dist/authz/oidc/oidc-adapter.js +131 -0
  29. package/dist/authz/oidc/oidc-adapter.js.map +1 -0
  30. package/dist/authz/oidc/pkce.d.ts +20 -0
  31. package/dist/authz/oidc/pkce.d.ts.map +1 -0
  32. package/dist/authz/oidc/pkce.js +29 -0
  33. package/dist/authz/oidc/pkce.js.map +1 -0
  34. package/dist/authz/registry.d.ts +29 -0
  35. package/dist/authz/registry.d.ts.map +1 -0
  36. package/dist/authz/registry.js +48 -0
  37. package/dist/authz/registry.js.map +1 -0
  38. package/dist/authz/requirement.d.ts +38 -0
  39. package/dist/authz/requirement.d.ts.map +1 -0
  40. package/dist/authz/requirement.js +45 -0
  41. package/dist/authz/requirement.js.map +1 -0
  42. package/dist/delegation/chain-enforcement.d.ts +86 -0
  43. package/dist/delegation/chain-enforcement.d.ts.map +1 -0
  44. package/dist/delegation/chain-enforcement.js +224 -0
  45. package/dist/delegation/chain-enforcement.js.map +1 -0
  46. package/dist/delegation/holder-binding.d.ts +128 -0
  47. package/dist/delegation/holder-binding.d.ts.map +1 -0
  48. package/dist/delegation/holder-binding.js +175 -0
  49. package/dist/delegation/holder-binding.js.map +1 -0
  50. package/dist/delegation/index.d.ts +2 -0
  51. package/dist/delegation/index.d.ts.map +1 -1
  52. package/dist/delegation/index.js +2 -0
  53. package/dist/delegation/index.js.map +1 -1
  54. package/dist/errors.d.ts +1 -0
  55. package/dist/errors.d.ts.map +1 -1
  56. package/dist/errors.js +1 -0
  57. package/dist/errors.js.map +1 -1
  58. package/dist/index.d.ts +2 -1
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +2 -1
  61. package/dist/index.js.map +1 -1
  62. package/dist/middleware/with-kya-os.d.ts +35 -1
  63. package/dist/middleware/with-kya-os.d.ts.map +1 -1
  64. package/dist/middleware/with-kya-os.js +94 -192
  65. package/dist/middleware/with-kya-os.js.map +1 -1
  66. package/dist/providers/grant-store.d.ts +98 -0
  67. package/dist/providers/grant-store.d.ts.map +1 -0
  68. package/dist/providers/grant-store.js +92 -0
  69. package/dist/providers/grant-store.js.map +1 -0
  70. package/dist/providers/index.d.ts +2 -0
  71. package/dist/providers/index.d.ts.map +1 -1
  72. package/dist/providers/index.js +2 -0
  73. package/dist/providers/index.js.map +1 -1
  74. package/dist/providers/runtime-fetch.d.ts +14 -0
  75. package/dist/providers/runtime-fetch.d.ts.map +1 -1
  76. package/dist/providers/runtime-fetch.js +22 -0
  77. package/dist/providers/runtime-fetch.js.map +1 -1
  78. package/dist/providers/web-crypto.d.ts +35 -0
  79. package/dist/providers/web-crypto.d.ts.map +1 -0
  80. package/dist/providers/web-crypto.js +91 -0
  81. package/dist/providers/web-crypto.js.map +1 -0
  82. package/dist/types/protocol.d.ts +1 -1
  83. package/dist/types/protocol.d.ts.map +1 -1
  84. package/dist/types/protocol.js +1 -1
  85. package/dist/types/protocol.js.map +1 -1
  86. package/package.json +25 -16
  87. package/schemas/README.md +1 -1
  88. package/schemas/delegation-credential.json +2 -2
  89. package/schemas/detached-proof.json +1 -1
  90. package/schemas/handshake-request.json +1 -1
  91. package/schemas/handshake-response.json +1 -1
  92. package/schemas/well-known-mcpi.json +1 -1
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Delegation chain enforcement — framework-agnostic core (E3 · #2888).
3
+ *
4
+ * The leaf→root chain walk, scope-attenuation, audience binding, confused-deputy
5
+ * guard (KYA-OS §11.6), and ancestor-revocation rules, lifted out of the
6
+ * `with-kya-os` middleware closure so the SAME logic runs in every host (MCP
7
+ * middleware, an HTTP PEP, the conformance harness) against one implementation
8
+ * rather than a per-transport fork.
9
+ *
10
+ * Dependencies are injected as ports (interface-first): a per-credential
11
+ * verifier, an optional ancestor resolver, and an optional graph-backed
12
+ * `RevocationChecker`. Nothing here imports a transport or framework.
13
+ */
14
+ import { extractDelegationFromVC, } from "../types/protocol.js";
15
+ import { verifyDelegationAudience } from "./audience-validator.js";
16
+ /** Union of a credential's delegation scopes and its constraint scopes. */
17
+ export function getDelegationScopes(credential) {
18
+ const scopes = new Set();
19
+ for (const scope of credential.credentialSubject.delegation.scopes ?? []) {
20
+ scopes.add(scope);
21
+ }
22
+ for (const scope of credential.credentialSubject.delegation.constraints?.scopes ?? []) {
23
+ scopes.add(scope);
24
+ }
25
+ return Array.from(scopes);
26
+ }
27
+ /**
28
+ * A child re-delegation may only narrow (attenuate) its parent's authority.
29
+ * Enforces flat-scope subset AND crisp-matcher subset (by matcher+resource),
30
+ * failing closed on any widening. Pure; never throws.
31
+ */
32
+ export function validateScopeAttenuation(parentCredential, childCredential) {
33
+ const parentScopes = getDelegationScopes(parentCredential);
34
+ const childScopes = getDelegationScopes(childCredential);
35
+ const childDelegation = childCredential.credentialSubject.delegation;
36
+ // CRISP matcher attenuation: getDelegationScopes does NOT see constraints.crisp.scopes,
37
+ // so a re-delegation could otherwise widen authority by introducing a broad
38
+ // prefix/regex matcher (e.g. resource:"" matches every scope). Require the child's
39
+ // crisp matchers to be a subset of the parent's (by matcher+resource). Fail closed.
40
+ const crispKey = (s) => `${s.matcher}\u0000${s.resource}`;
41
+ const parentCrisp = new Set((parentCredential.credentialSubject.delegation.constraints.crisp?.scopes ?? []).map(crispKey));
42
+ const widenedCrisp = (childDelegation.constraints.crisp?.scopes ?? []).filter((s) => !parentCrisp.has(crispKey(s)));
43
+ if (widenedCrisp.length > 0) {
44
+ return {
45
+ valid: false,
46
+ reason: `Delegation ${childDelegation.id} introduces crisp scope matcher(s) absent from parent ${parentCredential.credentialSubject.delegation.id}: ${widenedCrisp
47
+ .map((s) => `${s.matcher}:${s.resource}`)
48
+ .join(", ")}`,
49
+ };
50
+ }
51
+ if (parentScopes.length === 0) {
52
+ return { valid: true };
53
+ }
54
+ if (childScopes.length === 0) {
55
+ return {
56
+ valid: false,
57
+ reason: `Delegation ${childDelegation.id} omits scopes required to prove attenuation from parent ${parentCredential.credentialSubject.delegation.id}`,
58
+ };
59
+ }
60
+ const parentScopeSet = new Set(parentScopes);
61
+ const widenedScopes = childScopes.filter((scope) => !parentScopeSet.has(scope));
62
+ if (widenedScopes.length > 0) {
63
+ return {
64
+ valid: false,
65
+ reason: `Delegation ${childDelegation.id} widens scopes beyond parent ${parentCredential.credentialSubject.delegation.id}: ${widenedScopes.join(", ")}`,
66
+ };
67
+ }
68
+ return { valid: true };
69
+ }
70
+ /**
71
+ * Validate a delegation credential and (if re-delegated) its full chain:
72
+ * structural shape, per-credential verification, audience binding to the server,
73
+ * the §11.6 re-delegation audience-constraint requirement, parent↔child linkage
74
+ * (parentId + issuerDid==parent.subjectDid), cycle detection, scope attenuation,
75
+ * and — when a {@link RevocationChecker} is supplied — graph-backed ancestor
76
+ * revocation. Never throws on a malformed input; returns `{ valid, reason }`.
77
+ */
78
+ export async function validateDelegationChain(leafCredential, deps, options) {
79
+ // Shape guard (validate* never-throw contract): a structurally malformed leaf
80
+ // returns a { valid, reason } result rather than letting extractDelegationFromVC
81
+ // or the downstream scope check throw. Requires both
82
+ // credentialSubject.delegation AND .constraints (the verifier's own invariant).
83
+ const leafDelegationObj = leafCredential?.credentialSubject?.delegation;
84
+ if (!leafDelegationObj ||
85
+ typeof leafDelegationObj !== "object" ||
86
+ !leafDelegationObj.constraints ||
87
+ typeof leafDelegationObj.constraints !== "object") {
88
+ return {
89
+ valid: false,
90
+ reason: "Malformed delegation credential: missing credentialSubject.delegation or its constraints",
91
+ };
92
+ }
93
+ const leafDelegation = extractDelegationFromVC(leafCredential);
94
+ let chain = [leafCredential];
95
+ if (leafDelegation.parentId) {
96
+ if (!deps.resolveDelegationChain) {
97
+ return {
98
+ valid: false,
99
+ reason: `Delegation ${leafDelegation.id} references parent ${leafDelegation.parentId} but no resolveDelegationChain handler is configured`,
100
+ };
101
+ }
102
+ let resolvedChain;
103
+ try {
104
+ resolvedChain = await deps.resolveDelegationChain(leafCredential);
105
+ }
106
+ catch (error) {
107
+ return {
108
+ valid: false,
109
+ reason: `Failed to resolve delegation chain: ${error instanceof Error ? error.message : "Unknown error"}`,
110
+ };
111
+ }
112
+ if (resolvedChain.length === 0) {
113
+ return {
114
+ valid: false,
115
+ reason: `Delegation ${leafDelegation.id} references parent ${leafDelegation.parentId} but the resolved chain is empty`,
116
+ };
117
+ }
118
+ const leafIndex = resolvedChain.findIndex((credential) => credential.credentialSubject.delegation.id === leafDelegation.id);
119
+ if (leafIndex !== -1 && leafIndex !== resolvedChain.length - 1) {
120
+ return {
121
+ valid: false,
122
+ reason: `Resolved delegation chain for ${leafDelegation.id} must end with the leaf credential`,
123
+ };
124
+ }
125
+ chain = leafIndex === -1 ? [...resolvedChain, leafCredential] : resolvedChain;
126
+ }
127
+ const seenIds = new Set();
128
+ let previousDelegation;
129
+ let previousCredential;
130
+ for (const credential of chain) {
131
+ const delegation = extractDelegationFromVC(credential);
132
+ if (seenIds.has(delegation.id)) {
133
+ return {
134
+ valid: false,
135
+ reason: `Delegation chain contains a circular reference at ${delegation.id}`,
136
+ };
137
+ }
138
+ seenIds.add(delegation.id);
139
+ if (credential.credentialStatus && !deps.statusListConfigured) {
140
+ return {
141
+ valid: false,
142
+ reason: `Delegation ${delegation.id} has credentialStatus but no statusListResolver is configured`,
143
+ };
144
+ }
145
+ const credentialVerification = await deps.verifier.verifyDelegationCredential(credential, {
146
+ ...(options?.skipSignature ? { skipSignature: true } : {}),
147
+ });
148
+ if (!credentialVerification.valid) {
149
+ return {
150
+ valid: false,
151
+ reason: `Delegation ${delegation.id} invalid: ${credentialVerification.reason}`,
152
+ };
153
+ }
154
+ if (!verifyDelegationAudience(delegation, deps.serverDid)) {
155
+ return {
156
+ valid: false,
157
+ reason: `Delegation ${delegation.id} audience does not include server DID ${deps.serverDid}`,
158
+ };
159
+ }
160
+ // Every non-root credential in the chain MUST carry an `audience` constraint
161
+ // binding it to the verifying server. This closes the confused-deputy class
162
+ // where a re-delegated credential is forwarded to an unintended server
163
+ // (KYA-OS §11.6). Unconditional as of 1.4.0.
164
+ if (delegation.parentId && !delegation.constraints.audience) {
165
+ return {
166
+ valid: false,
167
+ reason: `Delegation ${delegation.id} is a re-delegation (parentId: ${delegation.parentId}) but has no audience constraint. Re-delegations MUST include an audience constraint (KYA-OS §11.6)`,
168
+ };
169
+ }
170
+ if (!previousDelegation || !previousCredential) {
171
+ if (delegation.parentId) {
172
+ return {
173
+ valid: false,
174
+ reason: `Resolved delegation chain is incomplete: root delegation ${delegation.id} still references parent ${delegation.parentId}`,
175
+ };
176
+ }
177
+ previousDelegation = delegation;
178
+ previousCredential = credential;
179
+ continue;
180
+ }
181
+ if (delegation.parentId !== previousDelegation.id) {
182
+ return {
183
+ valid: false,
184
+ reason: `Delegation ${delegation.id} references parent ${delegation.parentId} but expected ${previousDelegation.id}`,
185
+ };
186
+ }
187
+ if (delegation.issuerDid !== previousDelegation.subjectDid) {
188
+ return {
189
+ valid: false,
190
+ reason: `Delegation ${delegation.id} issued by ${delegation.issuerDid} but parent subject is ${previousDelegation.subjectDid}`,
191
+ };
192
+ }
193
+ const scopeValidation = validateScopeAttenuation(previousCredential, credential);
194
+ if (!scopeValidation.valid) {
195
+ return scopeValidation;
196
+ }
197
+ previousDelegation = delegation;
198
+ previousCredential = credential;
199
+ }
200
+ const finalDelegation = extractDelegationFromVC(chain[chain.length - 1]);
201
+ if (finalDelegation.id !== leafDelegation.id) {
202
+ return {
203
+ valid: false,
204
+ reason: `Resolved delegation chain ended at ${finalDelegation.id} instead of leaf ${leafDelegation.id}`,
205
+ };
206
+ }
207
+ // E3.1: graph-backed ancestor revocation. Independent of how the chain above
208
+ // was resolved — catches a cascade-revoked ANCESTOR even when the leaf's own
209
+ // credentialStatus bit was never flipped. Opt-in: only runs when a checker is
210
+ // wired, so existing callers are unaffected.
211
+ if (deps.revocationChecker) {
212
+ const revocation = await deps.revocationChecker.isRevoked(leafDelegation.id);
213
+ if (revocation.revoked) {
214
+ return {
215
+ valid: false,
216
+ reason: revocation.revokedAncestor
217
+ ? `Delegation ${leafDelegation.id} is revoked via ancestor ${revocation.revokedAncestor}`
218
+ : `Delegation ${leafDelegation.id} is revoked${revocation.reason ? `: ${revocation.reason}` : ""}`,
219
+ };
220
+ }
221
+ }
222
+ return { valid: true };
223
+ }
224
+ //# sourceMappingURL=chain-enforcement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain-enforcement.js","sourceRoot":"","sources":["../../src/delegation/chain-enforcement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,uBAAuB,GAGxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,2EAA2E;AAC3E,MAAM,UAAU,mBAAmB,CAAC,UAAgC;IAClE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,iBAAiB,CAAC,UAAU,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACzE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,iBAAiB,CAAC,UAAU,CAAC,WAAW,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;QACtF,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,gBAAsC,EACtC,eAAqC;IAErC,MAAM,YAAY,GAAG,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACzD,MAAM,eAAe,GAAG,eAAe,CAAC,iBAAiB,CAAC,UAAU,CAAC;IAErE,wFAAwF;IACxF,4EAA4E;IAC5E,mFAAmF;IACnF,oFAAoF;IACpF,MAAM,QAAQ,GAAG,CAAC,CAAwC,EAAU,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzG,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAC9F,CAAC;IACF,MAAM,YAAY,GAAG,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,MAAM,CAC3E,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CACrC,CAAC;IACF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,cAAc,eAAe,CAAC,EAAE,yDAAyD,gBAAgB,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,KAAK,YAAY;iBAC/J,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;iBACxC,IAAI,CAAC,IAAI,CAAC,EAAE;SAChB,CAAC;IACJ,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,cAAc,eAAe,CAAC,EAAE,2DAA2D,gBAAgB,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,EAAE;SACtJ,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IAC7C,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAChF,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,cAAc,eAAe,CAAC,EAAE,gCAAgC,gBAAgB,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,KAAK,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SACxJ,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC;AAuDD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,cAAoC,EACpC,IAA0B,EAC1B,OAAqC;IAErC,8EAA8E;IAC9E,iFAAiF;IACjF,qDAAqD;IACrD,gFAAgF;IAChF,MAAM,iBAAiB,GACrB,cAAc,EAAE,iBAGjB,EAAE,UAAU,CAAC;IACd,IACE,CAAC,iBAAiB;QAClB,OAAO,iBAAiB,KAAK,QAAQ;QACrC,CAAC,iBAAiB,CAAC,WAAW;QAC9B,OAAO,iBAAiB,CAAC,WAAW,KAAK,QAAQ,EACjD,CAAC;QACD,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EACJ,0FAA0F;SAC7F,CAAC;IACJ,CAAC;IACD,MAAM,cAAc,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAC;IAC/D,IAAI,KAAK,GAA2B,CAAC,cAAc,CAAC,CAAC;IAErD,IAAI,cAAc,CAAC,QAAQ,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACjC,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,cAAc,cAAc,CAAC,EAAE,sBAAsB,cAAc,CAAC,QAAQ,sDAAsD;aAC3I,CAAC;QACJ,CAAC;QAED,IAAI,aAAqC,CAAC;QAC1C,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,cAAc,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,uCAAuC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE;aAC1G,CAAC;QACJ,CAAC;QAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,cAAc,cAAc,CAAC,EAAE,sBAAsB,cAAc,CAAC,QAAQ,kCAAkC;aACvH,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CACvC,CAAC,UAAU,EAAE,EAAE,CACb,UAAU,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,KAAK,cAAc,CAAC,EAAE,CACnE,CAAC;QACF,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,SAAS,KAAK,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/D,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,iCAAiC,cAAc,CAAC,EAAE,oCAAoC;aAC/F,CAAC;QACJ,CAAC;QAED,KAAK,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;IAChF,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,kBAAgD,CAAC;IACrD,IAAI,kBAAoD,CAAC;IAEzD,KAAK,MAAM,UAAU,IAAI,KAAK,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;QAEvD,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC;YAC/B,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,qDAAqD,UAAU,CAAC,EAAE,EAAE;aAC7E,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAE3B,IAAI,UAAU,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC9D,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,cAAc,UAAU,CAAC,EAAE,+DAA+D;aACnG,CAAC;QACJ,CAAC;QAED,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAC3E,UAAU,EACV;YACE,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3D,CACF,CAAC;QACF,IAAI,CAAC,sBAAsB,CAAC,KAAK,EAAE,CAAC;YAClC,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,cAAc,UAAU,CAAC,EAAE,aAAa,sBAAsB,CAAC,MAAM,EAAE;aAChF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,wBAAwB,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1D,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,cAAc,UAAU,CAAC,EAAE,yCAAyC,IAAI,CAAC,SAAS,EAAE;aAC7F,CAAC;QACJ,CAAC;QAED,6EAA6E;QAC7E,4EAA4E;QAC5E,uEAAuE;QACvE,6CAA6C;QAC7C,IAAI,UAAU,CAAC,QAAQ,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;YAC5D,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,cAAc,UAAU,CAAC,EAAE,kCAAkC,UAAU,CAAC,QAAQ,qGAAqG;aAC9L,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,kBAAkB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC/C,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;gBACxB,OAAO;oBACL,KAAK,EAAE,KAAK;oBACZ,MAAM,EAAE,4DAA4D,UAAU,CAAC,EAAE,4BAA4B,UAAU,CAAC,QAAQ,EAAE;iBACnI,CAAC;YACJ,CAAC;YAED,kBAAkB,GAAG,UAAU,CAAC;YAChC,kBAAkB,GAAG,UAAU,CAAC;YAChC,SAAS;QACX,CAAC;QAED,IAAI,UAAU,CAAC,QAAQ,KAAK,kBAAkB,CAAC,EAAE,EAAE,CAAC;YAClD,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,cAAc,UAAU,CAAC,EAAE,sBAAsB,UAAU,CAAC,QAAQ,iBAAiB,kBAAkB,CAAC,EAAE,EAAE;aACrH,CAAC;QACJ,CAAC;QAED,IAAI,UAAU,CAAC,SAAS,KAAK,kBAAkB,CAAC,UAAU,EAAE,CAAC;YAC3D,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,cAAc,UAAU,CAAC,EAAE,cAAc,UAAU,CAAC,SAAS,0BAA0B,kBAAkB,CAAC,UAAU,EAAE;aAC/H,CAAC;QACJ,CAAC;QAED,MAAM,eAAe,GAAG,wBAAwB,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;QACjF,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;YAC3B,OAAO,eAAe,CAAC;QACzB,CAAC;QAED,kBAAkB,GAAG,UAAU,CAAC;QAChC,kBAAkB,GAAG,UAAU,CAAC;IAClC,CAAC;IAED,MAAM,eAAe,GAAG,uBAAuB,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,CAAC;IAC1E,IAAI,eAAe,CAAC,EAAE,KAAK,cAAc,CAAC,EAAE,EAAE,CAAC;QAC7C,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,sCAAsC,eAAe,CAAC,EAAE,oBAAoB,cAAc,CAAC,EAAE,EAAE;SACxG,CAAC;IACJ,CAAC;IAED,6EAA6E;IAC7E,6EAA6E;IAC7E,8EAA8E;IAC9E,6CAA6C;IAC7C,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QAC7E,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,UAAU,CAAC,eAAe;oBAChC,CAAC,CAAC,cAAc,cAAc,CAAC,EAAE,4BAA4B,UAAU,CAAC,eAAe,EAAE;oBACzF,CAAC,CAAC,cAAc,cAAc,CAAC,EAAE,cAAc,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;aACrG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Holder binding — enforce that a request proof is bound to the delegation subject.
3
+ *
4
+ * A delegation credential names a subject DID and grants it authority. On its
5
+ * own that credential is a *bearer* token: anyone who obtains the string can
6
+ * present it. Holder binding closes that gap (spec §11.8 theft-replay residual)
7
+ * by requiring the caller to prove possession of the subject DID's key on the
8
+ * request itself.
9
+ *
10
+ * For a `did:key` subject the proof is exact and needs no new credential fields:
11
+ * the DID *is* the public key, so "the proof verifies against the subject DID's
12
+ * key" is equivalent to "the caller holds the subject's private key". This module
13
+ * derives the subject key straight from the DID and verifies the request proof
14
+ * against it. A proof signed by any other key — a thief replaying a stolen
15
+ * credential — cannot verify and is rejected.
16
+ *
17
+ * `did:web` (and other non-`did:key`) subjects do not encode their key in the
18
+ * DID and may rotate or hold several keys, so phase-1 cannot pin "the" key for
19
+ * them. They are reported {@link HolderBindingStatus | not_applicable} so the
20
+ * caller can defer them to cnf-based binding (phase 2) instead of rejecting
21
+ * legitimate traffic. Callers MUST surface that gap (e.g. log it) rather than
22
+ * treat `not_applicable` as success.
23
+ */
24
+ import type { ProofVerifier } from '../proof/verifier.js';
25
+ import type { ToolRequest, ToolResponse, ProofAgentIdentity } from '../proof/generator.js';
26
+ import type { DetachedProof } from '../types/protocol.js';
27
+ import type { CryptoProvider } from '../providers/base.js';
28
+ /**
29
+ * Whether an argument key is reserved KYA-OS protocol envelope (`_kyaos*`:
30
+ * `_kyaos_delegation`, `_kyaos_proof`, `_kyaos_approvals`, …) rather than caller
31
+ * tool intent. The SINGLE predicate behind both the holder-binding request hash
32
+ * and the middleware's handler-arg stripping, so the set excluded from the bound
33
+ * hash and the set withheld from the handler cannot drift — a proof binds exactly
34
+ * the call the handler runs.
35
+ */
36
+ export declare function isKyaOsControlArg(key: string): boolean;
37
+ /**
38
+ * The canonical request a holder-binding proof binds: the tool name plus the
39
+ * caller's business arguments, with protocol control args stripped. SHARED by
40
+ * the client (when minting the proof) and the PEP (when verifying it) so the two
41
+ * cannot drift — the request hash is computed over the identical shape on both
42
+ * sides regardless of which control args rode along.
43
+ */
44
+ export declare function toHolderBindingRequest(toolName: string, args: Record<string, unknown>): ToolRequest;
45
+ export interface GenerateRequestProofInput {
46
+ /** The agent (delegation subject) identity holding the signing key. */
47
+ identity: ProofAgentIdentity;
48
+ /** Crypto provider used to sign and to mint the per-request nonce. */
49
+ crypto: CryptoProvider;
50
+ /** The tool being called. */
51
+ toolName: string;
52
+ /** The tool arguments (control args are stripped before binding). */
53
+ args: Record<string, unknown>;
54
+ /** The server DID the call is addressed to. */
55
+ audience: string;
56
+ /** The handshake session id, when one exists. */
57
+ sessionId?: string;
58
+ }
59
+ /**
60
+ * Mint the `_kyaos_proof` a key-bearing agent attaches to an outbound tool call
61
+ * — the client half of holder binding. It is a request-only detached proof (no
62
+ * response yet) signed by the agent's key over {@link toHolderBindingRequest}.
63
+ * A fresh nonce is generated per call so the PEP's replay cache rejects reuse.
64
+ */
65
+ export declare function generateRequestProof(input: GenerateRequestProofInput): Promise<DetachedProof>;
66
+ /**
67
+ * Stable, client-facing error code for a failed holder binding. Distinct from
68
+ * the verifier's granular codes (which are kept in {@link HolderBindingResult.cause}
69
+ * for server-side diagnosis) so a binding failure presents one reason to callers
70
+ * and never leaks why the proof was rejected.
71
+ */
72
+ export declare const HOLDER_BINDING_ERROR = "holder_binding_failed";
73
+ /**
74
+ * - `bound` — subject is a did:key and the proof verifies against its key: the
75
+ * caller is the holder. Allow.
76
+ * - `unbound` — subject is a did:key but the proof failed (wrong key, tampered
77
+ * request, stale, or replayed). Reject — this is the theft-replay closure.
78
+ * - `not_applicable` — subject is not a did:key, so phase-1 cannot bind it.
79
+ * Defer to cnf-based binding (phase 2); the caller decides how to treat it.
80
+ */
81
+ export type HolderBindingStatus = 'bound' | 'unbound' | 'not_applicable';
82
+ /**
83
+ * Whether phase-1 holder binding can bind this subject. True only for did:key
84
+ * (the DID encodes the key). The PEP uses this to decide between *enforcing* a
85
+ * proof (did:key) and *deferring* to cnf binding (did:web and others), so it
86
+ * never rejects legitimate traffic it cannot yet bind.
87
+ */
88
+ export declare function isHolderBindingApplicable(subjectDid: string): boolean;
89
+ export interface AssertHolderBindingInput {
90
+ /** The per-request detached proof presented by the caller. */
91
+ proof: DetachedProof;
92
+ /** The delegation subject DID the proof must be bound to. */
93
+ subjectDid: string;
94
+ /** The request the proof must bind (content binding). */
95
+ request: ToolRequest;
96
+ /**
97
+ * The response the proof binds, when the proof carries one. Inbound request
98
+ * proofs are request-only and omit this.
99
+ */
100
+ response?: ToolResponse;
101
+ /**
102
+ * The audience the proof must be addressed to — the recipient server's DID
103
+ * (RFC 8707 "to-whom" binding). When set, `proof.meta.audience` must equal it
104
+ * (or be one of the array, for DID rotation / multi-DID servers); a proof
105
+ * minted for another server is rejected, closing confused-deputy replay across
106
+ * servers. Omit to skip the audience check (back-compatible).
107
+ */
108
+ expectedAudience?: string | string[];
109
+ /** The existing verifier — supplies signature, nonce, timestamp and content checks. */
110
+ proofVerifier: ProofVerifier;
111
+ }
112
+ export interface HolderBindingResult {
113
+ status: HolderBindingStatus;
114
+ /** Human-readable explanation (present whenever status is not `bound`). */
115
+ reason?: string;
116
+ /** {@link HOLDER_BINDING_ERROR} when status is `unbound`. */
117
+ errorCode?: typeof HOLDER_BINDING_ERROR;
118
+ /** Underlying verifier error code, for server-side diagnosis only. */
119
+ cause?: string;
120
+ }
121
+ /**
122
+ * Assert that `proof` is a holder-of-key proof for `subjectDid` over `request`.
123
+ *
124
+ * @see module documentation for the did:key / did:web split and the security
125
+ * property each branch enforces.
126
+ */
127
+ export declare function assertHolderBinding(input: AssertHolderBindingInput): Promise<HolderBindingResult>;
128
+ //# sourceMappingURL=holder-binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"holder-binding.d.ts","sourceRoot":"","sources":["../../src/delegation/holder-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAU3D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,WAAW,CAMb;AAED,MAAM,WAAW,yBAAyB;IACxC,uEAAuE;IACvE,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,sEAAsE;IACtE,MAAM,EAAE,cAAc,CAAC;IACvB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,aAAa,CAAC,CAgBxB;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,0BAA0B,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,SAAS,GAAG,gBAAgB,CAAC;AAEzE;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAErE;AAED,MAAM,WAAW,wBAAwB;IACvC,8DAA8D;IAC9D,KAAK,EAAE,aAAa,CAAC;IACrB,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,OAAO,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACrC,uFAAuF;IACvF,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,OAAO,oBAAoB,CAAC;IACxC,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,mBAAmB,CAAC,CA4E9B"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Holder binding — enforce that a request proof is bound to the delegation subject.
3
+ *
4
+ * A delegation credential names a subject DID and grants it authority. On its
5
+ * own that credential is a *bearer* token: anyone who obtains the string can
6
+ * present it. Holder binding closes that gap (spec §11.8 theft-replay residual)
7
+ * by requiring the caller to prove possession of the subject DID's key on the
8
+ * request itself.
9
+ *
10
+ * For a `did:key` subject the proof is exact and needs no new credential fields:
11
+ * the DID *is* the public key, so "the proof verifies against the subject DID's
12
+ * key" is equivalent to "the caller holds the subject's private key". This module
13
+ * derives the subject key straight from the DID and verifies the request proof
14
+ * against it. A proof signed by any other key — a thief replaying a stolen
15
+ * credential — cannot verify and is rejected.
16
+ *
17
+ * `did:web` (and other non-`did:key`) subjects do not encode their key in the
18
+ * DID and may rotate or hold several keys, so phase-1 cannot pin "the" key for
19
+ * them. They are reported {@link HolderBindingStatus | not_applicable} so the
20
+ * caller can defer them to cnf-based binding (phase 2) instead of rejecting
21
+ * legitimate traffic. Callers MUST surface that gap (e.g. log it) rather than
22
+ * treat `not_applicable` as success.
23
+ */
24
+ import { extractPublicKeyFromDidKey, publicKeyToJwk } from './did-key-resolver.js';
25
+ import { getDidMethod, didKeyFragment } from '../utils/did-helpers.js';
26
+ import { ProofGenerator } from '../proof/generator.js';
27
+ import { base64urlEncodeFromBytes } from '../utils/base64.js';
28
+ /**
29
+ * The control-arg key prefix. Args beginning with this are protocol envelope
30
+ * (`_kyaos_delegation`, `_kyaos_proof`, `_kyaos_approvals`), not the caller's
31
+ * tool intent, so they are excluded from the holder-binding request hash.
32
+ */
33
+ const KYAOS_CONTROL_PREFIX = '_kyaos';
34
+ /**
35
+ * Whether an argument key is reserved KYA-OS protocol envelope (`_kyaos*`:
36
+ * `_kyaos_delegation`, `_kyaos_proof`, `_kyaos_approvals`, …) rather than caller
37
+ * tool intent. The SINGLE predicate behind both the holder-binding request hash
38
+ * and the middleware's handler-arg stripping, so the set excluded from the bound
39
+ * hash and the set withheld from the handler cannot drift — a proof binds exactly
40
+ * the call the handler runs.
41
+ */
42
+ export function isKyaOsControlArg(key) {
43
+ return key.startsWith(KYAOS_CONTROL_PREFIX);
44
+ }
45
+ /**
46
+ * The canonical request a holder-binding proof binds: the tool name plus the
47
+ * caller's business arguments, with protocol control args stripped. SHARED by
48
+ * the client (when minting the proof) and the PEP (when verifying it) so the two
49
+ * cannot drift — the request hash is computed over the identical shape on both
50
+ * sides regardless of which control args rode along.
51
+ */
52
+ export function toHolderBindingRequest(toolName, args) {
53
+ const params = {};
54
+ for (const [k, v] of Object.entries(args)) {
55
+ if (!isKyaOsControlArg(k))
56
+ params[k] = v;
57
+ }
58
+ return { method: toolName, params };
59
+ }
60
+ /**
61
+ * Mint the `_kyaos_proof` a key-bearing agent attaches to an outbound tool call
62
+ * — the client half of holder binding. It is a request-only detached proof (no
63
+ * response yet) signed by the agent's key over {@link toHolderBindingRequest}.
64
+ * A fresh nonce is generated per call so the PEP's replay cache rejects reuse.
65
+ */
66
+ export async function generateRequestProof(input) {
67
+ const { identity, crypto, toolName, args, audience, sessionId } = input;
68
+ const generator = new ProofGenerator(identity, crypto);
69
+ const request = toHolderBindingRequest(toolName, args);
70
+ const nonce = base64urlEncodeFromBytes(await crypto.randomBytes(16));
71
+ const now = Math.floor(Date.now() / 1000);
72
+ return generator.generateProof(request, undefined, {
73
+ sessionId: sessionId ?? '',
74
+ audience,
75
+ nonce,
76
+ timestamp: now,
77
+ createdAt: now,
78
+ lastActivity: now,
79
+ ttlMinutes: 30,
80
+ identityState: 'anonymous',
81
+ });
82
+ }
83
+ /**
84
+ * Stable, client-facing error code for a failed holder binding. Distinct from
85
+ * the verifier's granular codes (which are kept in {@link HolderBindingResult.cause}
86
+ * for server-side diagnosis) so a binding failure presents one reason to callers
87
+ * and never leaks why the proof was rejected.
88
+ */
89
+ export const HOLDER_BINDING_ERROR = 'holder_binding_failed';
90
+ /**
91
+ * Whether phase-1 holder binding can bind this subject. True only for did:key
92
+ * (the DID encodes the key). The PEP uses this to decide between *enforcing* a
93
+ * proof (did:key) and *deferring* to cnf binding (did:web and others), so it
94
+ * never rejects legitimate traffic it cannot yet bind.
95
+ */
96
+ export function isHolderBindingApplicable(subjectDid) {
97
+ return extractPublicKeyFromDidKey(subjectDid) !== null;
98
+ }
99
+ /**
100
+ * Assert that `proof` is a holder-of-key proof for `subjectDid` over `request`.
101
+ *
102
+ * @see module documentation for the did:key / did:web split and the security
103
+ * property each branch enforces.
104
+ */
105
+ export async function assertHolderBinding(input) {
106
+ const { proof, subjectDid, request, response, expectedAudience, proofVerifier } = input;
107
+ // Phase-1 scope: did:key subjects only — the DID encodes the key, so holding
108
+ // the key is being the subject. Anything else is deferred to cnf binding.
109
+ const subjectKeyBytes = extractPublicKeyFromDidKey(subjectDid);
110
+ if (!subjectKeyBytes) {
111
+ return {
112
+ status: 'not_applicable',
113
+ reason: `Holder binding (phase 1) covers did:key subjects only; ` +
114
+ `"${getDidMethod(subjectDid) ?? 'unknown'}" is deferred to cnf-based binding`,
115
+ };
116
+ }
117
+ // Fail closed on a structurally malformed proof (e.g. the {} a caller
118
+ // substitutes when a string proof fails to parse) — never throw out of the
119
+ // gate, which would surface as an internal error instead of a binding failure.
120
+ if (typeof proof?.meta !== 'object' || proof.meta === null) {
121
+ return {
122
+ status: 'unbound',
123
+ errorCode: HOLDER_BINDING_ERROR,
124
+ reason: 'Malformed proof: missing meta',
125
+ };
126
+ }
127
+ // Pre-crypto consistency: the proof must self-declare the delegation subject.
128
+ // Cheap, and gives a precise reason before the signature check.
129
+ if (proof.meta.did !== subjectDid) {
130
+ return {
131
+ status: 'unbound',
132
+ errorCode: HOLDER_BINDING_ERROR,
133
+ reason: 'Proof subject does not match the delegation subject',
134
+ };
135
+ }
136
+ // Audience binding (RFC 8707): the proof must be addressed to THIS server. A
137
+ // proof minted for another server cannot be replayed here. Checked before the
138
+ // signature so a misdirected proof fails fast without burning its nonce.
139
+ if (expectedAudience !== undefined) {
140
+ const allowed = Array.isArray(expectedAudience) ? expectedAudience : [expectedAudience];
141
+ if (!allowed.includes(proof.meta.audience)) {
142
+ return {
143
+ status: 'unbound',
144
+ errorCode: HOLDER_BINDING_ERROR,
145
+ reason: 'Proof audience does not match this server',
146
+ cause: 'audience_mismatch',
147
+ };
148
+ }
149
+ }
150
+ // The binding itself: verify the proof against the SUBJECT DID's key. The
151
+ // verifier reconstructs the signed payload from proof.meta (sub/iss = subject),
152
+ // so a proof signed by any other key cannot verify here — defeating a
153
+ // stolen-credential replay — and a tampered request fails content binding.
154
+ // Tag the key with the subject's canonical did:key verification-method id.
155
+ // The verifier's kid check (publicKeyJwk.kid === proof.meta.kid) then enforces
156
+ // that the proof's kid is the subject's verification method — a proof citing
157
+ // any other kid is rejected before the signature is even checked. The key
158
+ // material (x) still comes from the DID, so the signature is the real binding.
159
+ const subjectKey = publicKeyToJwk(subjectKeyBytes);
160
+ subjectKey.kid = `${subjectDid}#${didKeyFragment(subjectDid)}`;
161
+ const verification = await proofVerifier.verifyProof(proof, subjectKey, {
162
+ request,
163
+ ...(response !== undefined ? { response } : {}),
164
+ });
165
+ if (!verification.valid) {
166
+ return {
167
+ status: 'unbound',
168
+ errorCode: HOLDER_BINDING_ERROR,
169
+ reason: 'Request proof is not bound to the delegation subject',
170
+ ...(verification.errorCode !== undefined ? { cause: verification.errorCode } : {}),
171
+ };
172
+ }
173
+ return { status: 'bound' };
174
+ }
175
+ //# sourceMappingURL=holder-binding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"holder-binding.js","sourceRoot":"","sources":["../../src/delegation/holder-binding.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,8 @@ export * from './outbound-proof.js';
15
15
  export * from './outbound-headers.js';
16
16
  export * from './audience-validator.js';
17
17
  export * from './scope-matcher.js';
18
+ export * from './holder-binding.js';
19
+ export * from './chain-enforcement.js';
18
20
  export { createDidKeyResolver, resolveDidKeySync, isEd25519DidKey, extractPublicKeyFromDidKey, publicKeyToJwk, } from './did-key-resolver.js';
19
21
  export { DidWebResolver, createDidWebResolver, isDidWeb, parseDidWeb, didWebToUrl, buildDidWebDocument, } from './did-web-resolver.js';
20
22
  export { MemoryStatusListStorage } from './storage/memory-statuslist-storage.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/delegation/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACX,WAAW,EACX,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/delegation/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACX,WAAW,EACX,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC"}
@@ -15,6 +15,8 @@ export * from './outbound-proof.js';
15
15
  export * from './outbound-headers.js';
16
16
  export * from './audience-validator.js';
17
17
  export * from './scope-matcher.js';
18
+ export * from './holder-binding.js';
19
+ export * from './chain-enforcement.js';
18
20
  export { createDidKeyResolver, resolveDidKeySync, isEd25519DidKey, extractPublicKeyFromDidKey, publicKeyToJwk, } from './did-key-resolver.js';
19
21
  export { DidWebResolver, createDidWebResolver, isDidWeb, parseDidWeb, didWebToUrl, buildDidWebDocument, } from './did-web-resolver.js';
20
22
  export { MemoryStatusListStorage } from './storage/memory-statuslist-storage.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/delegation/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACX,WAAW,EACX,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/delegation/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACX,WAAW,EACX,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -24,6 +24,7 @@ export declare const KYA_OS_ERROR_CODES: {
24
24
  readonly delegation_not_yet_valid: "delegation_not_yet_valid";
25
25
  readonly delegation_revoked: "delegation_revoked";
26
26
  readonly delegation_invalid: "delegation_invalid";
27
+ readonly holder_binding_failed: "holder_binding_failed";
27
28
  readonly budget_exceeded: "budget_exceeded";
28
29
  readonly rate_limit_exceeded: "rate_limit_exceeded";
29
30
  readonly invalid_token: "invalid_token";
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;CAsCrB,CAAC;AAEX,MAAM,MAAM,cAAc,GACxB,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC;AAE/D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,kBAAkB,CAEpB"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCrB,CAAC;AAEX,MAAM,MAAM,cAAc,GACxB,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC;AAE/D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,kBAAkB,CAEpB"}
package/dist/errors.js CHANGED
@@ -28,6 +28,7 @@ export const KYA_OS_ERROR_CODES = {
28
28
  delegation_not_yet_valid: "delegation_not_yet_valid",
29
29
  delegation_revoked: "delegation_revoked",
30
30
  delegation_invalid: "delegation_invalid",
31
+ holder_binding_failed: "holder_binding_failed",
31
32
  budget_exceeded: "budget_exceeded",
32
33
  rate_limit_exceeded: "rate_limit_exceeded",
33
34
  // Token errors
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,eAAe;IACf,aAAa,EAAE,eAAe;IAC9B,WAAW,EAAE,aAAa;IAC1B,YAAY,EAAE,cAAc;IAC5B,cAAc,EAAE,gBAAgB;IAEhC,wBAAwB;IACxB,aAAa,EAAE,eAAe;IAC9B,kBAAkB,EAAE,oBAAoB;IAExC,6BAA6B;IAC7B,gBAAgB,EAAE,kBAAkB;IACpC,eAAe,EAAE,iBAAiB;IAClC,eAAe,EAAE,iBAAiB;IAElC,oBAAoB;IACpB,mBAAmB,EAAE,qBAAqB;IAC1C,kBAAkB,EAAE,oBAAoB;IACxC,aAAa,EAAE,eAAe;IAC9B,kBAAkB,EAAE,oBAAoB;IACxC,wBAAwB,EAAE,0BAA0B;IACpD,kBAAkB,EAAE,oBAAoB;IACxC,kBAAkB,EAAE,oBAAoB;IACxC,eAAe,EAAE,iBAAiB;IAClC,mBAAmB,EAAE,qBAAqB;IAE1C,eAAe;IACf,aAAa,EAAE,eAAe;IAC9B,aAAa,EAAE,eAAe;IAE9B,kBAAkB;IAClB,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,cAAc;IAE5B,gBAAgB;IAChB,mBAAmB,EAAE,qBAAqB;IAC1C,aAAa,EAAE,eAAe;CACtB,CAAC;AAWX,MAAM,UAAU,gBAAgB,CAC9B,IAAoB,EACpB,OAAe,EACf,OAAiC;IAEjC,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,eAAe;IACf,aAAa,EAAE,eAAe;IAC9B,WAAW,EAAE,aAAa;IAC1B,YAAY,EAAE,cAAc;IAC5B,cAAc,EAAE,gBAAgB;IAEhC,wBAAwB;IACxB,aAAa,EAAE,eAAe;IAC9B,kBAAkB,EAAE,oBAAoB;IAExC,6BAA6B;IAC7B,gBAAgB,EAAE,kBAAkB;IACpC,eAAe,EAAE,iBAAiB;IAClC,eAAe,EAAE,iBAAiB;IAElC,oBAAoB;IACpB,mBAAmB,EAAE,qBAAqB;IAC1C,kBAAkB,EAAE,oBAAoB;IACxC,aAAa,EAAE,eAAe;IAC9B,kBAAkB,EAAE,oBAAoB;IACxC,wBAAwB,EAAE,0BAA0B;IACpD,kBAAkB,EAAE,oBAAoB;IACxC,kBAAkB,EAAE,oBAAoB;IACxC,qBAAqB,EAAE,uBAAuB;IAC9C,eAAe,EAAE,iBAAiB;IAClC,mBAAmB,EAAE,qBAAqB;IAE1C,eAAe;IACf,aAAa,EAAE,eAAe;IAC9B,aAAa,EAAE,eAAe;IAE9B,kBAAkB;IAClB,cAAc,EAAE,gBAAgB;IAChC,YAAY,EAAE,cAAc;IAE5B,gBAAgB;IAChB,mBAAmB,EAAE,qBAAqB;IAC1C,aAAa,EAAE,eAAe;CACtB,CAAC;AAWX,MAAM,UAAU,gBAAgB,CAC9B,IAAoB,EACpB,OAAe,EACf,OAAiC;IAEjC,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAClE,CAAC"}
package/dist/index.d.ts CHANGED
@@ -28,6 +28,7 @@ export { verifyDelegationAudience, } from './delegation/audience-validator.js';
28
28
  export { buildDelegationProofJWT, buildChainString, type DelegationProofOptions, type Ed25519PrivateJWK, } from './delegation/outbound-proof.js';
29
29
  export { buildOutboundDelegationHeaders, OUTBOUND_HEADER_NAMES, type OutboundDelegationContext, type OutboundDelegationHeaders, } from './delegation/outbound-headers.js';
30
30
  export { canonicalizeJSON, createUnsignedVCJWT, completeVCJWT, parseVCJWT, type VCJWTHeader, type VCJWTPayload, } from './delegation/utils.js';
31
+ export { assertHolderBinding, generateRequestProof, toHolderBindingRequest, isHolderBindingApplicable, isKyaOsControlArg, HOLDER_BINDING_ERROR, type AssertHolderBindingInput, type GenerateRequestProofInput, type HolderBindingResult, type HolderBindingStatus, } from './delegation/holder-binding.js';
31
32
  export { MemoryStatusListStorage } from './delegation/storage/memory-statuslist-storage.js';
32
33
  export { MemoryDelegationGraphStorage } from './delegation/storage/memory-graph-storage.js';
33
34
  export { createDidKeyResolver, resolveDidKeySync, isEd25519DidKey, extractPublicKeyFromDidKey, publicKeyToJwk, } from './delegation/did-key-resolver.js';
@@ -43,7 +44,7 @@ export { CryptoProvider, ClockProvider, FetchProvider, StorageProvider, NonceCac
43
44
  export { MemoryStorageProvider, MemoryNonceCacheProvider, MemoryIdentityProvider, } from './providers/memory.js';
44
45
  export { NodeCryptoProvider } from './providers/node-crypto.js';
45
46
  export { SystemClockProvider } from './providers/system-clock.js';
46
- export { RuntimeFetchProvider } from './providers/runtime-fetch.js';
47
+ export { RuntimeFetchProvider, NoopFetchProvider } from './providers/runtime-fetch.js';
47
48
  export { AuditLogProvider, MemoryAuditLogProvider, NoopAuditLogProvider, buildAuditRecord, } from './providers/audit-log.js';
48
49
  export { createKyaOsMiddleware, type KyaOsConfig, type KyaOsDelegationConfig, type KyaOsIdentityConfig, type KyaOsMiddleware, type KyaOsToolDefinition, type KyaOsToolHandler, type KyaOsServer, withKyaOs, generateIdentity, type WithKyaOsOptions, } from './middleware/index.js';
49
50
  export * from './policy/index.js';