@interop/was-react 0.12.0 → 0.13.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.
- package/README.md +23 -25
- package/dist/auth/loginFlow.d.ts +8 -5
- package/dist/auth/loginFlow.d.ts.map +1 -1
- package/dist/auth/loginFlow.js +46 -16
- package/dist/auth/loginFlow.js.map +1 -1
- package/dist/auth/loginRequest.d.ts +27 -81
- package/dist/auth/loginRequest.d.ts.map +1 -1
- package/dist/auth/loginRequest.js +94 -41
- package/dist/auth/loginRequest.js.map +1 -1
- package/dist/auth/verifyResponse.d.ts +3 -3
- package/dist/auth/verifyResponse.d.ts.map +1 -1
- package/dist/auth/verifyResponse.js +16 -13
- package/dist/auth/verifyResponse.js.map +1 -1
- package/dist/auth/walletRequestTypes.d.ts +8 -6
- package/dist/auth/walletRequestTypes.d.ts.map +1 -1
- package/dist/config.d.ts +19 -13
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -0
- package/dist/config.js.map +1 -1
- package/dist/identity/seedCredential.d.ts +39 -38
- package/dist/identity/seedCredential.d.ts.map +1 -1
- package/dist/identity/seedCredential.js +79 -77
- package/dist/identity/seedCredential.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/react/documentApp.d.ts +6 -6
- package/dist/react/documentApp.d.ts.map +1 -1
- package/dist/react/documentApp.js +7 -6
- package/dist/react/documentApp.js.map +1 -1
- package/dist/react/hooks.d.ts +1 -1
- package/dist/react/hooks.js +1 -1
- package/dist/session/authStore.d.ts +1 -1
- package/dist/session/authStore.js +6 -6
- package/dist/session/authStore.js.map +1 -1
- package/dist/storage/adopt.d.ts +3 -3
- package/dist/storage/adopt.js +5 -5
- package/dist/storage/entityStore.d.ts +1 -1
- package/dist/storage/localStore.d.ts +2 -2
- package/dist/storage/localStore.js +2 -2
- package/dist/storage/storageManager.d.ts +8 -3
- package/dist/storage/storageManager.d.ts.map +1 -1
- package/dist/storage/storageManager.js +19 -12
- package/dist/storage/storageManager.js.map +1 -1
- package/dist/sync/lww.d.ts +4 -4
- package/dist/sync/lww.js +7 -7
- package/dist/sync/lwwConflictHandler.d.ts +4 -4
- package/dist/sync/lwwConflictHandler.js +1 -1
- package/package.json +1 -1
|
@@ -1,18 +1,64 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
1
4
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
+
* RP-side VPR construction for Login With Wallet: the one-popup App Connect
|
|
6
|
+
* request.
|
|
7
|
+
*
|
|
8
|
+
* A single CHAPI `get` carries DIDAuthentication plus an `AppConnectQuery` that
|
|
9
|
+
* names the app (its display name for the wallet's consent screen and the
|
|
10
|
+
* canonical `appUrl` the wallet needs to MATCH an existing app key or MINT a
|
|
11
|
+
* fresh one), and one collection-scoped capabilityQuery per requested
|
|
12
|
+
* collection. The wallet responds -- in the same round -- with the app-key
|
|
13
|
+
* credential and the delegated zcaps embedded in the response VP, so first-run
|
|
14
|
+
* and returning are a single request/response with no store popup and no
|
|
15
|
+
* separate grants popup.
|
|
16
|
+
*
|
|
17
|
+
* Only collection-scoped capabilities are requested (no whole-space grant),
|
|
18
|
+
* and each request stays within the ALLOWED ACTIONS of the descriptor class it
|
|
19
|
+
* uses (the App Connect spec's "Allowed actions" table): both collection
|
|
20
|
+
* classes -- private and public -- allow the full action vocabulary
|
|
21
|
+
* ({@link RW_ACTIONS}), since a published collection is still the app's own
|
|
22
|
+
* data and un-publishing and revision are data management like any other
|
|
23
|
+
* write. A share is read-only ({@link SHARED_ACTIONS}). A configured action set
|
|
24
|
+
* naming an action above a requested collection's allowed set is a
|
|
25
|
+
* configuration error thrown here, at build time -- a conformant wallet can
|
|
26
|
+
* never grant it, so letting it ride would surface later as a failed login
|
|
27
|
+
* instead.
|
|
28
|
+
*
|
|
29
|
+
* A `visibility: 'public'` collection is requested with the distinct descriptor
|
|
30
|
+
* type `https://w3id.org/byoe#public-collection` (the wallet provisions it plaintext with a
|
|
31
|
+
* collection-level public-read policy and renders a world-readable consent
|
|
32
|
+
* warning); wallets that predate the type render it UNSATISFIABLE, which is the
|
|
33
|
+
* intended fail-closed behavior -- an older wallet must not silently provision a
|
|
34
|
+
* private collection the app believes is public. The App Connect query as a
|
|
35
|
+
* whole is likewise unsatisfiable on a wallet that predates it, so an old wallet
|
|
36
|
+
* fails closed rather than degrading into a partial generic flow.
|
|
37
|
+
*
|
|
38
|
+
* A SHARED collection -- one the wallet already owns and encrypts, which the app
|
|
39
|
+
* asks to read and decrypt -- uses the
|
|
40
|
+
* `https://w3id.org/byoe#shared-wallet-collection` descriptor type, and the
|
|
41
|
+
* actions are read-only by construction ({@link SHARED_ACTIONS}):
|
|
42
|
+
* the app never requests writes on a wallet collection. Exactly like
|
|
43
|
+
* `https://w3id.org/byoe#public-collection`, a wallet that predates the type resolves the
|
|
44
|
+
* descriptor UNSATISFIABLE and fails closed -- which is the point here. A share
|
|
45
|
+
* fuses two axes (a read zcap AND an entry in the collection's key-epoch
|
|
46
|
+
* roster), so a wallet that granted only the zcap would hand the app ciphertext
|
|
47
|
+
* it cannot decrypt; that would surface as corrupt data rather than as a wallet
|
|
48
|
+
* that needs updating.
|
|
49
|
+
*
|
|
50
|
+
* `domain` must host-match the CHAPI requesting origin or the wallet refuses
|
|
51
|
+
* to sign; `challenge` must be fresh per request (echoed into the DIDAuth
|
|
52
|
+
* proof and checked in verifyResponse).
|
|
5
53
|
*/
|
|
6
|
-
|
|
54
|
+
import { serializedAppUrl } from '@interop/wallet-core/request';
|
|
7
55
|
/**
|
|
8
|
-
* The
|
|
9
|
-
*
|
|
10
|
-
* collection
|
|
11
|
-
*
|
|
12
|
-
* asked -- and the App Connect spec forbids an application from requiring an
|
|
13
|
-
* action above it.
|
|
56
|
+
* The full WAS action vocabulary, in the order of the App Connect spec's
|
|
57
|
+
* "Allowed actions" table -- also the allowed-action set of BOTH collection
|
|
58
|
+
* classes, `https://w3id.org/byoe#private-collection` and
|
|
59
|
+
* `https://w3id.org/byoe#public-collection`.
|
|
14
60
|
*/
|
|
15
|
-
export const
|
|
61
|
+
export const RW_ACTIONS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE'];
|
|
16
62
|
/**
|
|
17
63
|
* The actions requested on a SHARED (wallet-owned) collection: read-only, and
|
|
18
64
|
* not configurable. A shared collection belongs to the wallet, so an app never
|
|
@@ -20,18 +66,21 @@ export const PUBLIC_ACTIONS = ['GET', 'HEAD', 'POST'];
|
|
|
20
66
|
*/
|
|
21
67
|
export const SHARED_ACTIONS = ['GET', 'HEAD'];
|
|
22
68
|
/**
|
|
23
|
-
* The
|
|
24
|
-
* (the App Connect spec's "
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
69
|
+
* The allowed actions of the descriptor class a collection is requested with
|
|
70
|
+
* (the App Connect spec's "Allowed actions" table). Both collection classes --
|
|
71
|
+
* public and private -- allow the full action vocabulary: published content is
|
|
72
|
+
* still the application's own data, and un-publishing and revision are data
|
|
73
|
+
* management like any other write, so an app may `PUT` or `DELETE` what it
|
|
74
|
+
* published. Shares have their own fixed {@link SHARED_ACTIONS} and never
|
|
75
|
+
* consult a configured action set.
|
|
29
76
|
*
|
|
30
|
-
* @param [
|
|
77
|
+
* @param [_visibility] {'private' | 'public'}
|
|
31
78
|
* @returns {string[]}
|
|
32
79
|
*/
|
|
33
|
-
export function actionCeiling(
|
|
34
|
-
|
|
80
|
+
export function actionCeiling(_visibility) {
|
|
81
|
+
// Both classes currently allow the full vocabulary; the parameter stays so a
|
|
82
|
+
// future class that DOES bound actions has one place to bound them.
|
|
83
|
+
return RW_ACTIONS;
|
|
35
84
|
}
|
|
36
85
|
/**
|
|
37
86
|
* A fresh nonce for a VPR challenge.
|
|
@@ -41,13 +90,14 @@ export function newChallenge() {
|
|
|
41
90
|
}
|
|
42
91
|
/**
|
|
43
92
|
* The actions to request for one collection: the configured set capped at the
|
|
44
|
-
* collection's
|
|
45
|
-
* the whole
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
93
|
+
* collection class's allowed actions, kept in table order. When no set is
|
|
94
|
+
* configured the whole allowed set is requested; a narrower subset stays legal
|
|
95
|
+
* and is passed through as asked. An EXPLICIT set naming an action OUTSIDE the
|
|
96
|
+
* class's allowed actions is a configuration error thrown here, at request
|
|
97
|
+
* build time: a conformant wallet can never grant it, so silently capping
|
|
98
|
+
* would leave the app believing it asked for more than any correct wallet
|
|
99
|
+
* returns, and the mismatch would surface later as a failed login instead of
|
|
100
|
+
* as the config bug it is.
|
|
51
101
|
*
|
|
52
102
|
* @param options {object}
|
|
53
103
|
* @param options.id {string} the WAS collection id (for error messages)
|
|
@@ -62,8 +112,9 @@ function requestedActions({ id, visibility, actions }) {
|
|
|
62
112
|
}
|
|
63
113
|
const excess = actions.filter(action => !ceiling.includes(action));
|
|
64
114
|
if (excess.length > 0) {
|
|
65
|
-
throw new Error(`Collection "${id}" cannot request action(s)
|
|
66
|
-
|
|
115
|
+
throw new Error(`Collection "${id}" cannot request action(s) outside its class's ` +
|
|
116
|
+
`allowed actions: ${excess.join(', ')} (the allowed actions are ` +
|
|
117
|
+
`${ceiling.join(', ')}).`);
|
|
67
118
|
}
|
|
68
119
|
const capped = ceiling.filter(action => actions.includes(action));
|
|
69
120
|
if (capped.length === 0) {
|
|
@@ -76,9 +127,12 @@ function requestedActions({ id, visibility, actions }) {
|
|
|
76
127
|
/**
|
|
77
128
|
* The one-popup App Connect VPR: DIDAuthentication + a single `AppConnectQuery`.
|
|
78
129
|
*
|
|
79
|
-
* The `app` block names the app
|
|
80
|
-
* the
|
|
81
|
-
*
|
|
130
|
+
* The `app` block names the app -- `name` for the wallet's consent screen, and
|
|
131
|
+
* `appUrl`, the application's canonical URL, which the wallet needs to MATCH an
|
|
132
|
+
* existing app key or MINT a fresh one. The `appUrl` is validated and
|
|
133
|
+
* serialized here against `domain` (this app's own live browser origin): it
|
|
134
|
+
* must be an absolute, fragment-less, same-origin URL, and the serialization is
|
|
135
|
+
* what everything downstream stores and compares. `capabilityQuery` holds one
|
|
82
136
|
* collection-scoped grant request per app collection -- the existing capability
|
|
83
137
|
* shape MINUS `controller` (the wallet fills it with the app-key subject DID)
|
|
84
138
|
* and MINUS `reason` (the App Connect consent screen supersedes per-grant
|
|
@@ -91,8 +145,8 @@ function requestedActions({ id, visibility, actions }) {
|
|
|
91
145
|
* @param options.domain {string}
|
|
92
146
|
* @param options.appName {string} human-readable app name for the consent
|
|
93
147
|
* screen
|
|
94
|
-
* @param options.
|
|
95
|
-
*
|
|
148
|
+
* @param options.appUrl {string} the application's canonical URL, same-origin
|
|
149
|
+
* with `domain` and fragment-less; emitted in its serialized form
|
|
96
150
|
* @param options.collections {GrantRequestCollection[]} the collections to
|
|
97
151
|
* request (WAS collection id + visibility)
|
|
98
152
|
* @param [options.sharedCollections] {string[]} WAS collection ids of
|
|
@@ -100,13 +154,13 @@ function requestedActions({ id, visibility, actions }) {
|
|
|
100
154
|
* a `https://w3id.org/byoe#shared-wallet-collection` descriptor with
|
|
101
155
|
* {@link SHARED_ACTIONS}
|
|
102
156
|
* @param [options.actions] {string[]} the action set to request on each app
|
|
103
|
-
* collection; when omitted each collection requests exactly its class
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
157
|
+
* collection; when omitted each collection requests exactly its class's
|
|
158
|
+
* allowed actions ({@link actionCeiling}). An explicit set naming an action
|
|
159
|
+
* outside them throws (a configuration error, surfaced at build time rather
|
|
160
|
+
* than as a failed login)
|
|
107
161
|
* @returns {IVPRDetails}
|
|
108
162
|
*/
|
|
109
|
-
export function buildAppConnectVpr({ challenge, domain, appName,
|
|
163
|
+
export function buildAppConnectVpr({ challenge, domain, appName, appUrl, collections, sharedCollections = [], actions }) {
|
|
110
164
|
const capabilityQuery = collections.map(({ id, visibility }) => ({
|
|
111
165
|
referenceId: id,
|
|
112
166
|
allowedAction: requestedActions({ id, visibility, actions }),
|
|
@@ -137,8 +191,7 @@ export function buildAppConnectVpr({ challenge, domain, appName, credential, col
|
|
|
137
191
|
type: 'AppConnectQuery',
|
|
138
192
|
app: {
|
|
139
193
|
name: appName,
|
|
140
|
-
|
|
141
|
-
vocabBase: credential.vocabBase
|
|
194
|
+
appUrl: serializedAppUrl({ appUrl, origin: domain })
|
|
142
195
|
},
|
|
143
196
|
capabilityQuery
|
|
144
197
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loginRequest.js","sourceRoot":"","sources":["../../src/auth/loginRequest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loginRequest.js","sourceRoot":"","sources":["../../src/auth/loginRequest.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,10 +43,10 @@ export interface CheckedGrants {
|
|
|
43
43
|
* @param options.controllerDid {string} this app's seed-derived DID
|
|
44
44
|
* @param options.collections {GrantRequestCollection[]} the collections that
|
|
45
45
|
* must be covered (WAS collection id + visibility; the visibility selects
|
|
46
|
-
* the class
|
|
46
|
+
* the class's allowed actions the required actions are capped at)
|
|
47
47
|
* @param [options.requiredActions] {string[]} the actions each collection
|
|
48
|
-
* grant must allow, capped per collection at its class
|
|
49
|
-
* `RW_ACTIONS`, so each collection requires exactly
|
|
48
|
+
* grant must allow, capped per collection at its class's allowed actions
|
|
49
|
+
* (defaults to `RW_ACTIONS`, so each collection requires exactly them)
|
|
50
50
|
* @returns {CheckedGrants}
|
|
51
51
|
*/
|
|
52
52
|
export declare function checkGrants({ grants, controllerDid, collections, requiredActions }: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verifyResponse.d.ts","sourceRoot":"","sources":["../../src/auth/verifyResponse.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verifyResponse.d.ts","sourceRoot":"","sources":["../../src/auth/verifyResponse.ts"],"names":[],"mappings":"AAmCA,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;AAG7D,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,mBAAmB,CAAA;AAE1B;;;;;;;;;;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,CA0EhB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,YAAY,EAAE,uBAAuB,GAAG,KAAK,EAAE,CAMvE;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAA;IACpB,MAAM,EAAE,KAAK,EAAE,CAAA;IACf;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;CAChB;AASD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,aAAa,EACb,WAAW,EACX,eAA4B,EAC7B,EAAE;IACD,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,sBAAsB,EAAE,CAAA;IACrC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC3B,GAAG,aAAa,CA+ChB"}
|
|
@@ -13,13 +13,16 @@
|
|
|
13
13
|
* 2. Manual proof checks verifier-core does not make: `proofPurpose` is
|
|
14
14
|
* `authentication`, `domain` equals what this app sent (its origin), and
|
|
15
15
|
* the `challenge` echoes this request's fresh nonce.
|
|
16
|
-
* 3. Grant structure: every zcap is controlled by OUR seed-derived DID,
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
16
|
+
* 3. Grant structure: every zcap is controlled by OUR seed-derived DID, carries
|
|
17
|
+
* a single non-empty string `invocationTarget`, targets a collection (never
|
|
18
|
+
* the Space itself or a reserved sub-endpoint) in a single space on a single
|
|
19
|
+
* WAS host, is unexpired, and the collection set is fully covered with
|
|
20
|
+
* sufficient actions -- where "sufficient" is capped at each collection
|
|
21
|
+
* class's allowed actions (the App Connect spec's "Allowed actions" table).
|
|
22
|
+
* Both collection classes allow the full vocabulary today, so the cap bounds
|
|
23
|
+
* nothing at present; it stays because the spec forbids failing a connection
|
|
24
|
+
* over an action the requested class never allows, which a correct wallet
|
|
25
|
+
* would be obliged to withhold.
|
|
23
26
|
* (Delegation-chain proofs are enforced server-side at invocation; the RP
|
|
24
27
|
* checks structure.)
|
|
25
28
|
*
|
|
@@ -129,10 +132,10 @@ function actionsOf(zcap) {
|
|
|
129
132
|
* @param options.controllerDid {string} this app's seed-derived DID
|
|
130
133
|
* @param options.collections {GrantRequestCollection[]} the collections that
|
|
131
134
|
* must be covered (WAS collection id + visibility; the visibility selects
|
|
132
|
-
* the class
|
|
135
|
+
* the class's allowed actions the required actions are capped at)
|
|
133
136
|
* @param [options.requiredActions] {string[]} the actions each collection
|
|
134
|
-
* grant must allow, capped per collection at its class
|
|
135
|
-
* `RW_ACTIONS`, so each collection requires exactly
|
|
137
|
+
* grant must allow, capped per collection at its class's allowed actions
|
|
138
|
+
* (defaults to `RW_ACTIONS`, so each collection requires exactly them)
|
|
136
139
|
* @returns {CheckedGrants}
|
|
137
140
|
*/
|
|
138
141
|
export function checkGrants({ grants, controllerDid, collections, requiredActions = RW_ACTIONS }) {
|
|
@@ -159,9 +162,9 @@ export function checkGrants({ grants, controllerDid, collections, requiredAction
|
|
|
159
162
|
throw new Error(`No grant covers the "${id}" collection.`);
|
|
160
163
|
}
|
|
161
164
|
const actions = actionsOf(grant);
|
|
162
|
-
// The requirement is capped at the class
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
+
// The requirement is capped at the class's allowed actions: an app must
|
|
166
|
+
// never fail a connection over an action its requested class never allows,
|
|
167
|
+
// since a conformant wallet is obliged to withhold it.
|
|
165
168
|
const required = actionCeiling(visibility).filter(action => requiredActions.includes(action));
|
|
166
169
|
const missing = required.filter(action => !actions.includes(action));
|
|
167
170
|
if (missing.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verifyResponse.js","sourceRoot":"","sources":["../../src/auth/verifyResponse.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"verifyResponse.js","sourceRoot":"","sources":["../../src/auth/verifyResponse.ts"],"names":[],"mappings":"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"}
|
|
@@ -68,10 +68,13 @@ export type ICapabilityQueryDetail = {
|
|
|
68
68
|
*/
|
|
69
69
|
export type IAppConnectCapabilityQuery = Omit<ICapabilityQueryDetail, 'controller' | 'reason'>;
|
|
70
70
|
/**
|
|
71
|
-
* The one-popup App Connect query: it names the requesting app
|
|
72
|
-
* screen
|
|
73
|
-
*
|
|
74
|
-
*
|
|
71
|
+
* The one-popup App Connect query: it names the requesting app -- `name` for
|
|
72
|
+
* the consent screen, and `appUrl`, the application's canonical URL (absolute,
|
|
73
|
+
* fragment-less, same-origin with the request `domain`, in serialized form),
|
|
74
|
+
* which the wallet uses to MATCH an existing app key or MINT a fresh one --
|
|
75
|
+
* alongside the collection grants to delegate to that app key's subject DID.
|
|
76
|
+
* The app identity is scoped to the pair (origin, `appUrl`), so applications
|
|
77
|
+
* sharing an origin keep distinct identities. A wallet that predates this type renders it
|
|
75
78
|
* UNSATISFIABLE (the intended fail-closed behavior -- see `verifyResponse` /
|
|
76
79
|
* `loginFlow`), so an older wallet cannot silently degrade the login.
|
|
77
80
|
*
|
|
@@ -81,8 +84,7 @@ export type IAppConnectQuery = {
|
|
|
81
84
|
type: 'AppConnectQuery';
|
|
82
85
|
app: {
|
|
83
86
|
name: string;
|
|
84
|
-
|
|
85
|
-
vocabBase: string;
|
|
87
|
+
appUrl: string;
|
|
86
88
|
};
|
|
87
89
|
capabilityQuery: IAppConnectCapabilityQuery | IAppConnectCapabilityQuery[];
|
|
88
90
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"walletRequestTypes.d.ts","sourceRoot":"","sources":["../../src/auth/walletRequestTypes.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EACV,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,EACN,MAAM,8BAA8B,CAAA;AAErC;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,uBAAuB,GAAG,gBAAgB,CAAA;AAElE;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,mBAAmB,CAAA;IACzB,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC3C,oBAAoB,CAAC,EAAE,KAAK,CAAC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACtD,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC3D,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,sBAAsB,EACtB,YAAY,GAAG,QAAQ,CACxB,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"walletRequestTypes.d.ts","sourceRoot":"","sources":["../../src/auth/walletRequestTypes.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EACV,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,EACN,MAAM,8BAA8B,CAAA;AAErC;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,uBAAuB,GAAG,gBAAgB,CAAA;AAElE;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,mBAAmB,CAAA;IACzB,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC3C,oBAAoB,CAAC,EAAE,KAAK,CAAC;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACtD,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC3D,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,sBAAsB,EACtB,YAAY,GAAG,QAAQ,CACxB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,iBAAiB,CAAA;IACvB,GAAG,EAAE;QACH,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;IACD,eAAe,EAAE,0BAA0B,GAAG,0BAA0B,EAAE,CAAA;CAC3E,CAAA;AAED,YAAY,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAA"}
|
package/dist/config.d.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
5
|
* The central configuration contract for a WAS-backed local-first app: the app
|
|
6
|
-
* identity/origin, the registry of storage collections, the
|
|
7
|
-
*
|
|
6
|
+
* identity/origin/URL, the registry of storage collections, and the
|
|
7
|
+
* (all-optional) sync/expiry tuning. An app builds one
|
|
8
8
|
* {@link WasAppConfig} and threads it through the auth, storage, and sync
|
|
9
9
|
* layers.
|
|
10
10
|
*
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
* an app special-case a singleton collection (e.g. a current-focus doc) without
|
|
27
27
|
* a rigid CRUD interface.
|
|
28
28
|
*/
|
|
29
|
-
import type { SeedCredentialConfig } from './identity/seedCredential.js';
|
|
30
29
|
/**
|
|
31
30
|
* One storage collection: the logical `key` (app-side / RxDB collection handle)
|
|
32
31
|
* mapped to its WAS collection `id` (the generic, interoperable name).
|
|
@@ -46,7 +45,7 @@ export interface WasCollectionConfig {
|
|
|
46
45
|
* declares a world-readable collection (the wallet provisions it with a
|
|
47
46
|
* public-read policy); public implies PLAINTEXT -- payloads are stored as-is,
|
|
48
47
|
* with no per-collection cipher, and the LWW bookkeeping fields (`updatedAt`,
|
|
49
|
-
* `
|
|
48
|
+
* `writerId`) are world-readable alongside the content (`writerId` is a
|
|
50
49
|
* random per-install attribution label, but still a linkability handle across
|
|
51
50
|
* a user's public documents). Changing a collection's visibility after first
|
|
52
51
|
* use is a data-migration event, not a config tweak: existing rows keep
|
|
@@ -66,7 +65,7 @@ export interface WasCollectionConfig {
|
|
|
66
65
|
/**
|
|
67
66
|
* One SHARED collection: a wallet-owned, already-encrypted collection the app
|
|
68
67
|
* asks the wallet for read-and-decrypt access to (the
|
|
69
|
-
* `https://w3id.org/byoe#shared-collection` grant). It is the mirror image of
|
|
68
|
+
* `https://w3id.org/byoe#shared-wallet-collection` grant). It is the mirror image of
|
|
70
69
|
* {@link WasCollectionConfig}: read-only, NOT replicated into RxDB, NOT written
|
|
71
70
|
* to, and with no local replica. Reads go straight to the server through a
|
|
72
71
|
* `SharedCollectionReader`.
|
|
@@ -128,6 +127,17 @@ export interface WasAppConfig {
|
|
|
128
127
|
* This app's own web origin (the anti-phishing bind on the app key).
|
|
129
128
|
*/
|
|
130
129
|
appOrigin: string;
|
|
130
|
+
/**
|
|
131
|
+
* This app's canonical URL: what identifies this application among the
|
|
132
|
+
* applications served from its origin, so the app identity is scoped to the
|
|
133
|
+
* triple (user, origin, `appUrl`). It MUST be an absolute URL, MUST NOT carry
|
|
134
|
+
* a fragment, and MUST be same-origin with the app's live browser origin.
|
|
135
|
+
* Everything downstream stores and compares the parsed URL's serialization,
|
|
136
|
+
* so spellings differing only in a default port, in percent-encoding case, or
|
|
137
|
+
* in dot-segments do not name distinct applications. An app with a Web App
|
|
138
|
+
* Manifest is well served by using its processed manifest `id` here.
|
|
139
|
+
*/
|
|
140
|
+
appUrl: string;
|
|
131
141
|
/**
|
|
132
142
|
* The CHAPI mediator base URL (the requesting origin is appended).
|
|
133
143
|
*/
|
|
@@ -138,7 +148,7 @@ export interface WasAppConfig {
|
|
|
138
148
|
collections: WasCollectionConfig[];
|
|
139
149
|
/**
|
|
140
150
|
* Wallet-owned collections this app asks to be given READ-AND-DECRYPT access
|
|
141
|
-
* to (the `https://w3id.org/byoe#shared-collection` grant). Read-only by construction: they
|
|
151
|
+
* to (the `https://w3id.org/byoe#shared-wallet-collection` grant). Read-only by construction: they
|
|
142
152
|
* are never replicated into RxDB, never written to, and have no local
|
|
143
153
|
* replica -- reads go straight to the server through a
|
|
144
154
|
* `SharedCollectionReader`. A collection may be app-owned (`collections`) or
|
|
@@ -162,19 +172,15 @@ export interface WasAppConfig {
|
|
|
162
172
|
* undefined`) to keep fixtures out of production local-first apps.
|
|
163
173
|
*/
|
|
164
174
|
seedLocal?: () => Promise<void>;
|
|
165
|
-
/**
|
|
166
|
-
* The seed-credential type name + vocabulary namespace.
|
|
167
|
-
*/
|
|
168
|
-
credential: SeedCredentialConfig;
|
|
169
175
|
/**
|
|
170
176
|
* Base name for the local RxDB database and session IndexedDB naming. Defaults
|
|
171
177
|
* to {@link DEFAULT_DB_NAME}.
|
|
172
178
|
*/
|
|
173
179
|
dbName?: string;
|
|
174
180
|
/**
|
|
175
|
-
* Prefix for this app's `localStorage` keys (e.g. the LWW `
|
|
181
|
+
* Prefix for this app's `localStorage` keys (e.g. the LWW `writerId`).
|
|
176
182
|
* Defaults to {@link DEFAULT_STORAGE_KEY_PREFIX}. Migrating apps should set
|
|
177
|
-
* their prior prefix so an existing per-install
|
|
183
|
+
* their prior prefix so an existing per-install writer id is preserved.
|
|
178
184
|
*/
|
|
179
185
|
storageKeyPrefix?: string;
|
|
180
186
|
/**
|
|
@@ -228,7 +234,7 @@ export declare const DEFAULT_DB_NAME = "was-react";
|
|
|
228
234
|
*/
|
|
229
235
|
export declare const DEFAULT_ONBOARDING = "login-gated";
|
|
230
236
|
/**
|
|
231
|
-
* Default `localStorage` key prefix (e.g. `was-react:
|
|
237
|
+
* Default `localStorage` key prefix (e.g. `was-react:writerId`).
|
|
232
238
|
*/
|
|
233
239
|
export declare const DEFAULT_STORAGE_KEY_PREFIX = "was-react:";
|
|
234
240
|
/**
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
Binary file
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,11 +2,10 @@ import type { IVerifiableCredential, IVerifiablePresentation } from '@interop/da
|
|
|
2
2
|
import { type IdentityAgents } from './agents.js';
|
|
3
3
|
import type { DocumentLoader } from './documentLoader.js';
|
|
4
4
|
/**
|
|
5
|
-
* The marker type every app key carries
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* foreign app key at store time.
|
|
5
|
+
* The marker type every app key carries, mapped to one stable IRI for every
|
|
6
|
+
* app by the hosted App Connect context. It makes "presents as an app key" a
|
|
7
|
+
* term check rather than a shape heuristic, which is what lets the wallet
|
|
8
|
+
* refuse a foreign app key at store time.
|
|
10
9
|
*
|
|
11
10
|
* It is a self-declaration, not evidence: the `type` array of a planted
|
|
12
11
|
* credential is attacker-controlled like the rest of it. The marker makes the
|
|
@@ -15,14 +14,9 @@ import type { DocumentLoader } from './documentLoader.js';
|
|
|
15
14
|
*/
|
|
16
15
|
export declare const APP_KEY_CREDENTIAL_TYPE = "AppKeyCredential";
|
|
17
16
|
/**
|
|
18
|
-
*
|
|
19
|
-
* vocabulary namespace its inline-context terms are minted under (e.g.
|
|
20
|
-
* `credentialType: 'MyAppKey'`, `vocabBase: 'urn:my-app:vocab#'`).
|
|
17
|
+
* The credential's fixed two-entry `type` array, in this order.
|
|
21
18
|
*/
|
|
22
|
-
export
|
|
23
|
-
credentialType: string;
|
|
24
|
-
vocabBase: string;
|
|
25
|
-
}
|
|
19
|
+
export declare const APP_KEY_TYPE_ARRAY: readonly string[];
|
|
26
20
|
/**
|
|
27
21
|
* A parsed and structurally validated seed credential.
|
|
28
22
|
*/
|
|
@@ -51,59 +45,66 @@ export declare function base64urlToBytes(text: string): Uint8Array;
|
|
|
51
45
|
* @param options {object}
|
|
52
46
|
* @param options.seed {Uint8Array} the 32-byte master seed
|
|
53
47
|
* @param options.origin {string} this app's web origin (anti-phishing bind)
|
|
48
|
+
* @param options.appUrl {string} this app's canonical URL, in its
|
|
49
|
+
* serialized form (see `serializedAppUrl`); identifies the application among
|
|
50
|
+
* the applications on its origin
|
|
54
51
|
* @param options.appName {string} human-readable app name, shown by the
|
|
55
52
|
* wallet on the credential (`name`/`description`)
|
|
56
|
-
* @param options.config {SeedCredentialConfig} credential type + vocab
|
|
57
53
|
* @param options.documentLoader {DocumentLoader}
|
|
58
54
|
* @returns {Promise<IVerifiableCredential>}
|
|
59
55
|
*/
|
|
60
|
-
export declare function issueSeedCredential({ seed, origin,
|
|
56
|
+
export declare function issueSeedCredential({ seed, origin, appUrl, appName, documentLoader }: {
|
|
61
57
|
seed: Uint8Array;
|
|
62
58
|
origin: string;
|
|
59
|
+
appUrl: string;
|
|
63
60
|
appName: string;
|
|
64
|
-
config: SeedCredentialConfig;
|
|
65
61
|
documentLoader: DocumentLoader;
|
|
66
62
|
}): Promise<IVerifiableCredential>;
|
|
67
63
|
/**
|
|
68
|
-
* Parses
|
|
69
|
-
* `AppKeyCredential` marker type, the
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
64
|
+
* Parses an app-key credential and enforces the App Connect spec's six parse
|
|
65
|
+
* checks, in order: the `AppKeyCredential` marker type, the `appUrl` claim
|
|
66
|
+
* matching what this request sent (exact string), self-issue (issuer ===
|
|
67
|
+
* subject id), the origin binding (exact string, against this app's own live
|
|
68
|
+
* origin -- the same value it sent as the request `domain`), a well-formed
|
|
69
|
+
* 32-byte base64url-no-pad seed, and -- the strongest check -- that the DID
|
|
70
|
+
* derived from the embedded seed IS the credential's subject/issuer DID. (The
|
|
71
|
+
* cryptographic proof on the credential is verified separately at the
|
|
72
|
+
* presentation level.)
|
|
74
73
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* since the seed-to-DID binding below is the boundary either way.
|
|
74
|
+
* These duplicate checks the wallet already made; that is the point. They are
|
|
75
|
+
* defense in depth over an origin binding and an identity binding this app is
|
|
76
|
+
* fully able to check itself.
|
|
79
77
|
*
|
|
80
78
|
* @param options {object}
|
|
81
79
|
* @param options.credential {IVerifiableCredential}
|
|
82
|
-
* @param options.origin {string}
|
|
83
|
-
* @param options.
|
|
80
|
+
* @param options.origin {string} this app's own live browser origin
|
|
81
|
+
* @param options.appUrl {string} the serialized `appUrl` this request sent
|
|
84
82
|
* @returns {Promise<ParsedSeedCredential>}
|
|
85
83
|
*/
|
|
86
|
-
export declare function parseSeedCredential({ credential, origin,
|
|
84
|
+
export declare function parseSeedCredential({ credential, origin, appUrl }: {
|
|
87
85
|
credential: IVerifiableCredential;
|
|
88
86
|
origin: string;
|
|
89
|
-
|
|
87
|
+
appUrl: string;
|
|
90
88
|
}): Promise<ParsedSeedCredential>;
|
|
91
89
|
/**
|
|
92
|
-
* Finds the
|
|
93
|
-
* wallet returned none (the
|
|
90
|
+
* Finds the app-key credential inside a wallet response VP, or `null` when the
|
|
91
|
+
* wallet returned none (the wallet-unsupported signal).
|
|
94
92
|
*
|
|
95
|
-
* Matched on the
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
93
|
+
* Matched on the `credentialSubject.appUrl` claim ALONE: per the App Connect
|
|
94
|
+
* spec's response-verification step 3, the `AppKeyCredential` marker type must
|
|
95
|
+
* NOT be required here. Requiring it would make "the wallet returned a
|
|
96
|
+
* credential that is wrong" indistinguishable from "the wallet returned
|
|
97
|
+
* nothing" -- a returned credential missing the marker must surface as a parse
|
|
98
|
+
* error from {@link parseSeedCredential}, not as a `null` a caller would read
|
|
99
|
+
* as first run and answer by silently minting a second key.
|
|
99
100
|
*
|
|
100
101
|
* @param options {object}
|
|
101
102
|
* @param options.presentation {IVerifiablePresentation}
|
|
102
|
-
* @param options.
|
|
103
|
+
* @param options.appUrl {string} the serialized `appUrl` this request sent
|
|
103
104
|
* @returns {IVerifiableCredential | null}
|
|
104
105
|
*/
|
|
105
|
-
export declare function findSeedCredential({ presentation,
|
|
106
|
+
export declare function findSeedCredential({ presentation, appUrl }: {
|
|
106
107
|
presentation: IVerifiablePresentation;
|
|
107
|
-
|
|
108
|
+
appUrl: string;
|
|
108
109
|
}): IVerifiableCredential | null;
|
|
109
110
|
//# sourceMappingURL=seedCredential.d.ts.map
|