@interop/was-react 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 (223) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +410 -0
  3. package/dist/auth/chapi.d.ts +43 -0
  4. package/dist/auth/chapi.d.ts.map +1 -0
  5. package/dist/auth/chapi.js +107 -0
  6. package/dist/auth/chapi.js.map +1 -0
  7. package/dist/auth/loginFlow.d.ts +93 -0
  8. package/dist/auth/loginFlow.d.ts.map +1 -0
  9. package/dist/auth/loginFlow.js +149 -0
  10. package/dist/auth/loginFlow.js.map +1 -0
  11. package/dist/auth/loginRequest.d.ts +66 -0
  12. package/dist/auth/loginRequest.d.ts.map +1 -0
  13. package/dist/auth/loginRequest.js +83 -0
  14. package/dist/auth/loginRequest.js.map +1 -0
  15. package/dist/auth/verifyResponse.d.ts +52 -0
  16. package/dist/auth/verifyResponse.d.ts.map +1 -0
  17. package/dist/auth/verifyResponse.js +138 -0
  18. package/dist/auth/verifyResponse.js.map +1 -0
  19. package/dist/auth/verifyResponse.test.d.ts +2 -0
  20. package/dist/auth/verifyResponse.test.d.ts.map +1 -0
  21. package/dist/auth/verifyResponse.test.js +282 -0
  22. package/dist/auth/verifyResponse.test.js.map +1 -0
  23. package/dist/auth/walletRequestTypes.d.ts +143 -0
  24. package/dist/auth/walletRequestTypes.d.ts.map +1 -0
  25. package/dist/auth/walletRequestTypes.js +2 -0
  26. package/dist/auth/walletRequestTypes.js.map +1 -0
  27. package/dist/config.d.ts +150 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +27 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/dev/cli.d.ts +16 -0
  32. package/dist/dev/cli.d.ts.map +1 -0
  33. package/dist/dev/cli.js +122 -0
  34. package/dist/dev/cli.js.map +1 -0
  35. package/dist/dev/cli.test.d.ts +2 -0
  36. package/dist/dev/cli.test.d.ts.map +1 -0
  37. package/dist/dev/cli.test.js +39 -0
  38. package/dist/dev/cli.test.js.map +1 -0
  39. package/dist/dev/index.d.ts +10 -0
  40. package/dist/dev/index.d.ts.map +1 -0
  41. package/dist/dev/index.js +10 -0
  42. package/dist/dev/index.js.map +1 -0
  43. package/dist/dev/provisionDevGrants.d.ts +73 -0
  44. package/dist/dev/provisionDevGrants.d.ts.map +1 -0
  45. package/dist/dev/provisionDevGrants.js +176 -0
  46. package/dist/dev/provisionDevGrants.js.map +1 -0
  47. package/dist/grants.d.ts +59 -0
  48. package/dist/grants.d.ts.map +1 -0
  49. package/dist/grants.js +82 -0
  50. package/dist/grants.js.map +1 -0
  51. package/dist/grants.test.d.ts +2 -0
  52. package/dist/grants.test.d.ts.map +1 -0
  53. package/dist/grants.test.js +79 -0
  54. package/dist/grants.test.js.map +1 -0
  55. package/dist/identity/agents.d.ts +99 -0
  56. package/dist/identity/agents.d.ts.map +1 -0
  57. package/dist/identity/agents.js +132 -0
  58. package/dist/identity/agents.js.map +1 -0
  59. package/dist/identity/appSession.d.ts +78 -0
  60. package/dist/identity/appSession.d.ts.map +1 -0
  61. package/dist/identity/appSession.js +93 -0
  62. package/dist/identity/appSession.js.map +1 -0
  63. package/dist/identity/documentLoader.d.ts +20 -0
  64. package/dist/identity/documentLoader.d.ts.map +1 -0
  65. package/dist/identity/documentLoader.js +99 -0
  66. package/dist/identity/documentLoader.js.map +1 -0
  67. package/dist/identity/initAppSession.d.ts +27 -0
  68. package/dist/identity/initAppSession.d.ts.map +1 -0
  69. package/dist/identity/initAppSession.js +30 -0
  70. package/dist/identity/initAppSession.js.map +1 -0
  71. package/dist/identity/seedCredential.d.ts +74 -0
  72. package/dist/identity/seedCredential.d.ts.map +1 -0
  73. package/dist/identity/seedCredential.js +165 -0
  74. package/dist/identity/seedCredential.js.map +1 -0
  75. package/dist/identity/seedCredential.test.d.ts +2 -0
  76. package/dist/identity/seedCredential.test.d.ts.map +1 -0
  77. package/dist/identity/seedCredential.test.js +205 -0
  78. package/dist/identity/seedCredential.test.js.map +1 -0
  79. package/dist/identity/seedStore.d.ts +27 -0
  80. package/dist/identity/seedStore.d.ts.map +1 -0
  81. package/dist/identity/seedStore.js +74 -0
  82. package/dist/identity/seedStore.js.map +1 -0
  83. package/dist/index.d.ts +37 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +46 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/mui/ProtectedRoute.d.ts +10 -0
  88. package/dist/mui/ProtectedRoute.d.ts.map +1 -0
  89. package/dist/mui/ProtectedRoute.js +54 -0
  90. package/dist/mui/ProtectedRoute.js.map +1 -0
  91. package/dist/mui/ReconnectBanner.d.ts +2 -0
  92. package/dist/mui/ReconnectBanner.d.ts.map +1 -0
  93. package/dist/mui/ReconnectBanner.js +20 -0
  94. package/dist/mui/ReconnectBanner.js.map +1 -0
  95. package/dist/mui/SyncStatusChip.d.ts +2 -0
  96. package/dist/mui/SyncStatusChip.d.ts.map +1 -0
  97. package/dist/mui/SyncStatusChip.js +27 -0
  98. package/dist/mui/SyncStatusChip.js.map +1 -0
  99. package/dist/mui/index.d.ts +12 -0
  100. package/dist/mui/index.d.ts.map +1 -0
  101. package/dist/mui/index.js +12 -0
  102. package/dist/mui/index.js.map +1 -0
  103. package/dist/react/WasSessionProvider.d.ts +36 -0
  104. package/dist/react/WasSessionProvider.d.ts.map +1 -0
  105. package/dist/react/WasSessionProvider.js +35 -0
  106. package/dist/react/WasSessionProvider.js.map +1 -0
  107. package/dist/react/hooks.d.ts +66 -0
  108. package/dist/react/hooks.d.ts.map +1 -0
  109. package/dist/react/hooks.js +121 -0
  110. package/dist/react/hooks.js.map +1 -0
  111. package/dist/react/index.d.ts +11 -0
  112. package/dist/react/index.d.ts.map +1 -0
  113. package/dist/react/index.js +11 -0
  114. package/dist/react/index.js.map +1 -0
  115. package/dist/session/appReadyStore.d.ts +10 -0
  116. package/dist/session/appReadyStore.d.ts.map +1 -0
  117. package/dist/session/appReadyStore.js +22 -0
  118. package/dist/session/appReadyStore.js.map +1 -0
  119. package/dist/session/authStore.d.ts +71 -0
  120. package/dist/session/authStore.d.ts.map +1 -0
  121. package/dist/session/authStore.js +347 -0
  122. package/dist/session/authStore.js.map +1 -0
  123. package/dist/session/index.d.ts +10 -0
  124. package/dist/session/index.d.ts.map +1 -0
  125. package/dist/session/index.js +10 -0
  126. package/dist/session/index.js.map +1 -0
  127. package/dist/storage/entityStore.d.ts +51 -0
  128. package/dist/storage/entityStore.d.ts.map +1 -0
  129. package/dist/storage/entityStore.js +78 -0
  130. package/dist/storage/entityStore.js.map +1 -0
  131. package/dist/storage/localStore.d.ts +144 -0
  132. package/dist/storage/localStore.d.ts.map +1 -0
  133. package/dist/storage/localStore.js +289 -0
  134. package/dist/storage/localStore.js.map +1 -0
  135. package/dist/storage/rehydrate.d.ts +56 -0
  136. package/dist/storage/rehydrate.d.ts.map +1 -0
  137. package/dist/storage/rehydrate.js +87 -0
  138. package/dist/storage/rehydrate.js.map +1 -0
  139. package/dist/storage/rehydrate.test.d.ts +2 -0
  140. package/dist/storage/rehydrate.test.d.ts.map +1 -0
  141. package/dist/storage/rehydrate.test.js +172 -0
  142. package/dist/storage/rehydrate.test.js.map +1 -0
  143. package/dist/storage/storageManager.d.ts +39 -0
  144. package/dist/storage/storageManager.d.ts.map +1 -0
  145. package/dist/storage/storageManager.js +68 -0
  146. package/dist/storage/storageManager.js.map +1 -0
  147. package/dist/storage/syncController.d.ts +79 -0
  148. package/dist/storage/syncController.d.ts.map +1 -0
  149. package/dist/storage/syncController.js +189 -0
  150. package/dist/storage/syncController.js.map +1 -0
  151. package/dist/storage/syncStatusStore.d.ts +17 -0
  152. package/dist/storage/syncStatusStore.d.ts.map +1 -0
  153. package/dist/storage/syncStatusStore.js +19 -0
  154. package/dist/storage/syncStatusStore.js.map +1 -0
  155. package/dist/storage/wasRemoteStore.d.ts +73 -0
  156. package/dist/storage/wasRemoteStore.d.ts.map +1 -0
  157. package/dist/storage/wasRemoteStore.js +76 -0
  158. package/dist/storage/wasRemoteStore.js.map +1 -0
  159. package/dist/storage/wasSync.d.ts +42 -0
  160. package/dist/storage/wasSync.d.ts.map +1 -0
  161. package/dist/storage/wasSync.js +34 -0
  162. package/dist/storage/wasSync.js.map +1 -0
  163. package/dist/sync/changesQuery.d.ts +44 -0
  164. package/dist/sync/changesQuery.d.ts.map +1 -0
  165. package/dist/sync/changesQuery.js +61 -0
  166. package/dist/sync/changesQuery.js.map +1 -0
  167. package/dist/sync/changesQuery.test.d.ts +2 -0
  168. package/dist/sync/changesQuery.test.d.ts.map +1 -0
  169. package/dist/sync/changesQuery.test.js +145 -0
  170. package/dist/sync/changesQuery.test.js.map +1 -0
  171. package/dist/sync/docCipher.d.ts +68 -0
  172. package/dist/sync/docCipher.d.ts.map +1 -0
  173. package/dist/sync/docCipher.js +89 -0
  174. package/dist/sync/docCipher.js.map +1 -0
  175. package/dist/sync/feedMasterPort.d.ts +30 -0
  176. package/dist/sync/feedMasterPort.d.ts.map +1 -0
  177. package/dist/sync/feedMasterPort.js +58 -0
  178. package/dist/sync/feedMasterPort.js.map +1 -0
  179. package/dist/sync/index.d.ts +21 -0
  180. package/dist/sync/index.d.ts.map +1 -0
  181. package/dist/sync/index.js +21 -0
  182. package/dist/sync/index.js.map +1 -0
  183. package/dist/sync/lww.d.ts +29 -0
  184. package/dist/sync/lww.d.ts.map +1 -0
  185. package/dist/sync/lww.js +28 -0
  186. package/dist/sync/lww.js.map +1 -0
  187. package/dist/sync/lww.test.d.ts +2 -0
  188. package/dist/sync/lww.test.d.ts.map +1 -0
  189. package/dist/sync/lww.test.js +28 -0
  190. package/dist/sync/lww.test.js.map +1 -0
  191. package/dist/sync/lwwConflictHandler.d.ts +49 -0
  192. package/dist/sync/lwwConflictHandler.d.ts.map +1 -0
  193. package/dist/sync/lwwConflictHandler.js +65 -0
  194. package/dist/sync/lwwConflictHandler.js.map +1 -0
  195. package/dist/sync/lwwConflictHandler.test.d.ts +2 -0
  196. package/dist/sync/lwwConflictHandler.test.d.ts.map +1 -0
  197. package/dist/sync/lwwConflictHandler.test.js +78 -0
  198. package/dist/sync/lwwConflictHandler.test.js.map +1 -0
  199. package/dist/sync/pushWrites.d.ts +57 -0
  200. package/dist/sync/pushWrites.d.ts.map +1 -0
  201. package/dist/sync/pushWrites.js +159 -0
  202. package/dist/sync/pushWrites.js.map +1 -0
  203. package/dist/sync/pushWrites.test.d.ts +2 -0
  204. package/dist/sync/pushWrites.test.d.ts.map +1 -0
  205. package/dist/sync/pushWrites.test.js +287 -0
  206. package/dist/sync/pushWrites.test.js.map +1 -0
  207. package/dist/sync/syncedDocSchema.d.ts +22 -0
  208. package/dist/sync/syncedDocSchema.d.ts.map +1 -0
  209. package/dist/sync/syncedDocSchema.js +26 -0
  210. package/dist/sync/syncedDocSchema.js.map +1 -0
  211. package/dist/sync/types.d.ts +194 -0
  212. package/dist/sync/types.d.ts.map +1 -0
  213. package/dist/sync/types.js +36 -0
  214. package/dist/sync/types.js.map +1 -0
  215. package/dist/sync/wasReplication.d.ts +47 -0
  216. package/dist/sync/wasReplication.d.ts.map +1 -0
  217. package/dist/sync/wasReplication.js +55 -0
  218. package/dist/sync/wasReplication.js.map +1 -0
  219. package/dist/sync/wasSyncPort.d.ts +45 -0
  220. package/dist/sync/wasSyncPort.d.ts.map +1 -0
  221. package/dist/sync/wasSyncPort.js +170 -0
  222. package/dist/sync/wasSyncPort.js.map +1 -0
  223. package/package.json +142 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loginFlow.d.ts","sourceRoot":"","sources":["../../src/auth/loginFlow.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,EAKL,KAAK,oBAAoB,EAC1B,MAAM,+BAA+B,CAAA;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAO3D,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAA;IACjB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,4DAA4D;IAC5D,UAAU,EAAE,oBAAoB,CAAA;IAChC,gEAAgE;IAChE,cAAc,EAAE,cAAc,CAAA;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,sEAAsE;AACtE,MAAM,MAAM,UAAU,GACpB,SAAS,GAAG,aAAa,GAAG,mBAAmB,GAAG,WAAW,CAAA;AAE/D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,cAAc,CAAA;IACxB,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,MAAM,EAAE,YAAY,CAAA;IACpB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAA;IACf,kEAAkE;IAClE,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,6DAA6D;AAC7D,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,IAAI,EAAE,MAAM;CAIzB;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,EAClC,QAAQ,EACR,MAAM,EACN,OAAO,EACR,EAAE;IACD,QAAQ,EAAE,cAAc,CAAA;IACxB,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;CACtC,GAAG,OAAO,CAAC,aAAa,CAAC,CAkCzB;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,EACpC,MAAM,EACN,OAAO,EACR,EAAE;IACD,MAAM,EAAE,WAAW,CAAA;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;CACtC,GAAG,OAAO,CAAC,YAAY,CAAC,CAiFxB"}
@@ -0,0 +1,149 @@
1
+ import { findSeedCredential, issueSeedCredential, parseSeedCredential, wrapCredentialForStore } from '../identity/seedCredential.js';
2
+ import { initAppSession } from '../identity/initAppSession.js';
3
+ import { chapiGet, chapiStore } from './chapi.js';
4
+ import { buildGrantsVpr, buildSeedProbeVpr, newChallenge } from './loginRequest.js';
5
+ import { checkGrants, grantsOf, verifyLoginPresentation } from './verifyResponse.js';
6
+ /** Thrown when the user cancels/dismisses a wallet popup. */
7
+ export class LoginCancelledError extends Error {
8
+ constructor(step) {
9
+ super(`The wallet request was cancelled (${step}).`);
10
+ this.name = 'LoginCancelledError';
11
+ }
12
+ }
13
+ /**
14
+ * Requests storage grants for `identity` and validates them. Shared by the
15
+ * login flow and the expired-access reconnect path.
16
+ *
17
+ * @param options {object}
18
+ * @param options.identity {IdentityAgents}
19
+ * @param options.config {LoginConfig}
20
+ * @param [options.onPhase] {Function}
21
+ * @returns {Promise<CheckedGrants>}
22
+ */
23
+ export async function requestGrants({ identity, config, onPhase }) {
24
+ onPhase?.('requesting-grants');
25
+ const challenge = newChallenge();
26
+ const vpr = buildGrantsVpr({
27
+ challenge,
28
+ domain: window.location.origin,
29
+ controllerDid: identity.controllerDid,
30
+ collections: config.collections,
31
+ appName: config.appName
32
+ });
33
+ const presentation = await chapiGet({
34
+ vpr,
35
+ ...(config.mediatorBase !== undefined && {
36
+ mediatorBase: config.mediatorBase
37
+ })
38
+ });
39
+ if (!presentation) {
40
+ throw new LoginCancelledError('storage grants');
41
+ }
42
+ onPhase?.('verifying');
43
+ await verifyLoginPresentation({
44
+ presentation,
45
+ challenge,
46
+ domain: window.location.origin,
47
+ documentLoader: config.documentLoader
48
+ });
49
+ return checkGrants({
50
+ grants: grantsOf(presentation),
51
+ controllerDid: identity.controllerDid,
52
+ collections: config.collections,
53
+ ...(config.wasServerUrl !== undefined && {
54
+ expectedServerUrl: config.wasServerUrl
55
+ })
56
+ });
57
+ }
58
+ /**
59
+ * Runs the full Login-With-Wallet flow (first-run or returning, decided by
60
+ * the seed probe). Throws `LoginCancelledError` on dismissal and `Error` on
61
+ * verification failures; nothing is persisted here (the caller persists).
62
+ *
63
+ * @param options {object}
64
+ * @param options.config {LoginConfig}
65
+ * @param [options.onPhase] {Function}
66
+ * @returns {Promise<LoginOutcome>}
67
+ */
68
+ export async function loginWithWallet({ config, onPhase }) {
69
+ // Popup #1: probe the wallet for an existing app key.
70
+ onPhase?.('probing');
71
+ const probeChallenge = newChallenge();
72
+ const probeVpr = buildSeedProbeVpr({
73
+ challenge: probeChallenge,
74
+ domain: window.location.origin,
75
+ credentialType: config.credential.credentialType,
76
+ appName: config.appName
77
+ });
78
+ const probeVp = await chapiGet({
79
+ vpr: probeVpr,
80
+ ...(config.mediatorBase !== undefined && {
81
+ mediatorBase: config.mediatorBase
82
+ })
83
+ });
84
+ if (!probeVp) {
85
+ throw new LoginCancelledError('wallet login');
86
+ }
87
+ await verifyLoginPresentation({
88
+ presentation: probeVp,
89
+ challenge: probeChallenge,
90
+ domain: window.location.origin,
91
+ documentLoader: config.documentLoader
92
+ });
93
+ let seed;
94
+ let firstRun;
95
+ const credential = findSeedCredential({
96
+ presentation: probeVp,
97
+ credentialType: config.credential.credentialType
98
+ });
99
+ if (credential) {
100
+ // Returning login: recover the seed, enforce self-issue + origin + the
101
+ // seed-to-DID binding.
102
+ const parsed = await parseSeedCredential({
103
+ credential,
104
+ origin: config.appOrigin,
105
+ config: config.credential
106
+ });
107
+ seed = parsed.seed;
108
+ firstRun = false;
109
+ }
110
+ else {
111
+ // First run: mint a fresh master seed and store its credential in the
112
+ // wallet. Block until the store succeeds -- without it, cross-device
113
+ // recovery is silently broken.
114
+ seed = crypto.getRandomValues(new Uint8Array(32));
115
+ firstRun = true;
116
+ onPhase?.('storing-key');
117
+ const issued = await issueSeedCredential({
118
+ seed,
119
+ origin: config.appOrigin,
120
+ config: config.credential,
121
+ documentLoader: config.documentLoader
122
+ });
123
+ const stored = await chapiStore({
124
+ presentation: wrapCredentialForStore(issued),
125
+ ...(config.mediatorBase !== undefined && {
126
+ mediatorBase: config.mediatorBase
127
+ })
128
+ });
129
+ if (!stored) {
130
+ throw new LoginCancelledError('saving your app key to the wallet');
131
+ }
132
+ }
133
+ const identity = await initAppSession({ seed });
134
+ // Popup #2: request the storage grants for the stable controller DID.
135
+ const checked = await requestGrants({
136
+ identity,
137
+ config,
138
+ ...(onPhase && { onPhase })
139
+ });
140
+ return {
141
+ seed,
142
+ identity,
143
+ grants: checked.grants,
144
+ parsed: checked.parsed,
145
+ expires: checked.expires,
146
+ firstRun
147
+ };
148
+ }
149
+ //# sourceMappingURL=loginFlow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loginFlow.js","sourceRoot":"","sources":["../../src/auth/loginFlow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * RP-side VPR construction for Login With Wallet. Two requests:
6
+ *
7
+ * 1. The seed probe: DIDAuthentication + QueryByExample for the app-key
8
+ * credential. An empty result is the first-run signal; a hit recovers the
9
+ * master seed on a new device.
10
+ * 2. The grants request: DIDAuthentication + AuthorizationCapabilityQuery with
11
+ * one capabilityQuery per collection (descriptor-object targets, which the
12
+ * wallet resolves against the user's one Space and auto-provisions) plus a
13
+ * read-only whole-space grant. The wallet force-caps whole-space grants to
14
+ * GET/HEAD, so read-only is all that is ever requested there.
15
+ *
16
+ * `domain` must host-match the CHAPI requesting origin or the wallet refuses
17
+ * to sign; `challenge` must be fresh per request (echoed into the DIDAuth
18
+ * proof and checked in verifyResponse).
19
+ */
20
+ import type { IVPRDetails } from './walletRequestTypes.js';
21
+ /** Default read/write actions requested on each app collection. */
22
+ export declare const RW_ACTIONS: string[];
23
+ /** The referenceId of the read-only whole-space grant. */
24
+ export declare const SPACE_READ_REFERENCE_ID = "space-read";
25
+ /** A fresh nonce for a VPR challenge. */
26
+ export declare function newChallenge(): string;
27
+ /**
28
+ * VPR #1: DIDAuthentication + QueryByExample for the app-key credential.
29
+ *
30
+ * @param options {object}
31
+ * @param options.challenge {string}
32
+ * @param options.domain {string}
33
+ * @param options.credentialType {string} the app's seed-credential type name
34
+ * @param options.appName {string} human-readable app name for the reason line
35
+ * @returns {IVPRDetails}
36
+ */
37
+ export declare function buildSeedProbeVpr({ challenge, domain, credentialType, appName }: {
38
+ challenge: string;
39
+ domain: string;
40
+ credentialType: string;
41
+ appName: string;
42
+ }): IVPRDetails;
43
+ /**
44
+ * VPR #2: DIDAuthentication + AuthorizationCapabilityQuery -- one read/write
45
+ * capabilityQuery per app collection (delegated to `controllerDid`), plus a
46
+ * read-only whole-space grant.
47
+ *
48
+ * @param options {object}
49
+ * @param options.challenge {string}
50
+ * @param options.domain {string}
51
+ * @param options.controllerDid {string}
52
+ * @param options.collections {string[]} the WAS collection ids to request
53
+ * @param options.appName {string} human-readable app name for the reason line
54
+ * @param [options.actions] {string[]} the RW action set (defaults to
55
+ * `RW_ACTIONS`)
56
+ * @returns {IVPRDetails}
57
+ */
58
+ export declare function buildGrantsVpr({ challenge, domain, controllerDid, collections, appName, actions }: {
59
+ challenge: string;
60
+ domain: string;
61
+ controllerDid: string;
62
+ collections: string[];
63
+ appName: string;
64
+ actions?: string[];
65
+ }): IVPRDetails;
66
+ //# sourceMappingURL=loginRequest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loginRequest.d.ts","sourceRoot":"","sources":["../../src/auth/loginRequest.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAEV,WAAW,EACZ,MAAM,yBAAyB,CAAA;AAEhC,mEAAmE;AACnE,eAAO,MAAM,UAAU,UAA2C,CAAA;AAElE,0DAA0D;AAC1D,eAAO,MAAM,uBAAuB,eAAe,CAAA;AAEnD,yCAAyC;AACzC,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,MAAM,EACN,cAAc,EACd,OAAO,EACR,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG,WAAW,CAkBd;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,MAAM,EACN,aAAa,EACb,WAAW,EACX,OAAO,EACP,OAAoB,EACrB,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB,GAAG,WAAW,CA6Bd"}
@@ -0,0 +1,83 @@
1
+ /** Default read/write actions requested on each app collection. */
2
+ export const RW_ACTIONS = ['GET', 'HEAD', 'PUT', 'POST', 'DELETE'];
3
+ /** The referenceId of the read-only whole-space grant. */
4
+ export const SPACE_READ_REFERENCE_ID = 'space-read';
5
+ /** A fresh nonce for a VPR challenge. */
6
+ export function newChallenge() {
7
+ return crypto.randomUUID();
8
+ }
9
+ /**
10
+ * VPR #1: DIDAuthentication + QueryByExample for the app-key credential.
11
+ *
12
+ * @param options {object}
13
+ * @param options.challenge {string}
14
+ * @param options.domain {string}
15
+ * @param options.credentialType {string} the app's seed-credential type name
16
+ * @param options.appName {string} human-readable app name for the reason line
17
+ * @returns {IVPRDetails}
18
+ */
19
+ export function buildSeedProbeVpr({ challenge, domain, credentialType, appName }) {
20
+ return {
21
+ query: [
22
+ {
23
+ type: 'DIDAuthentication',
24
+ acceptedMethods: [{ method: 'key' }]
25
+ },
26
+ {
27
+ type: 'QueryByExample',
28
+ credentialQuery: {
29
+ reason: `Recover the ${appName} app key stored in your wallet.`,
30
+ example: { type: credentialType }
31
+ }
32
+ }
33
+ ],
34
+ challenge,
35
+ domain
36
+ };
37
+ }
38
+ /**
39
+ * VPR #2: DIDAuthentication + AuthorizationCapabilityQuery -- one read/write
40
+ * capabilityQuery per app collection (delegated to `controllerDid`), plus a
41
+ * read-only whole-space grant.
42
+ *
43
+ * @param options {object}
44
+ * @param options.challenge {string}
45
+ * @param options.domain {string}
46
+ * @param options.controllerDid {string}
47
+ * @param options.collections {string[]} the WAS collection ids to request
48
+ * @param options.appName {string} human-readable app name for the reason line
49
+ * @param [options.actions] {string[]} the RW action set (defaults to
50
+ * `RW_ACTIONS`)
51
+ * @returns {IVPRDetails}
52
+ */
53
+ export function buildGrantsVpr({ challenge, domain, controllerDid, collections, appName, actions = RW_ACTIONS }) {
54
+ const capabilityQuery = collections.map(id => ({
55
+ referenceId: id,
56
+ reason: `Store your ${appName} data in the "${id}" collection.`,
57
+ controller: controllerDid,
58
+ allowedAction: actions,
59
+ invocationTarget: { type: 'urn:was:collection', name: id }
60
+ }));
61
+ capabilityQuery.push({
62
+ referenceId: SPACE_READ_REFERENCE_ID,
63
+ reason: 'Read your storage space description.',
64
+ controller: controllerDid,
65
+ allowedAction: ['GET', 'HEAD'],
66
+ invocationTarget: { type: 'urn:was:space' }
67
+ });
68
+ return {
69
+ query: [
70
+ {
71
+ type: 'DIDAuthentication',
72
+ acceptedMethods: [{ method: 'key' }]
73
+ },
74
+ {
75
+ type: 'AuthorizationCapabilityQuery',
76
+ capabilityQuery
77
+ }
78
+ ],
79
+ challenge,
80
+ domain
81
+ };
82
+ }
83
+ //# sourceMappingURL=loginRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loginRequest.js","sourceRoot":"","sources":["../../src/auth/loginRequest.ts"],"names":[],"mappings":"AAwBA,mEAAmE;AACnE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;AAElE,0DAA0D;AAC1D,MAAM,CAAC,MAAM,uBAAuB,GAAG,YAAY,CAAA;AAEnD,yCAAyC;AACzC,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,UAAU,EAAE,CAAA;AAC5B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAChC,SAAS,EACT,MAAM,EACN,cAAc,EACd,OAAO,EAMR;IACC,OAAO;QACL,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,mBAAmB;gBACzB,eAAe,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;aACrC;YACD;gBACE,IAAI,EAAE,gBAAgB;gBACtB,eAAe,EAAE;oBACf,MAAM,EAAE,eAAe,OAAO,iCAAiC;oBAC/D,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE;iBAClC;aACF;SACF;QACD,SAAS;QACT,MAAM;KACP,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,SAAS,EACT,MAAM,EACN,aAAa,EACb,WAAW,EACX,OAAO,EACP,OAAO,GAAG,UAAU,EAQrB;IACC,MAAM,eAAe,GAA6B,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACvE,WAAW,EAAE,EAAE;QACf,MAAM,EAAE,cAAc,OAAO,iBAAiB,EAAE,eAAe;QAC/D,UAAU,EAAE,aAAa;QACzB,aAAa,EAAE,OAAO;QACtB,gBAAgB,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,EAAE,EAAE;KAC3D,CAAC,CAAC,CAAA;IACH,eAAe,CAAC,IAAI,CAAC;QACnB,WAAW,EAAE,uBAAuB;QACpC,MAAM,EAAE,sCAAsC;QAC9C,UAAU,EAAE,aAAa;QACzB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;QAC9B,gBAAgB,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE;KAC5C,CAAC,CAAA;IACF,OAAO;QACL,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,mBAAmB;gBACzB,eAAe,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;aACrC;YACD;gBACE,IAAI,EAAE,8BAA8B;gBACpC,eAAe;aAChB;SACF;QACD,SAAS;QACT,MAAM;KACP,CAAA;AACH,CAAC"}
@@ -0,0 +1,52 @@
1
+ import type { IVerifiablePresentation, IZcap } from '@interop/data-integrity-core';
2
+ import type { DocumentLoader } from '../identity/documentLoader.js';
3
+ import { type ParsedGrants } from '../grants.js';
4
+ /**
5
+ * Verifies a login response VP cryptographically and structurally (steps 1-2
6
+ * above). Throws on any failure.
7
+ *
8
+ * @param options {object}
9
+ * @param options.presentation {IVerifiablePresentation}
10
+ * @param options.challenge {string} the fresh nonce this app sent
11
+ * @param options.domain {string} the domain this app sent (its origin)
12
+ * @param options.documentLoader {DocumentLoader}
13
+ * @returns {Promise<void>}
14
+ */
15
+ export declare function verifyLoginPresentation({ presentation, challenge, domain, documentLoader }: {
16
+ presentation: IVerifiablePresentation;
17
+ challenge: string;
18
+ domain: string;
19
+ documentLoader: DocumentLoader;
20
+ }): Promise<void>;
21
+ /** Extracts the delegated zcaps from a wallet response VP (`zcap` array). */
22
+ export declare function grantsOf(presentation: IVerifiablePresentation): IZcap[];
23
+ /** A validated grant set: parsed topology plus the earliest expiry. */
24
+ export interface CheckedGrants {
25
+ parsed: ParsedGrants;
26
+ grants: IZcap[];
27
+ /** ISO timestamp: the earliest expiry across the grants. */
28
+ expires: string;
29
+ }
30
+ /**
31
+ * Structural validation of the granted zcaps (step 3 above). Throws on any
32
+ * failure; returns the parsed topology and the earliest expiry on success.
33
+ *
34
+ * @param options {object}
35
+ * @param options.grants {IZcap[]}
36
+ * @param options.controllerDid {string} this app's seed-derived DID
37
+ * @param options.collections {string[]} the WAS collection ids that must be
38
+ * covered
39
+ * @param [options.requiredActions] {string[]} the actions each collection
40
+ * grant must allow (defaults to `RW_ACTIONS`)
41
+ * @param [options.expectedServerUrl] {string} the configured WAS host; when
42
+ * set, every grant must target it
43
+ * @returns {CheckedGrants}
44
+ */
45
+ export declare function checkGrants({ grants, controllerDid, collections, requiredActions, expectedServerUrl }: {
46
+ grants: IZcap[];
47
+ controllerDid: string;
48
+ collections: string[];
49
+ requiredActions?: string[];
50
+ expectedServerUrl?: string;
51
+ }): CheckedGrants;
52
+ //# sourceMappingURL=verifyResponse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyResponse.d.ts","sourceRoot":"","sources":["../../src/auth/verifyResponse.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EACV,uBAAuB,EACvB,KAAK,EACN,MAAM,8BAA8B,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAY7D;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAAC,EAC5C,YAAY,EACZ,SAAS,EACT,MAAM,EACN,cAAc,EACf,EAAE;IACD,YAAY,EAAE,uBAAuB,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,cAAc,CAAA;CAC/B,GAAG,OAAO,CAAC,IAAI,CAAC,CAmChB;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,YAAY,EAAE,uBAAuB,GAAG,KAAK,EAAE,CAMvE;AAED,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAA;CAChB;AAQD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,aAAa,EACb,WAAW,EACX,eAA4B,EAC5B,iBAAiB,EAClB,EAAE;IACD,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,GAAG,aAAa,CAgDhB"}
@@ -0,0 +1,138 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * RP-side verification of a wallet's Login-With-Wallet response VP.
6
+ *
7
+ * Layered checks:
8
+ * 1. Cryptographic: `@interop/verifier-core` `verifyPresentation` (the VP's
9
+ * DIDAuth proof plus every embedded VC proof; the default crypto service
10
+ * covers Ed25519Signature2020 and eddsa-rdfc-2022, the two suites the
11
+ * wallet mints). `registries: []` disables issuer-registry lookup (the
12
+ * app-key credential is self-issued by design).
13
+ * 2. Manual proof checks verifier-core does not make: `proofPurpose` is
14
+ * `authentication`, `domain` equals what this app sent (its origin), and
15
+ * the `challenge` echoes this request's fresh nonce.
16
+ * 3. Grant structure: every zcap is controlled by OUR seed-derived DID,
17
+ * targets a single space on the expected WAS host, is unexpired, and the
18
+ * collection set is fully covered with sufficient actions. (Delegation-
19
+ * chain proofs are enforced server-side at invocation; the RP checks
20
+ * structure.)
21
+ *
22
+ * Note on holder binding: the wallet signs the VP as ITS holder DID (did:web
23
+ * or the wallet's did:key) -- not as this app's controller DID, which never
24
+ * leaves this app. The seed-to-identity binding is enforced instead by
25
+ * `parseSeedCredential` (issuer === subject === DID derived from the embedded
26
+ * seed) and by every grant's `controller` being the requested controller DID.
27
+ */
28
+ import { verifyPresentation } from '@interop/verifier-core';
29
+ import { parseGrants } from '../grants.js';
30
+ import { earliestExpiry, isExpired } from '../identity/appSession.js';
31
+ import { RW_ACTIONS } from './loginRequest.js';
32
+ /**
33
+ * Verifies a login response VP cryptographically and structurally (steps 1-2
34
+ * above). Throws on any failure.
35
+ *
36
+ * @param options {object}
37
+ * @param options.presentation {IVerifiablePresentation}
38
+ * @param options.challenge {string} the fresh nonce this app sent
39
+ * @param options.domain {string} the domain this app sent (its origin)
40
+ * @param options.documentLoader {DocumentLoader}
41
+ * @returns {Promise<void>}
42
+ */
43
+ export async function verifyLoginPresentation({ presentation, challenge, domain, documentLoader }) {
44
+ const result = await verifyPresentation({
45
+ presentation,
46
+ challenge,
47
+ registries: [],
48
+ documentLoader
49
+ });
50
+ if (!result.verified) {
51
+ const failures = [
52
+ ...result.presentationResults,
53
+ ...result.credentialResults.flatMap(c => c.results)
54
+ ]
55
+ .filter(check => check.outcome.status === 'failure')
56
+ .map(check => check.check);
57
+ throw new Error(`Wallet presentation failed verification (${failures.join(', ') || 'unknown check'}).`);
58
+ }
59
+ const rawProof = presentation.proof;
60
+ const proofs = Array.isArray(rawProof) ? rawProof : rawProof ? [rawProof] : [];
61
+ const authProof = proofs.find(proof => proof.proofPurpose === 'authentication');
62
+ if (!authProof) {
63
+ throw new Error('Wallet presentation carries no authentication proof.');
64
+ }
65
+ if (authProof.challenge !== challenge) {
66
+ throw new Error('Wallet presentation challenge does not match.');
67
+ }
68
+ if (authProof.domain !== domain) {
69
+ throw new Error(`Wallet presentation domain "${authProof.domain ?? ''}" does not match "${domain}".`);
70
+ }
71
+ }
72
+ /** Extracts the delegated zcaps from a wallet response VP (`zcap` array). */
73
+ export function grantsOf(presentation) {
74
+ const zcap = presentation.zcap;
75
+ if (!Array.isArray(zcap)) {
76
+ return [];
77
+ }
78
+ return zcap;
79
+ }
80
+ /** The actions a grant allows, normalized to an array. */
81
+ function actionsOf(zcap) {
82
+ const allowed = zcap.allowedAction;
83
+ return Array.isArray(allowed) ? allowed : allowed ? [allowed] : [];
84
+ }
85
+ /**
86
+ * Structural validation of the granted zcaps (step 3 above). Throws on any
87
+ * failure; returns the parsed topology and the earliest expiry on success.
88
+ *
89
+ * @param options {object}
90
+ * @param options.grants {IZcap[]}
91
+ * @param options.controllerDid {string} this app's seed-derived DID
92
+ * @param options.collections {string[]} the WAS collection ids that must be
93
+ * covered
94
+ * @param [options.requiredActions] {string[]} the actions each collection
95
+ * grant must allow (defaults to `RW_ACTIONS`)
96
+ * @param [options.expectedServerUrl] {string} the configured WAS host; when
97
+ * set, every grant must target it
98
+ * @returns {CheckedGrants}
99
+ */
100
+ export function checkGrants({ grants, controllerDid, collections, requiredActions = RW_ACTIONS, expectedServerUrl }) {
101
+ if (grants.length === 0) {
102
+ throw new Error('The wallet returned no storage grants.');
103
+ }
104
+ for (const grant of grants) {
105
+ const controller = grant.controller;
106
+ if (controller !== controllerDid) {
107
+ throw new Error(`A grant is controlled by "${String(controller)}", not this app's DID.`);
108
+ }
109
+ const expires = grant.expires;
110
+ if (typeof expires !== 'string' || isExpired(expires)) {
111
+ throw new Error('A grant is missing an expiry or is already expired.');
112
+ }
113
+ }
114
+ // Asserts a single server origin + single space across all grants and
115
+ // builds the per-collection routing table.
116
+ const parsed = parseGrants(grants);
117
+ if (expectedServerUrl !== undefined &&
118
+ parsed.serverUrl !== expectedServerUrl) {
119
+ throw new Error(`Grants target "${parsed.serverUrl}", expected "${expectedServerUrl}".`);
120
+ }
121
+ for (const id of collections) {
122
+ const grant = parsed.byCollectionId[id];
123
+ if (!grant) {
124
+ throw new Error(`No grant covers the "${id}" collection.`);
125
+ }
126
+ const actions = actionsOf(grant);
127
+ const missing = requiredActions.filter(action => !actions.includes(action));
128
+ if (missing.length > 0) {
129
+ throw new Error(`The "${id}" grant lacks required actions: ${missing.join(', ')}.`);
130
+ }
131
+ }
132
+ const expires = earliestExpiry(grants);
133
+ if (!expires) {
134
+ throw new Error('No grant carries a parseable expiry.');
135
+ }
136
+ return { parsed, grants, expires };
137
+ }
138
+ //# sourceMappingURL=verifyResponse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyResponse.js","sourceRoot":"","sources":["../../src/auth/verifyResponse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=verifyResponse.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyResponse.test.d.ts","sourceRoot":"","sources":["../../src/auth/verifyResponse.test.ts"],"names":[],"mappings":""}