@openvtc/pnm-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/README.md +129 -0
  2. package/dist/did/derive-signing-key.d.ts +19 -0
  3. package/dist/did/derive-signing-key.d.ts.map +1 -0
  4. package/dist/did/derive-signing-key.js +96 -0
  5. package/dist/did/derive-signing-key.js.map +1 -0
  6. package/dist/did/index.d.ts +5 -0
  7. package/dist/did/index.d.ts.map +1 -0
  8. package/dist/did/index.js +5 -0
  9. package/dist/did/index.js.map +1 -0
  10. package/dist/did/peer.d.ts +37 -0
  11. package/dist/did/peer.d.ts.map +1 -0
  12. package/dist/did/peer.js +49 -0
  13. package/dist/did/peer.js.map +1 -0
  14. package/dist/did/verification-method.d.ts +43 -0
  15. package/dist/did/verification-method.d.ts.map +1 -0
  16. package/dist/did/verification-method.js +32 -0
  17. package/dist/did/verification-method.js.map +1 -0
  18. package/dist/did/verify.d.ts +49 -0
  19. package/dist/did/verify.d.ts.map +1 -0
  20. package/dist/did/verify.js +89 -0
  21. package/dist/did/verify.js.map +1 -0
  22. package/dist/didcomm/index.d.ts +235 -0
  23. package/dist/didcomm/index.d.ts.map +1 -0
  24. package/dist/didcomm/index.js +415 -0
  25. package/dist/didcomm/index.js.map +1 -0
  26. package/dist/inbound/confirm.d.ts +50 -0
  27. package/dist/inbound/confirm.d.ts.map +1 -0
  28. package/dist/inbound/confirm.js +64 -0
  29. package/dist/inbound/confirm.js.map +1 -0
  30. package/dist/inbound/dedup.d.ts +9 -0
  31. package/dist/inbound/dedup.d.ts.map +1 -0
  32. package/dist/inbound/dedup.js +31 -0
  33. package/dist/inbound/dedup.js.map +1 -0
  34. package/dist/inbound/index.d.ts +3 -0
  35. package/dist/inbound/index.d.ts.map +1 -0
  36. package/dist/inbound/index.js +3 -0
  37. package/dist/inbound/index.js.map +1 -0
  38. package/dist/index.d.ts +14 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +14 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/onboarding/index.d.ts +2 -0
  43. package/dist/onboarding/index.d.ts.map +1 -0
  44. package/dist/onboarding/index.js +2 -0
  45. package/dist/onboarding/index.js.map +1 -0
  46. package/dist/onboarding/swap.d.ts +60 -0
  47. package/dist/onboarding/swap.d.ts.map +1 -0
  48. package/dist/onboarding/swap.js +148 -0
  49. package/dist/onboarding/swap.js.map +1 -0
  50. package/dist/provision/adopt.d.ts +31 -0
  51. package/dist/provision/adopt.d.ts.map +1 -0
  52. package/dist/provision/adopt.js +114 -0
  53. package/dist/provision/adopt.js.map +1 -0
  54. package/dist/provision/armor.d.ts +19 -0
  55. package/dist/provision/armor.d.ts.map +1 -0
  56. package/dist/provision/armor.js +243 -0
  57. package/dist/provision/armor.js.map +1 -0
  58. package/dist/provision/crc24.d.ts +5 -0
  59. package/dist/provision/crc24.d.ts.map +1 -0
  60. package/dist/provision/crc24.js +30 -0
  61. package/dist/provision/crc24.js.map +1 -0
  62. package/dist/provision/hpke.d.ts +17 -0
  63. package/dist/provision/hpke.d.ts.map +1 -0
  64. package/dist/provision/hpke.js +60 -0
  65. package/dist/provision/hpke.js.map +1 -0
  66. package/dist/provision/index.d.ts +10 -0
  67. package/dist/provision/index.d.ts.map +1 -0
  68. package/dist/provision/index.js +16 -0
  69. package/dist/provision/index.js.map +1 -0
  70. package/dist/provision/open.d.ts +28 -0
  71. package/dist/provision/open.d.ts.map +1 -0
  72. package/dist/provision/open.js +224 -0
  73. package/dist/provision/open.js.map +1 -0
  74. package/dist/provision/request.d.ts +65 -0
  75. package/dist/provision/request.d.ts.map +1 -0
  76. package/dist/provision/request.js +53 -0
  77. package/dist/provision/request.js.map +1 -0
  78. package/dist/provision/run.d.ts +76 -0
  79. package/dist/provision/run.d.ts.map +1 -0
  80. package/dist/provision/run.js +110 -0
  81. package/dist/provision/run.js.map +1 -0
  82. package/dist/provision/send.d.ts +85 -0
  83. package/dist/provision/send.d.ts.map +1 -0
  84. package/dist/provision/send.js +87 -0
  85. package/dist/provision/send.js.map +1 -0
  86. package/dist/provision/types.d.ts +110 -0
  87. package/dist/provision/types.d.ts.map +1 -0
  88. package/dist/provision/types.js +17 -0
  89. package/dist/provision/types.js.map +1 -0
  90. package/dist/rp-login/didcomm.d.ts +34 -0
  91. package/dist/rp-login/didcomm.d.ts.map +1 -0
  92. package/dist/rp-login/didcomm.js +72 -0
  93. package/dist/rp-login/didcomm.js.map +1 -0
  94. package/dist/rp-login/index.d.ts +3 -0
  95. package/dist/rp-login/index.d.ts.map +1 -0
  96. package/dist/rp-login/index.js +3 -0
  97. package/dist/rp-login/index.js.map +1 -0
  98. package/dist/rp-login/step-up.d.ts +43 -0
  99. package/dist/rp-login/step-up.d.ts.map +1 -0
  100. package/dist/rp-login/step-up.js +118 -0
  101. package/dist/rp-login/step-up.js.map +1 -0
  102. package/dist/siop/index.d.ts +3 -0
  103. package/dist/siop/index.d.ts.map +1 -0
  104. package/dist/siop/index.js +3 -0
  105. package/dist/siop/index.js.map +1 -0
  106. package/dist/siop/login-client.d.ts +29 -0
  107. package/dist/siop/login-client.d.ts.map +1 -0
  108. package/dist/siop/login-client.js +79 -0
  109. package/dist/siop/login-client.js.map +1 -0
  110. package/dist/siop/self-issued.d.ts +96 -0
  111. package/dist/siop/self-issued.d.ts.map +1 -0
  112. package/dist/siop/self-issued.js +162 -0
  113. package/dist/siop/self-issued.js.map +1 -0
  114. package/dist/store/holder-identity.d.ts +241 -0
  115. package/dist/store/holder-identity.d.ts.map +1 -0
  116. package/dist/store/holder-identity.js +441 -0
  117. package/dist/store/holder-identity.js.map +1 -0
  118. package/dist/store/index.d.ts +4 -0
  119. package/dist/store/index.d.ts.map +1 -0
  120. package/dist/store/index.js +4 -0
  121. package/dist/store/index.js.map +1 -0
  122. package/dist/store/kv-store.d.ts +51 -0
  123. package/dist/store/kv-store.d.ts.map +1 -0
  124. package/dist/store/kv-store.js +100 -0
  125. package/dist/store/kv-store.js.map +1 -0
  126. package/dist/store/secret-wrap.d.ts +109 -0
  127. package/dist/store/secret-wrap.d.ts.map +1 -0
  128. package/dist/store/secret-wrap.js +85 -0
  129. package/dist/store/secret-wrap.js.map +1 -0
  130. package/dist/trust-tasks/index.d.ts +2 -0
  131. package/dist/trust-tasks/index.d.ts.map +1 -0
  132. package/dist/trust-tasks/index.js +2 -0
  133. package/dist/trust-tasks/index.js.map +1 -0
  134. package/dist/trust-tasks/sign.d.ts +31 -0
  135. package/dist/trust-tasks/sign.d.ts.map +1 -0
  136. package/dist/trust-tasks/sign.js +141 -0
  137. package/dist/trust-tasks/sign.js.map +1 -0
  138. package/dist/util/timing.d.ts +14 -0
  139. package/dist/util/timing.d.ts.map +1 -0
  140. package/dist/util/timing.js +20 -0
  141. package/dist/util/timing.js.map +1 -0
  142. package/dist/vault/delete.d.ts +19 -0
  143. package/dist/vault/delete.d.ts.map +1 -0
  144. package/dist/vault/delete.js +35 -0
  145. package/dist/vault/delete.js.map +1 -0
  146. package/dist/vault/index.d.ts +8 -0
  147. package/dist/vault/index.d.ts.map +1 -0
  148. package/dist/vault/index.js +7 -0
  149. package/dist/vault/index.js.map +1 -0
  150. package/dist/vault/list.d.ts +96 -0
  151. package/dist/vault/list.d.ts.map +1 -0
  152. package/dist/vault/list.js +106 -0
  153. package/dist/vault/list.js.map +1 -0
  154. package/dist/vault/proxy-login.d.ts +100 -0
  155. package/dist/vault/proxy-login.d.ts.map +1 -0
  156. package/dist/vault/proxy-login.js +106 -0
  157. package/dist/vault/proxy-login.js.map +1 -0
  158. package/dist/vault/release.d.ts +33 -0
  159. package/dist/vault/release.d.ts.map +1 -0
  160. package/dist/vault/release.js +83 -0
  161. package/dist/vault/release.js.map +1 -0
  162. package/dist/vault/sign-trust-task.d.ts +26 -0
  163. package/dist/vault/sign-trust-task.d.ts.map +1 -0
  164. package/dist/vault/sign-trust-task.js +53 -0
  165. package/dist/vault/sign-trust-task.js.map +1 -0
  166. package/dist/vault/transport.d.ts +50 -0
  167. package/dist/vault/transport.d.ts.map +1 -0
  168. package/dist/vault/transport.js +118 -0
  169. package/dist/vault/transport.js.map +1 -0
  170. package/dist/vault/upsert.d.ts +102 -0
  171. package/dist/vault/upsert.d.ts.map +1 -0
  172. package/dist/vault/upsert.js +92 -0
  173. package/dist/vault/upsert.js.map +1 -0
  174. package/dist/vta/bridge-mediator-session.d.ts +26 -0
  175. package/dist/vta/bridge-mediator-session.d.ts.map +1 -0
  176. package/dist/vta/bridge-mediator-session.js +37 -0
  177. package/dist/vta/bridge-mediator-session.js.map +1 -0
  178. package/dist/vta/bridge-memory.d.ts +80 -0
  179. package/dist/vta/bridge-memory.d.ts.map +1 -0
  180. package/dist/vta/bridge-memory.js +162 -0
  181. package/dist/vta/bridge-memory.js.map +1 -0
  182. package/dist/vta/client.d.ts +40 -0
  183. package/dist/vta/client.d.ts.map +1 -0
  184. package/dist/vta/client.js +91 -0
  185. package/dist/vta/client.js.map +1 -0
  186. package/dist/vta/contexts.d.ts +60 -0
  187. package/dist/vta/contexts.d.ts.map +1 -0
  188. package/dist/vta/contexts.js +118 -0
  189. package/dist/vta/contexts.js.map +1 -0
  190. package/dist/vta/didcomm.d.ts +57 -0
  191. package/dist/vta/didcomm.d.ts.map +1 -0
  192. package/dist/vta/didcomm.js +138 -0
  193. package/dist/vta/didcomm.js.map +1 -0
  194. package/dist/vta/errors.d.ts +20 -0
  195. package/dist/vta/errors.d.ts.map +1 -0
  196. package/dist/vta/errors.js +64 -0
  197. package/dist/vta/errors.js.map +1 -0
  198. package/dist/vta/index.d.ts +15 -0
  199. package/dist/vta/index.d.ts.map +1 -0
  200. package/dist/vta/index.js +15 -0
  201. package/dist/vta/index.js.map +1 -0
  202. package/dist/vta/mediation.d.ts +80 -0
  203. package/dist/vta/mediation.d.ts.map +1 -0
  204. package/dist/vta/mediation.js +29 -0
  205. package/dist/vta/mediation.js.map +1 -0
  206. package/dist/vta/mediator-client.d.ts +66 -0
  207. package/dist/vta/mediator-client.d.ts.map +1 -0
  208. package/dist/vta/mediator-client.js +139 -0
  209. package/dist/vta/mediator-client.js.map +1 -0
  210. package/dist/vta/pickup.d.ts +81 -0
  211. package/dist/vta/pickup.d.ts.map +1 -0
  212. package/dist/vta/pickup.js +30 -0
  213. package/dist/vta/pickup.js.map +1 -0
  214. package/dist/vta/protocol.d.ts +76 -0
  215. package/dist/vta/protocol.d.ts.map +1 -0
  216. package/dist/vta/protocol.js +30 -0
  217. package/dist/vta/protocol.js.map +1 -0
  218. package/dist/vta/smoke.d.ts +59 -0
  219. package/dist/vta/smoke.d.ts.map +1 -0
  220. package/dist/vta/smoke.js +408 -0
  221. package/dist/vta/smoke.js.map +1 -0
  222. package/dist/vta/transport.d.ts +55 -0
  223. package/dist/vta/transport.d.ts.map +1 -0
  224. package/dist/vta/transport.js +2 -0
  225. package/dist/vta/transport.js.map +1 -0
  226. package/dist/vta/types.d.ts +50 -0
  227. package/dist/vta/types.d.ts.map +1 -0
  228. package/dist/vta/types.js +2 -0
  229. package/dist/vta/types.js.map +1 -0
  230. package/dist/vta/wallet-session.d.ts +87 -0
  231. package/dist/vta/wallet-session.d.ts.map +1 -0
  232. package/dist/vta/wallet-session.js +106 -0
  233. package/dist/vta/wallet-session.js.map +1 -0
  234. package/dist/webauthn/base64url.d.ts +3 -0
  235. package/dist/webauthn/base64url.d.ts.map +1 -0
  236. package/dist/webauthn/base64url.js +17 -0
  237. package/dist/webauthn/base64url.js.map +1 -0
  238. package/dist/webauthn/index.d.ts +4 -0
  239. package/dist/webauthn/index.d.ts.map +1 -0
  240. package/dist/webauthn/index.js +4 -0
  241. package/dist/webauthn/index.js.map +1 -0
  242. package/dist/webauthn/multikey.d.ts +26 -0
  243. package/dist/webauthn/multikey.d.ts.map +1 -0
  244. package/dist/webauthn/multikey.js +91 -0
  245. package/dist/webauthn/multikey.js.map +1 -0
  246. package/dist/webauthn/register.d.ts +36 -0
  247. package/dist/webauthn/register.d.ts.map +1 -0
  248. package/dist/webauthn/register.js +77 -0
  249. package/dist/webauthn/register.js.map +1 -0
  250. package/package.json +56 -0
@@ -0,0 +1,79 @@
1
+ // SIOPv2 login client for a Trust-Tasks Relying Party (the DID hosting
2
+ // service). Drives the RP's challenge → authenticate flow: fetch a
3
+ // nonce, self-issue an `id_token` signed by the holder's Ed25519
4
+ // `did:key`, wrap it in the RP's authenticate Trust-Task envelope, and
5
+ // exchange it for a session JWT. No passkey, no DIDComm to the RP — the
6
+ // RP verifies by resolving the holder DID.
7
+ import { createStopwatch } from "../util/timing.js";
8
+ import { issueIdToken } from "./self-issued.js";
9
+ /** The canonical authenticate Trust-Task type from trusttasks-tf.
10
+ * did-hosting + VTA + VTC all dispatch on this same URI. */
11
+ const TASK_AUTH_AUTHENTICATE = "https://trusttasks.org/spec/auth/authenticate/0.1";
12
+ /**
13
+ * Log into a Trust-Tasks RP via SIOPv2 self-issuance. Returns the
14
+ * RP-issued session tokens. Throws on a transport error or an RP
15
+ * rejection (the error message carries the RP's response body).
16
+ */
17
+ export async function loginViaSiop(opts) {
18
+ const fetchFn = opts.fetch ?? fetch.bind(globalThis);
19
+ const base = opts.baseUrl.replace(/\/+$/, "");
20
+ const sw = createStopwatch();
21
+ // 1. Request a challenge nonce for the holder DID.
22
+ const challengeRes = await fetchFn(`${base}/auth/challenge`, {
23
+ method: "POST",
24
+ headers: { "content-type": "application/json" },
25
+ body: JSON.stringify({ did: opts.signing.did }),
26
+ });
27
+ if (!challengeRes.ok) {
28
+ throw new Error(`siop login: challenge failed (${challengeRes.status}): ${await challengeRes.text()}`);
29
+ }
30
+ // Canonical wire (spec/auth/challenge/0.1#response): flat
31
+ // { challenge, sessionId, expiresAt }. No `data` envelope.
32
+ const challenge = (await challengeRes.json());
33
+ sw.mark("challenge");
34
+ // 2. Self-issue the id_token — aud = the RP's DID, nonce = the challenge.
35
+ const idToken = issueIdToken({
36
+ identity: opts.signing,
37
+ audience: opts.rpDid,
38
+ nonce: challenge.challenge,
39
+ });
40
+ sw.mark("id_token signed");
41
+ // 3. Wrap in the RP's authenticate Trust-Task envelope.
42
+ const envelope = {
43
+ id: `urn:uuid:${globalThis.crypto.randomUUID()}`,
44
+ type: TASK_AUTH_AUTHENTICATE,
45
+ issuer: opts.signing.did,
46
+ issuedAt: new Date().toISOString(),
47
+ payload: {
48
+ id_token: idToken,
49
+ session_id: challenge.sessionId,
50
+ ...(opts.sessionPubkeyB58btc
51
+ ? { session_pubkey_b58btc: opts.sessionPubkeyB58btc }
52
+ : {}),
53
+ },
54
+ };
55
+ // 4. Exchange for a session JWT.
56
+ const authRes = await fetchFn(`${base}/auth/`, {
57
+ method: "POST",
58
+ headers: { "content-type": "application/json" },
59
+ body: JSON.stringify(envelope),
60
+ });
61
+ if (!authRes.ok) {
62
+ throw new Error(`siop login: authenticate failed (${authRes.status}): ${await authRes.text()}`);
63
+ }
64
+ // Canonical wire (spec/auth/authenticate/0.1#response):
65
+ // { session: Session, tokens: TokenBundle }. Session.id is the
66
+ // session identifier; tokens.{accessToken, refreshToken} carry
67
+ // the bearer material. `expiresIn` is seconds-from-issuance per
68
+ // RFC 6749 §5.1 — clients compute the absolute moment as
69
+ // Date.parse(session.issuedAt) + tokens.expiresIn * 1000.
70
+ const r = (await authRes.json());
71
+ sw.mark("authenticate");
72
+ return {
73
+ timings: sw.marks,
74
+ accessToken: r.tokens.accessToken,
75
+ refreshToken: r.tokens.refreshToken ?? "",
76
+ sessionId: r.session.id,
77
+ };
78
+ }
79
+ //# sourceMappingURL=login-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-client.js","sourceRoot":"","sources":["../../src/siop/login-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /** An Ed25519 `did:key` signing identity. `privateKey` is held in JS
2
+ * memory (the accepted trade-off for the no-passkey path — see the
3
+ * step-up flow for hardware-backed signing). */
4
+ export interface SigningIdentity {
5
+ /** `did:key:z6Mk…` */
6
+ did: string;
7
+ /** Verification-method id for the signing key (`<did>#z6Mk…`). */
8
+ kid: string;
9
+ privateKey: Uint8Array;
10
+ publicKey: Uint8Array;
11
+ }
12
+ /** Mint a fresh Ed25519 `did:key` signing identity. */
13
+ export declare function generateSigningIdentity(): SigningIdentity;
14
+ /** Reconstruct a signing identity from a stored Ed25519 private key. */
15
+ export declare function signingIdentityFromSecret(privateKey: Uint8Array): SigningIdentity;
16
+ export interface IssueIdTokenOptions {
17
+ identity: SigningIdentity;
18
+ /** RP identifier the token is bound to (`aud`) — its DID or client_id. */
19
+ audience: string;
20
+ /** RP-supplied nonce echoed in the token (replay protection). */
21
+ nonce: string;
22
+ /** Token lifetime in seconds (default 300). */
23
+ ttlSeconds?: number;
24
+ }
25
+ /**
26
+ * Issue a self-issued `id_token` (compact EdDSA JWS). `iss` and `sub`
27
+ * are the holder DID; the RP verifies by resolving that DID and checking
28
+ * the signature against its authentication key.
29
+ */
30
+ export declare function issueIdToken(opts: IssueIdTokenOptions): string;
31
+ export interface IssueSwapPresentationOptions {
32
+ /** The signing identity proving control of the **new** DID (the wallet's
33
+ * long-term holder did:peer, `#key-2`). The presentation's `holder` is its
34
+ * DID — what the swap creates the new ACL entry for. */
35
+ holder: SigningIdentity;
36
+ /** The VTA's DID — bound as `aud` so the proof can't be replayed elsewhere. */
37
+ audience: string;
38
+ /** Lifetime in seconds (default 300). */
39
+ ttlSeconds?: number;
40
+ /** Optional explicit nonce; a random one is generated when omitted. */
41
+ nonce?: string;
42
+ }
43
+ /**
44
+ * Issue a swap-acl presentation: a W3C Verifiable Presentation secured as a
45
+ * compact EdDSA JWS (VP-JWT), proving control of the holder DID. The VTA's
46
+ * `swap-acl` handler resolves `iss` and verifies this signature against the
47
+ * holder's key, then moves the caller's ACL entry onto it. Same signing
48
+ * primitive as {@link issueIdToken} — just a VP envelope instead of an
49
+ * id_token.
50
+ */
51
+ export declare function issueSwapPresentation(opts: IssueSwapPresentationOptions): string;
52
+ export interface VerifiedIdToken {
53
+ /** The holder DID that signed the token (`iss`/`sub`). */
54
+ did: string;
55
+ claims: {
56
+ iss: string;
57
+ sub: string;
58
+ aud: string;
59
+ nonce: string;
60
+ iat: number;
61
+ exp: number;
62
+ };
63
+ }
64
+ /**
65
+ * Verify a self-issued `id_token`: resolve the `did:key`, check the
66
+ * EdDSA signature against its authentication VM, and enforce
67
+ * `aud` / `nonce` / `exp`. Throws on any failure.
68
+ */
69
+ export declare function verifyIdToken(jwt: string, expect: {
70
+ audience: string;
71
+ nonce: string;
72
+ now?: number;
73
+ }): VerifiedIdToken;
74
+ /** The X25519 keyAgreement material derived from an Ed25519 signing
75
+ * identity, ready to build a DIDComm `Identity`. */
76
+ export interface DidcommKeyAgreement {
77
+ /** keyAgreement VM id (`<did>#<x25519-multibase>`), as the did:key resolver emits it. */
78
+ keyAgreementKid: string;
79
+ /** X25519 secret JWK ({kty:OKP, crv:X25519, x, d}). */
80
+ secretJwk: {
81
+ kty: "OKP";
82
+ crv: "X25519";
83
+ x: string;
84
+ d: string;
85
+ };
86
+ }
87
+ /**
88
+ * Derive the DIDComm X25519 keyAgreement material from an Ed25519
89
+ * {@link SigningIdentity}. The X25519 key is the Montgomery form of the
90
+ * same key — exactly as the `did:key` resolver derives the keyAgreement
91
+ * VM — so one Ed25519 `did:key` serves both login (signing) and DIDComm
92
+ * (authcrypt) under a single DID. The kid is taken from the resolver so
93
+ * it matches byte-for-byte what counterparties address replies to.
94
+ */
95
+ export declare function didcommKeyAgreementFromSigning(identity: SigningIdentity): DidcommKeyAgreement;
96
+ //# sourceMappingURL=self-issued.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-issued.d.ts","sourceRoot":"","sources":["../../src/siop/self-issued.ts"],"names":[],"mappings":"AAkBA;;iDAEiD;AACjD,MAAM,WAAW,eAAe;IAC9B,sBAAsB;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,kEAAkE;IAClE,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,uDAAuD;AACvD,wBAAgB,uBAAuB,IAAI,eAAe,CAIzD;AAED,wEAAwE;AACxE,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,UAAU,GAAG,eAAe,CAEjF;AAWD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,eAAe,CAAC;IAC1B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAc9D;AAED,MAAM,WAAW,4BAA4B;IAC3C;;6DAEyD;IACzD,MAAM,EAAE,eAAe,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,4BAA4B,GAAG,MAAM,CAoBhF;AAED,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD,eAAe,CAkCjB;AAqBD;qDACqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,yFAAyF;IACzF,eAAe,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,SAAS,EAAE;QAAE,GAAG,EAAE,KAAK,CAAC;QAAC,GAAG,EAAE,QAAQ,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChE;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,eAAe,GACxB,mBAAmB,CAmBrB"}
@@ -0,0 +1,162 @@
1
+ // Self-Issued OpenID Provider v2 (SIOPv2) — the wallet self-issues an
2
+ // `id_token` proving control of its `did:key`, which a Relying Party
3
+ // verifies by resolving the DID. No passwords, no per-site passkey, no
4
+ // round-trip to the VTA: the holder key signs locally and the DID is
5
+ // self-certifying (resolvable without any server).
6
+ //
7
+ // This is the base login primitive. A `did:key` here is an **Ed25519**
8
+ // key (multicodec 0xed01) because the credential must SIGN — an
9
+ // X25519-only `did:key` can only do ECDH (DIDComm authcrypt) and cannot
10
+ // produce a JWS. The same Ed25519 key also yields a derived X25519
11
+ // keyAgreement key for DIDComm (see did:key resolution), so one identity
12
+ // covers both login and DIDComm.
13
+ import { ed25519, x25519 } from "@noble/curves/ed25519.js";
14
+ import { base64url, didKey, multibase } from "@openvtc/vti-didcomm-js";
15
+ const ED25519_PUB = multibase.MULTICODEC.ED25519_PUB;
16
+ /** Mint a fresh Ed25519 `did:key` signing identity. */
17
+ export function generateSigningIdentity() {
18
+ const privateKey = ed25519.utils.randomSecretKey();
19
+ const publicKey = ed25519.getPublicKey(privateKey);
20
+ return signingIdentityFromKeys(privateKey, publicKey);
21
+ }
22
+ /** Reconstruct a signing identity from a stored Ed25519 private key. */
23
+ export function signingIdentityFromSecret(privateKey) {
24
+ return signingIdentityFromKeys(privateKey, ed25519.getPublicKey(privateKey));
25
+ }
26
+ function signingIdentityFromKeys(privateKey, publicKey) {
27
+ const mb = multibase.encodeMultikey(ED25519_PUB, publicKey);
28
+ const did = `did:key:${mb}`;
29
+ return { did, kid: `${did}#${mb}`, privateKey, publicKey };
30
+ }
31
+ /**
32
+ * Issue a self-issued `id_token` (compact EdDSA JWS). `iss` and `sub`
33
+ * are the holder DID; the RP verifies by resolving that DID and checking
34
+ * the signature against its authentication key.
35
+ */
36
+ export function issueIdToken(opts) {
37
+ const now = Math.floor(Date.now() / 1000);
38
+ const header = { alg: "EdDSA", typ: "JWT", kid: opts.identity.kid };
39
+ const payload = {
40
+ iss: opts.identity.did,
41
+ sub: opts.identity.did,
42
+ aud: opts.audience,
43
+ nonce: opts.nonce,
44
+ iat: now,
45
+ exp: now + (opts.ttlSeconds ?? 300),
46
+ };
47
+ const signingInput = `${b64uJson(header)}.${b64uJson(payload)}`;
48
+ const sig = ed25519.sign(new TextEncoder().encode(signingInput), opts.identity.privateKey);
49
+ return `${signingInput}.${base64url.encode(sig)}`;
50
+ }
51
+ /**
52
+ * Issue a swap-acl presentation: a W3C Verifiable Presentation secured as a
53
+ * compact EdDSA JWS (VP-JWT), proving control of the holder DID. The VTA's
54
+ * `swap-acl` handler resolves `iss` and verifies this signature against the
55
+ * holder's key, then moves the caller's ACL entry onto it. Same signing
56
+ * primitive as {@link issueIdToken} — just a VP envelope instead of an
57
+ * id_token.
58
+ */
59
+ export function issueSwapPresentation(opts) {
60
+ const now = Math.floor(Date.now() / 1000);
61
+ const nonce = opts.nonce ?? base64url.encode(globalThis.crypto.getRandomValues(new Uint8Array(16)));
62
+ const header = { alg: "EdDSA", typ: "JWT", kid: opts.holder.kid };
63
+ const payload = {
64
+ iss: opts.holder.did,
65
+ aud: opts.audience,
66
+ iat: now,
67
+ exp: now + (opts.ttlSeconds ?? 300),
68
+ nonce,
69
+ vp: {
70
+ "@context": ["https://www.w3.org/ns/credentials/v2"],
71
+ type: ["VerifiablePresentation", "AclSwapRequest"],
72
+ holder: opts.holder.did,
73
+ },
74
+ };
75
+ const signingInput = `${b64uJson(header)}.${b64uJson(payload)}`;
76
+ const sig = ed25519.sign(new TextEncoder().encode(signingInput), opts.holder.privateKey);
77
+ return `${signingInput}.${base64url.encode(sig)}`;
78
+ }
79
+ /**
80
+ * Verify a self-issued `id_token`: resolve the `did:key`, check the
81
+ * EdDSA signature against its authentication VM, and enforce
82
+ * `aud` / `nonce` / `exp`. Throws on any failure.
83
+ */
84
+ export function verifyIdToken(jwt, expect) {
85
+ const parts = jwt.split(".");
86
+ if (parts.length !== 3)
87
+ throw new Error("siop: malformed JWS (expected 3 parts)");
88
+ const [h, p, s] = parts;
89
+ const header = jsonFromB64u(h);
90
+ if (header.alg !== "EdDSA") {
91
+ throw new Error(`siop: unsupported alg ${JSON.stringify(header.alg)}; expected EdDSA`);
92
+ }
93
+ const claims = jsonFromB64u(p);
94
+ if (typeof claims.iss !== "string" || claims.iss !== claims.sub) {
95
+ throw new Error("siop: iss/sub missing or mismatched (must be the self-issued DID)");
96
+ }
97
+ // Resolve the DID and pull its authentication signing key.
98
+ const signingKey = ed25519AuthKey(claims.iss);
99
+ const ok = ed25519.verify(base64url.decode(s), new TextEncoder().encode(`${h}.${p}`), signingKey);
100
+ if (!ok)
101
+ throw new Error("siop: signature does not verify against the DID's key");
102
+ if (claims.aud !== expect.audience) {
103
+ throw new Error(`siop: aud ${JSON.stringify(claims.aud)} != ${JSON.stringify(expect.audience)}`);
104
+ }
105
+ if (claims.nonce !== expect.nonce) {
106
+ throw new Error("siop: nonce mismatch (possible replay)");
107
+ }
108
+ const now = expect.now ?? Math.floor(Date.now() / 1000);
109
+ if (typeof claims.exp !== "number" || claims.exp < now) {
110
+ throw new Error("siop: token expired");
111
+ }
112
+ return { did: claims.iss, claims };
113
+ }
114
+ /** Resolve a `did:key` and return its Ed25519 authentication key bytes. */
115
+ function ed25519AuthKey(did) {
116
+ const doc = didKey.resolve(did).didDocument;
117
+ const authId = doc.authentication?.[0];
118
+ if (!authId)
119
+ throw new Error(`siop: ${did} has no authentication method (not a signing DID)`);
120
+ const vm = (doc.verificationMethod ?? []).find((v) => v.id === authId);
121
+ if (!vm?.publicKeyMultibase) {
122
+ throw new Error("siop: authentication VM missing publicKeyMultibase");
123
+ }
124
+ const { codec, key } = multibase.decodeMultikey(vm.publicKeyMultibase);
125
+ if (codec[0] !== ED25519_PUB[0] || codec[1] !== ED25519_PUB[1]) {
126
+ throw new Error("siop: authentication key is not Ed25519");
127
+ }
128
+ return key;
129
+ }
130
+ /**
131
+ * Derive the DIDComm X25519 keyAgreement material from an Ed25519
132
+ * {@link SigningIdentity}. The X25519 key is the Montgomery form of the
133
+ * same key — exactly as the `did:key` resolver derives the keyAgreement
134
+ * VM — so one Ed25519 `did:key` serves both login (signing) and DIDComm
135
+ * (authcrypt) under a single DID. The kid is taken from the resolver so
136
+ * it matches byte-for-byte what counterparties address replies to.
137
+ */
138
+ export function didcommKeyAgreementFromSigning(identity) {
139
+ const xPriv = ed25519.utils.toMontgomerySecret(identity.privateKey);
140
+ const xPub = x25519.getPublicKey(xPriv);
141
+ const doc = didKey.resolve(identity.did).didDocument;
142
+ const keyAgreementKid = doc.keyAgreement?.[0];
143
+ if (!keyAgreementKid) {
144
+ throw new Error("siop: Ed25519 did:key has no keyAgreement VM");
145
+ }
146
+ return {
147
+ keyAgreementKid,
148
+ secretJwk: {
149
+ kty: "OKP",
150
+ crv: "X25519",
151
+ x: base64url.encode(xPub),
152
+ d: base64url.encode(xPriv),
153
+ },
154
+ };
155
+ }
156
+ function b64uJson(value) {
157
+ return base64url.encode(new TextEncoder().encode(JSON.stringify(value)));
158
+ }
159
+ function jsonFromB64u(segment) {
160
+ return JSON.parse(new TextDecoder().decode(base64url.decode(segment)));
161
+ }
162
+ //# sourceMappingURL=self-issued.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-issued.js","sourceRoot":"","sources":["../../src/siop/self-issued.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,241 @@
1
+ import { Identity } from "../didcomm/index.js";
2
+ import type { SigningIdentity } from "../siop/index.js";
3
+ import type { KVStore } from "./kv-store.js";
4
+ import { type SecretWrap } from "./secret-wrap.js";
5
+ export interface HolderIdentityResult {
6
+ /** DIDComm key-agreement identity (X25519, `#key-1`) — used for authcrypt. */
7
+ identity: Identity;
8
+ /** Signing identity (Ed25519, `#key-2`) — self-issues SIOPv2 login
9
+ * `id_token`s and signs trust-task proofs. `.did` is the did:peer. */
10
+ signing: SigningIdentity;
11
+ /** True if this run minted a fresh identity (first launch); false if loaded. */
12
+ freshlyMinted: boolean;
13
+ }
14
+ export interface HolderIdentityOptions {
15
+ /** When set, the minted DID advertises a `DIDCommMessaging` service whose
16
+ * endpoint is this mediator DID — making the wallet reachable for inbound
17
+ * DIDComm. Only honoured on a FRESH mint (the persisted DID is immutable).
18
+ * Omit to mint a keys-only did:peer (sufficient for outbound login). */
19
+ mediatorDid?: string;
20
+ /**
21
+ * H1: encryption wrapper for the persisted Ed25519 secret.
22
+ * When supplied, fresh mints write `wrappedSecret` instead of
23
+ * `edSecretB64u`, and existing wallets stored with a matching
24
+ * wrap require the wrap on load to decrypt.
25
+ *
26
+ * Omit (or supply `PassthroughWrap`) for tests and legacy
27
+ * callers. Production extension wrappers supply a
28
+ * `WebAuthnPrfSecretWrap` so an exfiltrated IndexedDB row is
29
+ * useless without the operator's authenticator.
30
+ *
31
+ * Backward compatibility: a record written before this option
32
+ * landed (no `wrappedSecret`, plaintext `edSecretB64u`) loads
33
+ * regardless of whether a wrap is supplied — the loader
34
+ * detects the legacy shape and reads the plaintext. The
35
+ * **next save** (e.g. mediator-DID rotation, future schema
36
+ * upgrade) will re-persist using the wrap, migrating the
37
+ * record forward.
38
+ */
39
+ secretWrap?: SecretWrap;
40
+ }
41
+ /**
42
+ * Generate-or-load the wallet's holder identity (a `did:peer:2`) from a
43
+ * `KVStore`. Only the Ed25519 secret is persisted; the DID + kids are
44
+ * persisted alongside it (the DID is immutable once minted), and the X25519
45
+ * keyAgreement key is re-derived on every load.
46
+ *
47
+ * Persistence is wrapped via the optional [`HolderIdentityOptions.secretWrap`]
48
+ * — production extensions supply a `WebAuthnPrfSecretWrap` so storage
49
+ * exfil yields ciphertext, not the wallet's signing key. Callers that
50
+ * omit the wrap fall back to plaintext (legacy behaviour); the
51
+ * loader handles both shapes for backward compatibility.
52
+ */
53
+ export declare function generateOrLoadHolderIdentity(store: KVStore, opts?: HolderIdentityOptions): Promise<HolderIdentityResult>;
54
+ /** Forget every persisted holder identity. Mostly for tests / hard
55
+ * reset (the options page "wipe wallet" button). Clears the v3 row,
56
+ * the legacy single-VTA v4 row, AND every per-vta v4 record. After
57
+ * this the wallet looks freshly installed at every VTA. */
58
+ export declare function clearHolderIdentity(store: KVStore): Promise<void>;
59
+ /** Thrown by `loadHolderStrict` when neither a v3 nor a v4 holder record
60
+ * exists — the wallet is on a fresh install and the operator should
61
+ * proceed with onboarding. */
62
+ export declare class NoHolderError extends Error {
63
+ constructor();
64
+ }
65
+ /** Thrown by `loadHolderStrict` when a v3 (self-derived did:peer) record
66
+ * exists but no v4 (VTA-minted did:key) record. The wallet was built
67
+ * before the M2C identity migration; the operator must re-onboard so the
68
+ * VTA mints a fresh long-term DID. The old did:peer is unusable as the
69
+ * wallet's holder going forward — every RP that recognised it must be
70
+ * re-granted with the new VTA-minted DID.
71
+ *
72
+ * `previousDid` is the v3 DID, surfaced for the migration UI so the
73
+ * operator can audit what they're abandoning. */
74
+ export declare class RequiresReonboardError extends Error {
75
+ readonly previousDid: string;
76
+ constructor(previousDid: string);
77
+ }
78
+ export interface LoadHolderStrictOptions {
79
+ /** Which VTA's holder identity to load. Each VTA the wallet has been
80
+ * onboarded at has its own per-VTA holder record (the v4 schema is
81
+ * multi-instance — one record per VTA). Pass the VTA DID the
82
+ * operation is targeting; the store contains exactly one v4 record
83
+ * per `(vtaDid)` pair. */
84
+ vtaDid: string;
85
+ /** Wrap that decrypts the persisted Ed25519 seed. Same semantics as
86
+ * `HolderIdentityOptions.secretWrap` — omit for plaintext (tests /
87
+ * legacy), supply a `WebAuthnPrfSecretWrap` in production. */
88
+ secretWrap?: SecretWrap;
89
+ }
90
+ /** Load the wallet's holder identity for the given VTA, strictly
91
+ * preferring v4.
92
+ *
93
+ * - v4 record for `vtaDid` present → return the VTA-minted holder.
94
+ * - no v4 record for `vtaDid` but a legacy single-VTA v4 record
95
+ * exists → migrate it to the per-vta path (transparently) and
96
+ * return if its `vtaDid` matches the requested one.
97
+ * - no v4 (for `vtaDid` or legacy) but v3 present → throw
98
+ * `RequiresReonboardError` (the operator needs to re-onboard so the
99
+ * VTA mints a v4 identity).
100
+ * - none of the above → throw `NoHolderError` (fresh install). */
101
+ export declare function loadHolderStrict(store: KVStore, opts: LoadHolderStrictOptions): Promise<HolderIdentityResult>;
102
+ export interface InstallVtaMintedHolderOptions {
103
+ /** The freshly-minted did:key the VTA shipped (e.g. `did:key:z6Mk…`). */
104
+ did: string;
105
+ /** Ed25519 verification-method id (`<did>#<ed-mb>`). The VTA's
106
+ * template renderer emits this; for `vta-admin` the fragment is the
107
+ * Ed25519 public-key multibase. */
108
+ signingKid: string;
109
+ /** X25519 keyAgreement verification-method id (`<did>#<x-mb>`).
110
+ * Derived from the Ed25519 pubkey via Montgomery clamping; the VTA
111
+ * also emits this in the sealed bundle. */
112
+ keyAgreementKid: string;
113
+ /** 32-byte Ed25519 seed the VTA minted and shipped sealed. The wallet
114
+ * decoded it from the bundle's `admin.signing_key.private_key_multibase`. */
115
+ edSeed: Uint8Array;
116
+ /** Provenance — the VTA that minted this identity. */
117
+ vtaDid: string;
118
+ /** VTA's REST base URL, if advertised. */
119
+ vtaUrl?: string;
120
+ /** Optional secret wrap. Production extensions supply a
121
+ * WebAuthnPrfSecretWrap; tests omit. */
122
+ secretWrap?: SecretWrap;
123
+ }
124
+ /** Persist a freshly-minted VTA holder as the wallet's v4 identity.
125
+ *
126
+ * Returns the rebuilt `HolderIdentityResult` so the caller can use the
127
+ * identity immediately without an extra load. Clears any pre-existing
128
+ * v3 record on a successful install — the migration is a one-way move
129
+ * and a stale v3 record sitting alongside v4 is just a footgun for a
130
+ * future loader. */
131
+ export declare function installVtaMintedHolder(store: KVStore, opts: InstallVtaMintedHolderOptions): Promise<HolderIdentityResult>;
132
+ export interface RewrapHolderV4Options {
133
+ /** Which VTA's holder record to re-wrap. Multi-VTA: each VTA has
134
+ * its own v4 record; the rewrap targets exactly one. */
135
+ vtaDid: string;
136
+ /** Wrap that DECRYPTS the currently-persisted v4 record. Pass the
137
+ * wrap the wallet was using before the migration. Pass `undefined`
138
+ * when the existing record uses `PassthroughWrap` (plaintext),
139
+ * which is the typical post-onboard state. */
140
+ fromWrap?: SecretWrap;
141
+ /** Wrap to apply on the re-persisted record. Pass the wrap the
142
+ * wallet should use going forward (e.g. a `WebAuthnPrfSecretWrap`
143
+ * in the popup's visible context). Pass `undefined` to switch
144
+ * back to plaintext. */
145
+ toWrap?: SecretWrap;
146
+ }
147
+ /** Re-wrap the persisted v4 holder secret in place, preserving the
148
+ * wallet's DID + verification-method ids + VTA provenance.
149
+ *
150
+ * The canonical caller is the popup's post-onboard "Encrypt your
151
+ * wallet?" prompt: the operator clicks the button, the popup runs
152
+ * `navigator.credentials.create` (visible context, fresh user
153
+ * gesture), and re-wraps the existing passthrough record under
154
+ * the PRF-derived AES-GCM key. The wallet DID stays the same — no
155
+ * re-grant in any RP ACL, no re-onboarding.
156
+ *
157
+ * Mirrors the v3 `rewrapHolderSecret` but reads + writes the v4
158
+ * record (`STORE_KEY_V4`). Future cleanup could consolidate the
159
+ * two into one schema-version-aware function; kept separate for
160
+ * now so the v3 path's legacy `edSecretB64u` fallback doesn't
161
+ * leak into v4's cleaner shape.
162
+ *
163
+ * Throws if no v4 record exists. The popup should only invoke this
164
+ * AFTER `installVtaMintedHolder` has run. */
165
+ export declare function rewrapHolderV4Secret(store: KVStore, opts: RewrapHolderV4Options): Promise<HolderIdentityResult>;
166
+ export type HolderIdentityStateResult = {
167
+ kind: "none";
168
+ } | {
169
+ kind: "v3";
170
+ did: string;
171
+ } | {
172
+ kind: "v4";
173
+ did: string;
174
+ vtaDid: string;
175
+ wrapAlgorithm: string;
176
+ };
177
+ /** Inspect the persisted state without throwing. Used by the popup to
178
+ * decide which onboarding screen to show.
179
+ *
180
+ * For v4 records, `wrapAlgorithm` reveals whether the secret is
181
+ * encrypted at rest. `"passthrough"` means plaintext (the operator
182
+ * hasn't enabled encryption); anything else (currently only
183
+ * `"webauthn-prf-aes-gcm"`) means the popup needs to run an
184
+ * unlock ceremony before offscreen can load the holder identity.
185
+ *
186
+ * When `vtaDid` is passed: returns the state for that specific
187
+ * VTA's holder record. Used by the popup's active-VTA probe.
188
+ * When `vtaDid` is omitted: returns the first v4 record found
189
+ * (after migrating any legacy single-VTA row), else falls back to
190
+ * v3 / none. Used for the initial fresh-install / migration-banner
191
+ * decision before an active VTA has been selected. */
192
+ export declare function holderIdentityState(store: KVStore, vtaDid?: string): Promise<HolderIdentityStateResult>;
193
+ export interface HolderRecordSummary {
194
+ vtaDid: string;
195
+ did: string;
196
+ /** Encryption algorithm of the persisted secret. `"passthrough"` =
197
+ * plaintext at rest. */
198
+ wrapAlgorithm: string;
199
+ }
200
+ /** Enumerate every v4 holder record on disk — one per VTA the wallet
201
+ * has been onboarded at. Powers the popup's multi-VTA dropdown
202
+ * (PR 2). Migrates the legacy single-VTA row inline so a wallet
203
+ * upgraded from a single-VTA build surfaces its one wallet here. */
204
+ export declare function listHolderRecords(store: KVStore): Promise<HolderRecordSummary[]>;
205
+ /** Delete the v4 holder record for a specific VTA. Companion to
206
+ * `installVtaMintedHolder`. Idempotent: a no-op when the record is
207
+ * already gone. Other VTAs' records are left alone — call
208
+ * `clearHolderIdentity` to wipe every wallet on this device. */
209
+ export declare function forgetHolderRecord(store: KVStore, vtaDid: string): Promise<void>;
210
+ export interface RewrapOptions {
211
+ /**
212
+ * Wrap that decrypts the currently-persisted secret. Pass the
213
+ * wrap the wallet was using before the migration (or `undefined`
214
+ * if it was plaintext).
215
+ */
216
+ fromWrap?: SecretWrap;
217
+ /**
218
+ * Wrap to apply on the re-persisted record. Pass the wrap the
219
+ * wallet should use going forward (or `undefined` to switch back
220
+ * to plaintext).
221
+ */
222
+ toWrap?: SecretWrap;
223
+ }
224
+ /**
225
+ * Re-wrap the persisted holder secret in place, preserving the
226
+ * wallet's DID + verification-method ids + mediator endpoint.
227
+ *
228
+ * Used by the extension's settings UI when the operator flips
229
+ * the `encryptHolderSecret` toggle — the existing wallet keeps
230
+ * its identity (no re-grant in any RP ACL) but the on-disk
231
+ * secret transitions between plaintext and wrap-encrypted.
232
+ *
233
+ * Returns the rebuilt `HolderIdentityResult` so the caller can
234
+ * report the (unchanged) DID back to the operator immediately.
235
+ *
236
+ * Errors if no persisted record exists — caller should check
237
+ * `freshlyMinted` semantics first (a fresh-mint wallet has no
238
+ * pre-existing secret to re-wrap).
239
+ */
240
+ export declare function rewrapHolderSecret(store: KVStore, opts: RewrapOptions): Promise<HolderIdentityResult>;
241
+ //# sourceMappingURL=holder-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"holder-identity.d.ts","sourceRoot":"","sources":["../../src/store/holder-identity.ts"],"names":[],"mappings":"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"}