@kya-os/mcp 1.6.1 → 1.9.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 (282) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/README.md +228 -3
  3. package/dist/authz/index.d.ts +1 -0
  4. package/dist/authz/index.d.ts.map +1 -1
  5. package/dist/authz/index.js +1 -0
  6. package/dist/authz/index.js.map +1 -1
  7. package/dist/authz/oidc/oidc-adapter.d.ts +10 -2
  8. package/dist/authz/oidc/oidc-adapter.d.ts.map +1 -1
  9. package/dist/authz/oidc/oidc-adapter.js +18 -9
  10. package/dist/authz/oidc/oidc-adapter.js.map +1 -1
  11. package/dist/authz/oidc/pending-flow-store.d.ts +80 -0
  12. package/dist/authz/oidc/pending-flow-store.d.ts.map +1 -0
  13. package/dist/authz/oidc/pending-flow-store.js +82 -0
  14. package/dist/authz/oidc/pending-flow-store.js.map +1 -0
  15. package/dist/card/build.d.ts +41 -0
  16. package/dist/card/build.d.ts.map +1 -0
  17. package/dist/card/build.js +47 -0
  18. package/dist/card/build.js.map +1 -0
  19. package/dist/card/builder.d.ts +99 -0
  20. package/dist/card/builder.d.ts.map +1 -0
  21. package/dist/card/builder.js +147 -0
  22. package/dist/card/builder.js.map +1 -0
  23. package/dist/card/cimd.d.ts +92 -0
  24. package/dist/card/cimd.d.ts.map +1 -0
  25. package/dist/card/cimd.js +225 -0
  26. package/dist/card/cimd.js.map +1 -0
  27. package/dist/card/delegation.d.ts +145 -0
  28. package/dist/card/delegation.d.ts.map +1 -0
  29. package/dist/card/delegation.js +293 -0
  30. package/dist/card/delegation.js.map +1 -0
  31. package/dist/card/emit.d.ts +133 -0
  32. package/dist/card/emit.d.ts.map +1 -0
  33. package/dist/card/emit.js +127 -0
  34. package/dist/card/emit.js.map +1 -0
  35. package/dist/card/index.d.ts +43 -0
  36. package/dist/card/index.d.ts.map +1 -0
  37. package/dist/card/index.js +46 -0
  38. package/dist/card/index.js.map +1 -0
  39. package/dist/card/middleware.d.ts +112 -0
  40. package/dist/card/middleware.d.ts.map +1 -0
  41. package/dist/card/middleware.js +121 -0
  42. package/dist/card/middleware.js.map +1 -0
  43. package/dist/card/proof/build.d.ts +22 -0
  44. package/dist/card/proof/build.d.ts.map +1 -0
  45. package/dist/card/proof/build.js +55 -0
  46. package/dist/card/proof/build.js.map +1 -0
  47. package/dist/card/proof/canonical.d.ts +66 -0
  48. package/dist/card/proof/canonical.d.ts.map +1 -0
  49. package/dist/card/proof/canonical.js +131 -0
  50. package/dist/card/proof/canonical.js.map +1 -0
  51. package/dist/card/proof/http-sig.d.ts +69 -0
  52. package/dist/card/proof/http-sig.d.ts.map +1 -0
  53. package/dist/card/proof/http-sig.js +101 -0
  54. package/dist/card/proof/http-sig.js.map +1 -0
  55. package/dist/card/proof/index.d.ts +25 -0
  56. package/dist/card/proof/index.d.ts.map +1 -0
  57. package/dist/card/proof/index.js +25 -0
  58. package/dist/card/proof/index.js.map +1 -0
  59. package/dist/card/proof/nonce-cache.d.ts +67 -0
  60. package/dist/card/proof/nonce-cache.d.ts.map +1 -0
  61. package/dist/card/proof/nonce-cache.js +88 -0
  62. package/dist/card/proof/nonce-cache.js.map +1 -0
  63. package/dist/card/proof/signer.d.ts +32 -0
  64. package/dist/card/proof/signer.d.ts.map +1 -0
  65. package/dist/card/proof/signer.js +59 -0
  66. package/dist/card/proof/signer.js.map +1 -0
  67. package/dist/card/proof/types.d.ts +219 -0
  68. package/dist/card/proof/types.d.ts.map +1 -0
  69. package/dist/card/proof/types.js +87 -0
  70. package/dist/card/proof/types.js.map +1 -0
  71. package/dist/card/proof/verify.d.ts +27 -0
  72. package/dist/card/proof/verify.d.ts.map +1 -0
  73. package/dist/card/proof/verify.js +236 -0
  74. package/dist/card/proof/verify.js.map +1 -0
  75. package/dist/card/resolve.d.ts +97 -0
  76. package/dist/card/resolve.d.ts.map +1 -0
  77. package/dist/card/resolve.js +223 -0
  78. package/dist/card/resolve.js.map +1 -0
  79. package/dist/card/revocation.d.ts +96 -0
  80. package/dist/card/revocation.d.ts.map +1 -0
  81. package/dist/card/revocation.js +190 -0
  82. package/dist/card/revocation.js.map +1 -0
  83. package/dist/card/schema.d.ts +177 -0
  84. package/dist/card/schema.d.ts.map +1 -0
  85. package/dist/card/schema.js +119 -0
  86. package/dist/card/schema.js.map +1 -0
  87. package/dist/card/verify.d.ts +144 -0
  88. package/dist/card/verify.d.ts.map +1 -0
  89. package/dist/card/verify.js +132 -0
  90. package/dist/card/verify.js.map +1 -0
  91. package/dist/delegation/bitstring.d.ts +9 -7
  92. package/dist/delegation/bitstring.d.ts.map +1 -1
  93. package/dist/delegation/bitstring.js +70 -37
  94. package/dist/delegation/bitstring.js.map +1 -1
  95. package/dist/delegation/did-linkage.d.ts +23 -0
  96. package/dist/delegation/did-linkage.d.ts.map +1 -0
  97. package/dist/delegation/did-linkage.js +57 -0
  98. package/dist/delegation/did-linkage.js.map +1 -0
  99. package/dist/delegation/did-resolver-registry.d.ts +7 -0
  100. package/dist/delegation/did-resolver-registry.d.ts.map +1 -0
  101. package/dist/delegation/did-resolver-registry.js +20 -0
  102. package/dist/delegation/did-resolver-registry.js.map +1 -0
  103. package/dist/delegation/did-web-resolver.d.ts +29 -18
  104. package/dist/delegation/did-web-resolver.d.ts.map +1 -1
  105. package/dist/delegation/did-web-resolver.js +65 -35
  106. package/dist/delegation/did-web-resolver.js.map +1 -1
  107. package/dist/delegation/index.d.ts +3 -0
  108. package/dist/delegation/index.d.ts.map +1 -1
  109. package/dist/delegation/index.js +3 -0
  110. package/dist/delegation/index.js.map +1 -1
  111. package/dist/delegation/statuslist-manager.d.ts.map +1 -1
  112. package/dist/delegation/statuslist-manager.js +16 -1
  113. package/dist/delegation/statuslist-manager.js.map +1 -1
  114. package/dist/delegation/vc-jwt-verify.d.ts +61 -0
  115. package/dist/delegation/vc-jwt-verify.d.ts.map +1 -0
  116. package/dist/delegation/vc-jwt-verify.js +131 -0
  117. package/dist/delegation/vc-jwt-verify.js.map +1 -0
  118. package/dist/delegation/vc-verification-checks.d.ts +50 -0
  119. package/dist/delegation/vc-verification-checks.d.ts.map +1 -0
  120. package/dist/delegation/vc-verification-checks.js +212 -0
  121. package/dist/delegation/vc-verification-checks.js.map +1 -0
  122. package/dist/delegation/vc-verifier.d.ts +24 -61
  123. package/dist/delegation/vc-verifier.d.ts.map +1 -1
  124. package/dist/delegation/vc-verifier.js +57 -180
  125. package/dist/delegation/vc-verifier.js.map +1 -1
  126. package/dist/delegation/vc-verifier.types.d.ts +88 -0
  127. package/dist/delegation/vc-verifier.types.d.ts.map +1 -0
  128. package/dist/delegation/vc-verifier.types.js +9 -0
  129. package/dist/delegation/vc-verifier.types.js.map +1 -0
  130. package/dist/index.d.ts +8 -4
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +10 -3
  133. package/dist/index.js.map +1 -1
  134. package/dist/integrations/cheqd/dlr.d.ts +44 -0
  135. package/dist/integrations/cheqd/dlr.d.ts.map +1 -0
  136. package/dist/integrations/cheqd/dlr.js +86 -0
  137. package/dist/integrations/cheqd/dlr.js.map +1 -0
  138. package/dist/integrations/cheqd/index.d.ts +5 -0
  139. package/dist/integrations/cheqd/index.d.ts.map +1 -0
  140. package/dist/integrations/cheqd/index.js +5 -0
  141. package/dist/integrations/cheqd/index.js.map +1 -0
  142. package/dist/integrations/cheqd/linkage.d.ts +20 -0
  143. package/dist/integrations/cheqd/linkage.d.ts.map +1 -0
  144. package/dist/integrations/cheqd/linkage.js +32 -0
  145. package/dist/integrations/cheqd/linkage.js.map +1 -0
  146. package/dist/integrations/cheqd/registrar.d.ts +85 -0
  147. package/dist/integrations/cheqd/registrar.d.ts.map +1 -0
  148. package/dist/integrations/cheqd/registrar.js +304 -0
  149. package/dist/integrations/cheqd/registrar.js.map +1 -0
  150. package/dist/integrations/cheqd/resolver.d.ts +38 -0
  151. package/dist/integrations/cheqd/resolver.d.ts.map +1 -0
  152. package/dist/integrations/cheqd/resolver.js +156 -0
  153. package/dist/integrations/cheqd/resolver.js.map +1 -0
  154. package/dist/middleware/index.d.ts +2 -0
  155. package/dist/middleware/index.d.ts.map +1 -1
  156. package/dist/middleware/index.js +5 -0
  157. package/dist/middleware/index.js.map +1 -1
  158. package/dist/middleware/kya-os-transport.d.ts +2 -1
  159. package/dist/middleware/kya-os-transport.d.ts.map +1 -1
  160. package/dist/middleware/kya-os-transport.js +2 -1
  161. package/dist/middleware/kya-os-transport.js.map +1 -1
  162. package/dist/middleware/with-kya-os-server.d.ts +21 -4
  163. package/dist/middleware/with-kya-os-server.d.ts.map +1 -1
  164. package/dist/middleware/with-kya-os-server.js +4 -0
  165. package/dist/middleware/with-kya-os-server.js.map +1 -1
  166. package/dist/middleware/with-kya-os.config-types.d.ts +139 -0
  167. package/dist/middleware/with-kya-os.config-types.d.ts.map +1 -0
  168. package/dist/middleware/with-kya-os.config-types.js +9 -0
  169. package/dist/middleware/with-kya-os.config-types.js.map +1 -0
  170. package/dist/middleware/with-kya-os.d.ts +10 -238
  171. package/dist/middleware/with-kya-os.d.ts.map +1 -1
  172. package/dist/middleware/with-kya-os.delegation-gate.d.ts +19 -0
  173. package/dist/middleware/with-kya-os.delegation-gate.d.ts.map +1 -0
  174. package/dist/middleware/with-kya-os.delegation-gate.js +175 -0
  175. package/dist/middleware/with-kya-os.delegation-gate.js.map +1 -0
  176. package/dist/middleware/with-kya-os.delegation-verify.d.ts +51 -0
  177. package/dist/middleware/with-kya-os.delegation-verify.d.ts.map +1 -0
  178. package/dist/middleware/with-kya-os.delegation-verify.js +165 -0
  179. package/dist/middleware/with-kya-os.delegation-verify.js.map +1 -0
  180. package/dist/middleware/with-kya-os.deps.d.ts +40 -0
  181. package/dist/middleware/with-kya-os.deps.d.ts.map +1 -0
  182. package/dist/middleware/with-kya-os.deps.js +9 -0
  183. package/dist/middleware/with-kya-os.deps.js.map +1 -0
  184. package/dist/middleware/with-kya-os.grants.d.ts +30 -0
  185. package/dist/middleware/with-kya-os.grants.d.ts.map +1 -0
  186. package/dist/middleware/with-kya-os.grants.js +145 -0
  187. package/dist/middleware/with-kya-os.grants.js.map +1 -0
  188. package/dist/middleware/with-kya-os.helpers.d.ts +24 -0
  189. package/dist/middleware/with-kya-os.helpers.d.ts.map +1 -0
  190. package/dist/middleware/with-kya-os.helpers.js +57 -0
  191. package/dist/middleware/with-kya-os.helpers.js.map +1 -0
  192. package/dist/middleware/with-kya-os.js +65 -703
  193. package/dist/middleware/with-kya-os.js.map +1 -1
  194. package/dist/middleware/with-kya-os.policy-gate.d.ts +16 -0
  195. package/dist/middleware/with-kya-os.policy-gate.d.ts.map +1 -0
  196. package/dist/middleware/with-kya-os.policy-gate.js +98 -0
  197. package/dist/middleware/with-kya-os.policy-gate.js.map +1 -0
  198. package/dist/middleware/with-kya-os.protocol.d.ts +29 -0
  199. package/dist/middleware/with-kya-os.protocol.d.ts.map +1 -0
  200. package/dist/middleware/with-kya-os.protocol.js +121 -0
  201. package/dist/middleware/with-kya-os.protocol.js.map +1 -0
  202. package/dist/middleware/with-kya-os.session.d.ts +32 -0
  203. package/dist/middleware/with-kya-os.session.d.ts.map +1 -0
  204. package/dist/middleware/with-kya-os.session.js +201 -0
  205. package/dist/middleware/with-kya-os.session.js.map +1 -0
  206. package/dist/middleware/with-kya-os.types.d.ts +178 -0
  207. package/dist/middleware/with-kya-os.types.d.ts.map +1 -0
  208. package/dist/middleware/with-kya-os.types.js +13 -0
  209. package/dist/middleware/with-kya-os.types.js.map +1 -0
  210. package/dist/proof/generator.d.ts +21 -0
  211. package/dist/proof/generator.d.ts.map +1 -1
  212. package/dist/proof/generator.js +21 -0
  213. package/dist/proof/generator.js.map +1 -1
  214. package/dist/proof/index.d.ts +1 -1
  215. package/dist/proof/index.d.ts.map +1 -1
  216. package/dist/proof/index.js +1 -1
  217. package/dist/proof/index.js.map +1 -1
  218. package/dist/proof/verifier.d.ts +26 -3
  219. package/dist/proof/verifier.d.ts.map +1 -1
  220. package/dist/proof/verifier.js +54 -24
  221. package/dist/proof/verifier.js.map +1 -1
  222. package/dist/providers/grant-store.d.ts +10 -1
  223. package/dist/providers/grant-store.d.ts.map +1 -1
  224. package/dist/providers/grant-store.js.map +1 -1
  225. package/dist/providers/runtime-fetch.d.ts +8 -0
  226. package/dist/providers/runtime-fetch.d.ts.map +1 -1
  227. package/dist/providers/runtime-fetch.js +17 -0
  228. package/dist/providers/runtime-fetch.js.map +1 -1
  229. package/dist/providers/web-crypto.d.ts.map +1 -1
  230. package/dist/providers/web-crypto.js +15 -7
  231. package/dist/providers/web-crypto.js.map +1 -1
  232. package/dist/session/index.d.ts +1 -0
  233. package/dist/session/index.d.ts.map +1 -1
  234. package/dist/session/index.js +1 -0
  235. package/dist/session/index.js.map +1 -1
  236. package/dist/session/manager.d.ts +17 -6
  237. package/dist/session/manager.d.ts.map +1 -1
  238. package/dist/session/manager.js +16 -26
  239. package/dist/session/manager.js.map +1 -1
  240. package/dist/session/session-store.d.ts +78 -0
  241. package/dist/session/session-store.d.ts.map +1 -0
  242. package/dist/session/session-store.js +79 -0
  243. package/dist/session/session-store.js.map +1 -0
  244. package/dist/types/protocol.d.ts +9 -3
  245. package/dist/types/protocol.d.ts.map +1 -1
  246. package/dist/types/protocol.js.map +1 -1
  247. package/dist/utils/guards.d.ts +2 -0
  248. package/dist/utils/guards.d.ts.map +1 -0
  249. package/dist/utils/guards.js +4 -0
  250. package/dist/utils/guards.js.map +1 -0
  251. package/dist/utils/index.d.ts +3 -0
  252. package/dist/utils/index.d.ts.map +1 -1
  253. package/dist/utils/index.js +3 -0
  254. package/dist/utils/index.js.map +1 -1
  255. package/dist/utils/ip-classifier.d.ts +12 -0
  256. package/dist/utils/ip-classifier.d.ts.map +1 -0
  257. package/dist/utils/ip-classifier.js +153 -0
  258. package/dist/utils/ip-classifier.js.map +1 -0
  259. package/dist/utils/safe-fetch-transports.d.ts +40 -0
  260. package/dist/utils/safe-fetch-transports.d.ts.map +1 -0
  261. package/dist/utils/safe-fetch-transports.js +121 -0
  262. package/dist/utils/safe-fetch-transports.js.map +1 -0
  263. package/dist/utils/safe-fetch-types.d.ts +66 -0
  264. package/dist/utils/safe-fetch-types.d.ts.map +1 -0
  265. package/dist/utils/safe-fetch-types.js +10 -0
  266. package/dist/utils/safe-fetch-types.js.map +1 -0
  267. package/dist/utils/safe-fetch.d.ts +40 -0
  268. package/dist/utils/safe-fetch.d.ts.map +1 -0
  269. package/dist/utils/safe-fetch.js +188 -0
  270. package/dist/utils/safe-fetch.js.map +1 -0
  271. package/dist/utils/statuslist-purpose.d.ts +12 -0
  272. package/dist/utils/statuslist-purpose.d.ts.map +1 -0
  273. package/dist/utils/statuslist-purpose.js +19 -0
  274. package/dist/utils/statuslist-purpose.js.map +1 -0
  275. package/dist/utils/url.d.ts +2 -0
  276. package/dist/utils/url.d.ts.map +1 -0
  277. package/dist/utils/url.js +8 -0
  278. package/dist/utils/url.js.map +1 -0
  279. package/package.json +25 -5
  280. package/schemas/README.md +2 -1
  281. package/schemas/card-delegation-credential.json +239 -0
  282. package/schemas/kya-os-card.schema.json +284 -0
@@ -0,0 +1,69 @@
1
+ /**
2
+ * KYA-OS Entity Card proof — the RFC 9421 HTTP Message Signature sibling (DUAL carrier).
3
+ *
4
+ * The stateless proof carries TWO signatures by ONE DID key over ONE semantic set: the detached
5
+ * JWS in `_meta` (canonical, for JSON-RPC / stdio) and this RFC 9421 sibling for HTTP verifiers
6
+ * that already ship (SEP-1960, Cloudflare Web Bot Auth). A JWS signature also covers its protected
7
+ * header, so its bytes can NEVER satisfy a stock 9421 verifier reconstructing a bare signature
8
+ * base — the two carriers therefore require two signatures. `httpSig` (minted by the signer's
9
+ * `signRaw` seam) is a RAW EdDSA signature over exactly the base {@link httpSignatureBase} exposes,
10
+ * so a stock 9421 verifier reconstructs that base and verifies `httpSig` against the resolved DID
11
+ * key with zero new code. If a signer omits `signRaw`, the proof has no `httpSig` and the sibling
12
+ * simply degrades away (the JWS carrier still verifies).
13
+ *
14
+ * Covered set (the full semantic binding): `content-digest` (the `requestHash`, itself SHA-256 of
15
+ * `JCS({ method, params })` — so the request method+params are bound here), `kya-audience`,
16
+ * `kya-nonce`, `kya-cnf` when a `cnf` is present, plus `created`/`expires`/`keyid`/`alg` in
17
+ * `@signature-params`. Every covered value is reconstructable by a stock verifier from the message
18
+ * headers + `Signature-Input`, which is what keeps the sibling independently verifiable.
19
+ */
20
+ import type { ProofPublicJwk } from '../schema.js';
21
+ import type { CardProofMeta } from './types.js';
22
+ /** The signature label under which the KYA-OS covered components are grouped. */
23
+ export declare const HTTP_SIG_LABEL = "kyaos";
24
+ /**
25
+ * The RFC 9421 headers projected from a proof (a co-normative carrier, not a re-sign). Beyond the
26
+ * `Signature-Input`/`Signature` pair, every NON-`@` covered component is emitted as its own HTTP
27
+ * field so a stock verifier can resolve it from the message alone: `Content-Digest` (`content-digest`),
28
+ * `Kya-Audience` (`kya-audience`), `Kya-Nonce` (`kya-nonce`), and `Kya-Cnf` (`kya-cnf`, only when the
29
+ * proof carries a `cnf`). Each field value is BYTE-IDENTICAL to the corresponding {@link httpSignatureBase}
30
+ * line so reconstruction from the wire yields the exact base `httpSig` was signed over.
31
+ */
32
+ export interface HttpMessageSignature {
33
+ 'Content-Digest': string;
34
+ 'Kya-Audience': string;
35
+ 'Kya-Nonce': string;
36
+ 'Kya-Cnf'?: string;
37
+ 'Signature-Input': string;
38
+ Signature: string;
39
+ }
40
+ /**
41
+ * The RFC 9421 signature base — the EXACT string a stock 9421 verifier reconstructs and the exact
42
+ * bytes `httpSig` signs. Deterministic and self-contained from the proof, so both the minter and a
43
+ * third-party verifier derive an identical base.
44
+ */
45
+ export declare function httpSignatureBase(proof: CardProofMeta): string;
46
+ /** The UTF-8 bytes of {@link httpSignatureBase} — the payload the `signRaw` seam signs at mint. */
47
+ export declare function httpSignatureBaseBytes(proof: CardProofMeta): Uint8Array;
48
+ /**
49
+ * Project a minted `org.kya-os/proof@1` into its RFC 9421 header set. Emits EVERY covered
50
+ * component as a real HTTP field — `Content-Digest`/`Kya-Audience`/`Kya-Nonce` (and `Kya-Cnf`
51
+ * when a `cnf` is present), each byte-identical to its {@link httpSignatureBase} line — plus
52
+ * `Signature-Input` (the covered-component list + params) and `Signature` (the RAW `httpSig` as a
53
+ * base64 byte sequence). Because the message now carries every field the base names, a stock 9421
54
+ * verifier resolves and reconstructs the base from the wire alone. Throws when the proof has no
55
+ * `httpSig` (minted without a `signRaw` seam): there is no cross-verifiable sibling to project, and
56
+ * emitting the JWS bytes here would be silently unverifiable.
57
+ */
58
+ export declare function toHttpMessageSignature(proof: CardProofMeta): HttpMessageSignature;
59
+ /**
60
+ * Verify the sibling exactly as a stock RFC 9421 verifier would: reconstruct {@link httpSignatureBase}
61
+ * and check the RAW `httpSig` against `key` (the resolved DID verification key). Fail-closed —
62
+ * returns `false` when the proof carries no `httpSig` or the signature does not verify.
63
+ *
64
+ * CONTRACT: dispatches on the KEY type (P-256 → `ecdsa-p256-sha256`, Ed25519 → `ed25519`), NOT on
65
+ * `proof.alg`. It ASSUMES the caller has already bound `proof.alg` to the key type (the
66
+ * `alg_key_mismatch` check in `verify.ts`); call it standalone only after that binding holds.
67
+ */
68
+ export declare function verifyHttpSignature(proof: CardProofMeta, key: ProofPublicJwk): Promise<boolean>;
69
+ //# sourceMappingURL=http-sig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-sig.d.ts","sourceRoot":"","sources":["../../../src/card/proof/http-sig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,iFAAiF;AACjF,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAgBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAS9D;AAED,mGAAmG;AACnG,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,CAEvE;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,aAAa,GAAG,oBAAoB,CAajF;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,OAAO,CAAC,CAOlB"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * KYA-OS Entity Card proof — the RFC 9421 HTTP Message Signature sibling (DUAL carrier).
3
+ *
4
+ * The stateless proof carries TWO signatures by ONE DID key over ONE semantic set: the detached
5
+ * JWS in `_meta` (canonical, for JSON-RPC / stdio) and this RFC 9421 sibling for HTTP verifiers
6
+ * that already ship (SEP-1960, Cloudflare Web Bot Auth). A JWS signature also covers its protected
7
+ * header, so its bytes can NEVER satisfy a stock 9421 verifier reconstructing a bare signature
8
+ * base — the two carriers therefore require two signatures. `httpSig` (minted by the signer's
9
+ * `signRaw` seam) is a RAW EdDSA signature over exactly the base {@link httpSignatureBase} exposes,
10
+ * so a stock 9421 verifier reconstructs that base and verifies `httpSig` against the resolved DID
11
+ * key with zero new code. If a signer omits `signRaw`, the proof has no `httpSig` and the sibling
12
+ * simply degrades away (the JWS carrier still verifies).
13
+ *
14
+ * Covered set (the full semantic binding): `content-digest` (the `requestHash`, itself SHA-256 of
15
+ * `JCS({ method, params })` — so the request method+params are bound here), `kya-audience`,
16
+ * `kya-nonce`, `kya-cnf` when a `cnf` is present, plus `created`/`expires`/`keyid`/`alg` in
17
+ * `@signature-params`. Every covered value is reconstructable by a stock verifier from the message
18
+ * headers + `Signature-Input`, which is what keeps the sibling independently verifiable.
19
+ */
20
+ import { base64urlDecodeToBytes } from '../../utils/base64.js';
21
+ import { base64urlToBase64, ed25519VerifyRaw, es256VerifyRaw } from './canonical.js';
22
+ const encoder = new TextEncoder();
23
+ /** The signature label under which the KYA-OS covered components are grouped. */
24
+ export const HTTP_SIG_LABEL = 'kyaos';
25
+ /** The RFC 9421 covered-component list — includes `kya-cnf` only when the proof carries a `cnf`. */
26
+ function coveredComponents(proof) {
27
+ const comps = ['"content-digest"', '"kya-audience"', '"kya-nonce"'];
28
+ if (proof.cnf)
29
+ comps.push('"kya-cnf"');
30
+ return `(${comps.join(' ')})`;
31
+ }
32
+ /** The `;created=…;expires=…;keyid=…;alg=…` parameter tail shared by input + signature base. The
33
+ * `alg` label is the RFC 9421 name for the proof's algorithm (`ed25519` or `ecdsa-p256-sha256`). */
34
+ function sigParams(proof) {
35
+ const label = proof.alg === 'ES256' ? 'ecdsa-p256-sha256' : 'ed25519';
36
+ return `created=${proof.created};expires=${proof.expires};keyid="${proof.kid}";alg="${label}"`;
37
+ }
38
+ /**
39
+ * The RFC 9421 signature base — the EXACT string a stock 9421 verifier reconstructs and the exact
40
+ * bytes `httpSig` signs. Deterministic and self-contained from the proof, so both the minter and a
41
+ * third-party verifier derive an identical base.
42
+ */
43
+ export function httpSignatureBase(proof) {
44
+ const lines = [
45
+ `"content-digest": ${proof.requestHash}`,
46
+ `"kya-audience": ${proof.audience}`,
47
+ `"kya-nonce": ${proof.nonce}`,
48
+ ];
49
+ if (proof.cnf)
50
+ lines.push(`"kya-cnf": ${proof.cnf.jkt}`);
51
+ lines.push(`"@signature-params": ${coveredComponents(proof)};${sigParams(proof)}`);
52
+ return lines.join('\n');
53
+ }
54
+ /** The UTF-8 bytes of {@link httpSignatureBase} — the payload the `signRaw` seam signs at mint. */
55
+ export function httpSignatureBaseBytes(proof) {
56
+ return encoder.encode(httpSignatureBase(proof));
57
+ }
58
+ /**
59
+ * Project a minted `org.kya-os/proof@1` into its RFC 9421 header set. Emits EVERY covered
60
+ * component as a real HTTP field — `Content-Digest`/`Kya-Audience`/`Kya-Nonce` (and `Kya-Cnf`
61
+ * when a `cnf` is present), each byte-identical to its {@link httpSignatureBase} line — plus
62
+ * `Signature-Input` (the covered-component list + params) and `Signature` (the RAW `httpSig` as a
63
+ * base64 byte sequence). Because the message now carries every field the base names, a stock 9421
64
+ * verifier resolves and reconstructs the base from the wire alone. Throws when the proof has no
65
+ * `httpSig` (minted without a `signRaw` seam): there is no cross-verifiable sibling to project, and
66
+ * emitting the JWS bytes here would be silently unverifiable.
67
+ */
68
+ export function toHttpMessageSignature(proof) {
69
+ if (!proof.httpSig) {
70
+ throw new Error('card/proof: proof carries no httpSig; mint with a signRaw-capable signer');
71
+ }
72
+ const headers = {
73
+ 'Content-Digest': proof.requestHash,
74
+ 'Kya-Audience': proof.audience,
75
+ 'Kya-Nonce': proof.nonce,
76
+ 'Signature-Input': `${HTTP_SIG_LABEL}=${coveredComponents(proof)};${sigParams(proof)}`,
77
+ Signature: `${HTTP_SIG_LABEL}=:${base64urlToBase64(proof.httpSig)}:`,
78
+ };
79
+ if (proof.cnf)
80
+ headers['Kya-Cnf'] = proof.cnf.jkt;
81
+ return headers;
82
+ }
83
+ /**
84
+ * Verify the sibling exactly as a stock RFC 9421 verifier would: reconstruct {@link httpSignatureBase}
85
+ * and check the RAW `httpSig` against `key` (the resolved DID verification key). Fail-closed —
86
+ * returns `false` when the proof carries no `httpSig` or the signature does not verify.
87
+ *
88
+ * CONTRACT: dispatches on the KEY type (P-256 → `ecdsa-p256-sha256`, Ed25519 → `ed25519`), NOT on
89
+ * `proof.alg`. It ASSUMES the caller has already bound `proof.alg` to the key type (the
90
+ * `alg_key_mismatch` check in `verify.ts`); call it standalone only after that binding holds.
91
+ */
92
+ export async function verifyHttpSignature(proof, key) {
93
+ if (!proof.httpSig)
94
+ return false;
95
+ const sig = base64urlDecodeToBytes(proof.httpSig);
96
+ const base = httpSignatureBaseBytes(proof);
97
+ // Dispatch on the KEY type (authoritative): a P-256 key verifies the ecdsa-p256-sha256 sibling,
98
+ // an Ed25519 key the ed25519 sibling. verify.ts has already bound proof.alg to this key type.
99
+ return key.kty === 'EC' ? es256VerifyRaw(key, sig, base) : ed25519VerifyRaw(key, sig, base);
100
+ }
101
+ //# sourceMappingURL=http-sig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-sig.js","sourceRoot":"","sources":["../../../src/card/proof/http-sig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * KYA-OS Entity Card — stateless per-request holder-of-key proof (`org.kya-os/proof@1`).
3
+ *
4
+ * The security-critical module, split into focused units re-exported here:
5
+ * - types (./types): CardProofMeta + the minting/verifying seams and result shapes.
6
+ * - signer (./signer): the default Ed25519 minting seam (jose, no mcp-i-core).
7
+ * - build (./build): buildCardProof — mint one proof under the SHIPPED `_meta` key.
8
+ * - verify (./verify): verifyCardProof — recompute every binding, fail-closed.
9
+ * - http-sig (./http-sig): toHttpMessageSignature — the RFC 9421 sibling carrier.
10
+ * - canonical (./canonical): computeRequestHash — JCS request binding (shared by both halves).
11
+ * - nonce-cache (./nonce-cache): the batteries-included ATOMIC replay seams (InMemoryNonceCache
12
+ * + the NonceCacheProvider adapter) so the safe consume is the default.
13
+ *
14
+ * Distinct from — and orthogonal to — the legacy session-bound proof in `src/proof`: the card proof
15
+ * rides its OWN `_meta['org.kya-os/proof@1']` key, separate from the legacy `org.kya-os/proof`, so
16
+ * both regimes can run on one server without either guard seeing the other's proof.
17
+ */
18
+ export * from './types.js';
19
+ export * from './signer.js';
20
+ export * from './build.js';
21
+ export * from './verify.js';
22
+ export * from './http-sig.js';
23
+ export * from './nonce-cache.js';
24
+ export { computeRequestHash, digestsEqual } from './canonical.js';
25
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/card/proof/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * KYA-OS Entity Card — stateless per-request holder-of-key proof (`org.kya-os/proof@1`).
3
+ *
4
+ * The security-critical module, split into focused units re-exported here:
5
+ * - types (./types): CardProofMeta + the minting/verifying seams and result shapes.
6
+ * - signer (./signer): the default Ed25519 minting seam (jose, no mcp-i-core).
7
+ * - build (./build): buildCardProof — mint one proof under the SHIPPED `_meta` key.
8
+ * - verify (./verify): verifyCardProof — recompute every binding, fail-closed.
9
+ * - http-sig (./http-sig): toHttpMessageSignature — the RFC 9421 sibling carrier.
10
+ * - canonical (./canonical): computeRequestHash — JCS request binding (shared by both halves).
11
+ * - nonce-cache (./nonce-cache): the batteries-included ATOMIC replay seams (InMemoryNonceCache
12
+ * + the NonceCacheProvider adapter) so the safe consume is the default.
13
+ *
14
+ * Distinct from — and orthogonal to — the legacy session-bound proof in `src/proof`: the card proof
15
+ * rides its OWN `_meta['org.kya-os/proof@1']` key, separate from the legacy `org.kya-os/proof`, so
16
+ * both regimes can run on one server without either guard seeing the other's proof.
17
+ */
18
+ export * from './types.js';
19
+ export * from './signer.js';
20
+ export * from './build.js';
21
+ export * from './verify.js';
22
+ export * from './http-sig.js';
23
+ export * from './nonce-cache.js';
24
+ export { computeRequestHash, digestsEqual } from './canonical.js';
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/card/proof/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * KYA-OS Entity Card — batteries-included replay defense for `org.kya-os/proof@1`.
3
+ *
4
+ * The {@link ConsumeNonceIfFresh} seam is security-critical: it MUST be an ATOMIC test-AND-set
5
+ * (record the nonce AND report whether it was already seen, in one step). Hand-rolling it is the
6
+ * documented footgun — so this module ships the two implementations a developer should reach for:
7
+ *
8
+ * - {@link InMemoryNonceCache} — a single-process, race-free TTL cache. The check-and-set runs in
9
+ * one synchronous critical section (no `await` between read and write), so it cannot interleave
10
+ * with a concurrent replay within one process. Use it for a single instance / dev.
11
+ * - {@link consumeFromNonceCacheProvider} — composes the two-method `NonceCacheProvider`
12
+ * (`has()` + `add()`) into the atomic seam for a shared/distributed store (see the atomicity
13
+ * note on the function).
14
+ *
15
+ * Type-only import of `NonceCacheProvider` — no runtime coupling to the legacy proof engine and no
16
+ * `mcp-i-core` dependency.
17
+ */
18
+ import type { NonceCacheProvider } from '../../providers/base.js';
19
+ import { type ConsumeNonceIfFresh } from './types.js';
20
+ /** Construction options for {@link InMemoryNonceCache}. */
21
+ export interface InMemoryNonceCacheOptions {
22
+ /** How long a consumed nonce is remembered, in seconds (default {@link NONCE_RETENTION_SEC} —
23
+ * the full verifier acceptance window, so an evicted nonce can never outlive a valid proof). */
24
+ ttlSec?: number;
25
+ /** Injectable clock returning epoch MILLISECONDS (deterministic tests; default `Date.now`). */
26
+ now?: () => number;
27
+ }
28
+ /**
29
+ * A single-process, race-free replay cache implementing the {@link ConsumeNonceIfFresh} seam.
30
+ * Remembers each `(did, nonce)` for `ttlSec` — long enough to cover the proof's own lifetime — and
31
+ * rejects any repeat within that window.
32
+ */
33
+ export declare class InMemoryNonceCache {
34
+ /** `did\0nonce` → expiry epoch ms. */
35
+ private readonly seen;
36
+ private readonly ttlMs;
37
+ private readonly clock;
38
+ /** Inserts since the last sweep — amortises {@link cleanup} so `seen` stays bounded. */
39
+ private insertsSinceSweep;
40
+ constructor(opts?: InMemoryNonceCacheOptions);
41
+ /**
42
+ * Atomic test-AND-set: record `nonce` for `did` and return `true` iff it was NOT already recorded
43
+ * (and unexpired); return `false` on a replay, leaving the prior record intact. One synchronous
44
+ * critical section — no `await` between the read and the write — so it is race-free within one
45
+ * process. Arrow field so it stays bound when passed directly as the seam.
46
+ */
47
+ readonly consume: ConsumeNonceIfFresh;
48
+ /** Drop expired entries — call periodically to bound memory in a long-running process. */
49
+ cleanup(): void;
50
+ }
51
+ /** Options for {@link consumeFromNonceCacheProvider}. */
52
+ export interface NonceCacheProviderAdapterOptions {
53
+ /** TTL applied to each recorded nonce, in seconds (default {@link NONCE_RETENTION_SEC}). */
54
+ ttlSec?: number;
55
+ }
56
+ /**
57
+ * Adapt a two-method {@link NonceCacheProvider} (`has()` + `add()`) into the atomic
58
+ * {@link ConsumeNonceIfFresh} seam.
59
+ *
60
+ * ATOMICITY: `has()` then `add()` is only race-free when the provider serialises the pair — a
61
+ * single-process store, or a backend with a native compare-and-set. For a SHARED distributed cache,
62
+ * back it with a store that enforces atomic check-and-set (SPEC §12.2); otherwise two concurrent
63
+ * replays can both observe `has() === false` before either `add()`s. The bundled
64
+ * {@link InMemoryNonceCache} is race-free by construction and is the safer single-process default.
65
+ */
66
+ export declare function consumeFromNonceCacheProvider(provider: NonceCacheProvider, opts?: NonceCacheProviderAdapterOptions): ConsumeNonceIfFresh;
67
+ //# sourceMappingURL=nonce-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nonce-cache.d.ts","sourceRoot":"","sources":["../../../src/card/proof/nonce-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAuB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAK3E,2DAA2D;AAC3D,MAAM,WAAW,yBAAyB;IACxC;qGACiG;IACjG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+FAA+F;IAC/F,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,sCAAsC;IACtC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,wFAAwF;IACxF,OAAO,CAAC,iBAAiB,CAAK;gBAElB,IAAI,GAAE,yBAA8B;IAKhD;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAgBnC;IAEF,0FAA0F;IAC1F,OAAO,IAAI,IAAI;CAIhB;AAED,yDAAyD;AACzD,MAAM,WAAW,gCAAgC;IAC/C,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,kBAAkB,EAC5B,IAAI,GAAE,gCAAqC,GAC1C,mBAAmB,CAOrB"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * KYA-OS Entity Card — batteries-included replay defense for `org.kya-os/proof@1`.
3
+ *
4
+ * The {@link ConsumeNonceIfFresh} seam is security-critical: it MUST be an ATOMIC test-AND-set
5
+ * (record the nonce AND report whether it was already seen, in one step). Hand-rolling it is the
6
+ * documented footgun — so this module ships the two implementations a developer should reach for:
7
+ *
8
+ * - {@link InMemoryNonceCache} — a single-process, race-free TTL cache. The check-and-set runs in
9
+ * one synchronous critical section (no `await` between read and write), so it cannot interleave
10
+ * with a concurrent replay within one process. Use it for a single instance / dev.
11
+ * - {@link consumeFromNonceCacheProvider} — composes the two-method `NonceCacheProvider`
12
+ * (`has()` + `add()`) into the atomic seam for a shared/distributed store (see the atomicity
13
+ * note on the function).
14
+ *
15
+ * Type-only import of `NonceCacheProvider` — no runtime coupling to the legacy proof engine and no
16
+ * `mcp-i-core` dependency.
17
+ */
18
+ import { NONCE_RETENTION_SEC } from './types.js';
19
+ /** Inserts between amortised expired-entry sweeps (bounds memory without a timer/lifecycle). */
20
+ const SWEEP_EVERY = 1000;
21
+ /**
22
+ * A single-process, race-free replay cache implementing the {@link ConsumeNonceIfFresh} seam.
23
+ * Remembers each `(did, nonce)` for `ttlSec` — long enough to cover the proof's own lifetime — and
24
+ * rejects any repeat within that window.
25
+ */
26
+ export class InMemoryNonceCache {
27
+ /** `did\0nonce` → expiry epoch ms. */
28
+ seen = new Map();
29
+ ttlMs;
30
+ clock;
31
+ /** Inserts since the last sweep — amortises {@link cleanup} so `seen` stays bounded. */
32
+ insertsSinceSweep = 0;
33
+ constructor(opts = {}) {
34
+ this.ttlMs = (opts.ttlSec ?? NONCE_RETENTION_SEC) * 1000;
35
+ this.clock = opts.now ?? Date.now;
36
+ }
37
+ /**
38
+ * Atomic test-AND-set: record `nonce` for `did` and return `true` iff it was NOT already recorded
39
+ * (and unexpired); return `false` on a replay, leaving the prior record intact. One synchronous
40
+ * critical section — no `await` between the read and the write — so it is race-free within one
41
+ * process. Arrow field so it stays bound when passed directly as the seam.
42
+ */
43
+ consume = (nonce, did) => {
44
+ // NUL (`\0`) delimiter: `did` and `nonce` are opaque strings, so an ambiguous separator
45
+ // (e.g. a space) could let one (did, nonce) pair collide with another. `\0` cannot appear
46
+ // in a DID and is not a valid nonce byte, so the composite key stays unambiguous.
47
+ const key = `${did}\0${nonce}`;
48
+ const now = this.clock();
49
+ const expiry = this.seen.get(key);
50
+ if (expiry !== undefined && expiry > now)
51
+ return false;
52
+ this.seen.set(key, now + this.ttlMs);
53
+ // Amortised eviction: sweep expired entries every SWEEP_EVERY inserts so a long-running
54
+ // process cannot accumulate dead nonces unboundedly — no timer or lifecycle to manage.
55
+ if (++this.insertsSinceSweep >= SWEEP_EVERY) {
56
+ this.insertsSinceSweep = 0;
57
+ this.cleanup();
58
+ }
59
+ return true;
60
+ };
61
+ /** Drop expired entries — call periodically to bound memory in a long-running process. */
62
+ cleanup() {
63
+ const now = this.clock();
64
+ for (const [key, expiry] of this.seen)
65
+ if (expiry <= now)
66
+ this.seen.delete(key);
67
+ }
68
+ }
69
+ /**
70
+ * Adapt a two-method {@link NonceCacheProvider} (`has()` + `add()`) into the atomic
71
+ * {@link ConsumeNonceIfFresh} seam.
72
+ *
73
+ * ATOMICITY: `has()` then `add()` is only race-free when the provider serialises the pair — a
74
+ * single-process store, or a backend with a native compare-and-set. For a SHARED distributed cache,
75
+ * back it with a store that enforces atomic check-and-set (SPEC §12.2); otherwise two concurrent
76
+ * replays can both observe `has() === false` before either `add()`s. The bundled
77
+ * {@link InMemoryNonceCache} is race-free by construction and is the safer single-process default.
78
+ */
79
+ export function consumeFromNonceCacheProvider(provider, opts = {}) {
80
+ const ttlSec = opts.ttlSec ?? NONCE_RETENTION_SEC;
81
+ return async (nonce, did) => {
82
+ if (await provider.has(nonce, did))
83
+ return false;
84
+ await provider.add(nonce, ttlSec, did);
85
+ return true;
86
+ };
87
+ }
88
+ //# sourceMappingURL=nonce-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nonce-cache.js","sourceRoot":"","sources":["../../../src/card/proof/nonce-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,mBAAmB,EAA4B,MAAM,YAAY,CAAC;AAE3E,gGAAgG;AAChG,MAAM,WAAW,GAAG,IAAI,CAAC;AAWzB;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IAC7B,sCAAsC;IACrB,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACjC,KAAK,CAAS;IACd,KAAK,CAAe;IACrC,wFAAwF;IAChF,iBAAiB,GAAG,CAAC,CAAC;IAE9B,YAAY,OAAkC,EAAE;QAC9C,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,mBAAmB,CAAC,GAAG,IAAI,CAAC;QACzD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACpC,CAAC;IAED;;;;;OAKG;IACM,OAAO,GAAwB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACrD,wFAAwF;QACxF,0FAA0F;QAC1F,kFAAkF;QAClF,MAAM,GAAG,GAAG,GAAG,GAAG,KAAK,KAAK,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,GAAG,GAAG;YAAE,OAAO,KAAK,CAAC;QACvD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACrC,wFAAwF;QACxF,uFAAuF;QACvF,IAAI,EAAE,IAAI,CAAC,iBAAiB,IAAI,WAAW,EAAE,CAAC;YAC5C,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,0FAA0F;IAC1F,OAAO;QACL,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,MAAM,IAAI,GAAG;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAClF,CAAC;CACF;AAQD;;;;;;;;;GASG;AACH,MAAM,UAAU,6BAA6B,CAC3C,QAA4B,EAC5B,OAAyC,EAAE;IAE3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,mBAAmB,CAAC;IAClD,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC1B,IAAI,MAAM,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QACjD,MAAM,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * KYA-OS Entity Card proof — the default Ed25519 minting seam.
3
+ *
4
+ * `ed25519SignerFromJwk` wraps an Ed25519 private JWK into a {@link ProofSigner}: it produces a
5
+ * DETACHED EdDSA JWS (`protectedHeader..signature`) over the JCS-canonical covered claims and
6
+ * pre-computes the RFC 7638 thumbprint (`jkt`) of the public half for the `cnf` fusion. Uses
7
+ * `jose` directly (already a dependency) — no `mcp-i-core` runtime dependency leaks in. Callers
8
+ * with a KMS / HSM key can implement {@link ProofSigner} themselves; this is the batteries-included
9
+ * path for in-process keys.
10
+ */
11
+ import type { Ed25519PrivateJwk, P256PrivateJwk, ProofSigner } from './types.js';
12
+ /**
13
+ * Build a {@link ProofSigner} from an Ed25519 private JWK. The raw key is imported ONCE and never
14
+ * serialized back out; `jkt` is the RFC 7638 thumbprint of the public half (`{kty,crv,x}`), which
15
+ * is what `cnf.jkt` and the sender-constraint fusion compare against.
16
+ */
17
+ export declare function ed25519SignerFromJwk(opts: {
18
+ did: string;
19
+ kid: string;
20
+ privateJwk: Ed25519PrivateJwk;
21
+ }): Promise<ProofSigner>;
22
+ /**
23
+ * Build a {@link ProofSigner} from a P-256 private JWK — the ES256 (ECDSA, FIPS-eligible) path.
24
+ * Same shape as {@link ed25519SignerFromJwk}: RFC 7638 `jkt` over the public half `{kty,crv,x,y}`,
25
+ * a detached ES256 JWS, and the raw `ecdsa-p256-sha256` RFC 9421 sibling via {@link es256SignRaw}.
26
+ */
27
+ export declare function es256SignerFromJwk(opts: {
28
+ did: string;
29
+ kid: string;
30
+ privateJwk: P256PrivateJwk;
31
+ }): Promise<ProofSigner>;
32
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../../src/card/proof/signer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAcjF;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,iBAAiB,CAAC;CAC/B,GAAG,OAAO,CAAC,WAAW,CAAC,CAavB;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,cAAc,CAAC;CAC5B,GAAG,OAAO,CAAC,WAAW,CAAC,CAavB"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * KYA-OS Entity Card proof — the default Ed25519 minting seam.
3
+ *
4
+ * `ed25519SignerFromJwk` wraps an Ed25519 private JWK into a {@link ProofSigner}: it produces a
5
+ * DETACHED EdDSA JWS (`protectedHeader..signature`) over the JCS-canonical covered claims and
6
+ * pre-computes the RFC 7638 thumbprint (`jkt`) of the public half for the `cnf` fusion. Uses
7
+ * `jose` directly (already a dependency) — no `mcp-i-core` runtime dependency leaks in. Callers
8
+ * with a KMS / HSM key can implement {@link ProofSigner} themselves; this is the batteries-included
9
+ * path for in-process keys.
10
+ */
11
+ import { FlattenedSign, calculateJwkThumbprint, importJWK } from 'jose';
12
+ import { base64urlEncodeFromBytes } from '../../utils/base64.js';
13
+ import { ed25519SignRaw, es256SignRaw } from './canonical.js';
14
+ /** Shared detached-JWS producer: `protectedHeader..signature` with the given `alg` + `kid` (DRY). */
15
+ function detachedJwsSign(key, alg, kid) {
16
+ return async (payload) => {
17
+ const flattened = await new FlattenedSign(payload).setProtectedHeader({ alg, kid }).sign(key);
18
+ return `${flattened.protected ?? ''}..${flattened.signature}`;
19
+ };
20
+ }
21
+ /**
22
+ * Build a {@link ProofSigner} from an Ed25519 private JWK. The raw key is imported ONCE and never
23
+ * serialized back out; `jkt` is the RFC 7638 thumbprint of the public half (`{kty,crv,x}`), which
24
+ * is what `cnf.jkt` and the sender-constraint fusion compare against.
25
+ */
26
+ export async function ed25519SignerFromJwk(opts) {
27
+ const key = await importJWK(opts.privateJwk, 'EdDSA');
28
+ const publicJwk = { kty: 'OKP', crv: 'Ed25519', x: opts.privateJwk.x };
29
+ const jkt = await calculateJwkThumbprint(publicJwk, 'sha256');
30
+ const rawJwk = { kty: 'OKP', crv: 'Ed25519', x: opts.privateJwk.x, d: opts.privateJwk.d };
31
+ return {
32
+ did: opts.did,
33
+ kid: opts.kid,
34
+ jkt,
35
+ alg: 'EdDSA',
36
+ sign: detachedJwsSign(key, 'EdDSA', opts.kid),
37
+ signRaw: (payload) => ed25519SignRaw(rawJwk, payload).then(base64urlEncodeFromBytes),
38
+ };
39
+ }
40
+ /**
41
+ * Build a {@link ProofSigner} from a P-256 private JWK — the ES256 (ECDSA, FIPS-eligible) path.
42
+ * Same shape as {@link ed25519SignerFromJwk}: RFC 7638 `jkt` over the public half `{kty,crv,x,y}`,
43
+ * a detached ES256 JWS, and the raw `ecdsa-p256-sha256` RFC 9421 sibling via {@link es256SignRaw}.
44
+ */
45
+ export async function es256SignerFromJwk(opts) {
46
+ const key = await importJWK(opts.privateJwk, 'ES256');
47
+ const publicJwk = { kty: 'EC', crv: 'P-256', x: opts.privateJwk.x, y: opts.privateJwk.y };
48
+ const jkt = await calculateJwkThumbprint(publicJwk, 'sha256');
49
+ const rawJwk = { kty: 'EC', crv: 'P-256', x: opts.privateJwk.x, y: opts.privateJwk.y, d: opts.privateJwk.d };
50
+ return {
51
+ did: opts.did,
52
+ kid: opts.kid,
53
+ jkt,
54
+ alg: 'ES256',
55
+ sign: detachedJwsSign(key, 'ES256', opts.kid),
56
+ signRaw: (payload) => es256SignRaw(rawJwk, payload).then(base64urlEncodeFromBytes),
57
+ };
58
+ }
59
+ //# sourceMappingURL=signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.js","sourceRoot":"","sources":["../../../src/card/proof/signer.ts"],"names":[],"mappings":"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"}