@interop/was-react 0.6.0 → 0.7.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 +1 -1
- package/dist/dev/provisionDevGrants.d.ts +2 -2
- package/dist/dev/provisionDevGrants.js +7 -7
- package/dist/dev/provisionDevGrants.js.map +1 -1
- package/dist/identity/seedStore.d.ts +5 -5
- package/dist/identity/seedStore.d.ts.map +1 -1
- package/dist/identity/seedStore.js +6 -6
- package/dist/identity/seedStore.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/session/authStore.js +14 -14
- package/dist/session/authStore.js.map +1 -1
- package/dist/storage/localStore.d.ts +16 -16
- package/dist/storage/localStore.d.ts.map +1 -1
- package/dist/storage/localStore.js +36 -36
- package/dist/storage/localStore.js.map +1 -1
- package/dist/storage/sharedCollectionReader.d.ts +2 -2
- package/dist/storage/sharedCollectionReader.js +8 -8
- package/dist/storage/sharedCollectionReader.js.map +1 -1
- package/dist/storage/wasRemoteStore.d.ts +17 -17
- package/dist/storage/wasRemoteStore.d.ts.map +1 -1
- package/dist/storage/wasRemoteStore.js +11 -11
- package/dist/storage/wasRemoteStore.js.map +1 -1
- package/dist/storage/wasSync.d.ts +5 -5
- package/dist/storage/wasSync.d.ts.map +1 -1
- package/dist/storage/wasSync.js +16 -16
- package/dist/storage/wasSync.js.map +1 -1
- package/dist/sync/docCipher.d.ts +4 -4
- package/dist/sync/docCipher.js +4 -4
- package/dist/sync/wasSyncPort.d.ts +2 -2
- package/dist/sync/wasSyncPort.js +2 -2
- package/package.json +4 -4
package/dist/storage/wasSync.js
CHANGED
|
@@ -22,12 +22,12 @@ import { SharedCollectionReader } from './sharedCollectionReader.js';
|
|
|
22
22
|
* @param [options.identityKeys.keyResolver] {IKeyResolver}
|
|
23
23
|
* @param [options.onAuthError] {() => void} fired when replication hits a
|
|
24
24
|
* 401/403 (expired/revoked access) -- wired to the reconnect banner
|
|
25
|
-
* @param [options.
|
|
26
|
-
* the freshly fetched per-collection encryption
|
|
27
|
-
* id), to refresh the offline
|
|
25
|
+
* @param [options.onDescriptorsFetched] {(descriptors) => void | Promise<void>} given
|
|
26
|
+
* the freshly fetched per-collection encryption descriptors (by WAS collection
|
|
27
|
+
* id), to refresh the offline descriptor cache
|
|
28
28
|
* @returns {Promise<WasSyncBootstrap>}
|
|
29
29
|
*/
|
|
30
|
-
export async function startWasSync({ parsed, zcapClient, collections, localStore, syncController, onRemoteChange, sharedCollections = [], identityKeys, onAuthError,
|
|
30
|
+
export async function startWasSync({ parsed, zcapClient, collections, localStore, syncController, onRemoteChange, sharedCollections = [], identityKeys, onAuthError, onDescriptorsFetched }) {
|
|
31
31
|
const remoteStore = WasRemoteStore.fromGrants({
|
|
32
32
|
parsed,
|
|
33
33
|
zcapClient,
|
|
@@ -37,43 +37,43 @@ export async function startWasSync({ parsed, zcapClient, collections, localStore
|
|
|
37
37
|
// replicate into an unmarked collection just the same, and a query against
|
|
38
38
|
// undeclared indexes fails with a descriptive 400). Each helper skips the
|
|
39
39
|
// collections it does not apply to (reported ok + skipped): the encryption
|
|
40
|
-
//
|
|
40
|
+
// descriptor skips public collections, the indexes declaration skips private
|
|
41
41
|
// ones and public ones with no declared indexes.
|
|
42
42
|
const sharedIds = new Set(sharedCollections.map(entry => entry.id));
|
|
43
43
|
await Promise.all(Object.keys(parsed.byCollectionId)
|
|
44
44
|
.filter(collectionId => !sharedIds.has(collectionId))
|
|
45
45
|
.map(async (collectionId) => {
|
|
46
|
-
const
|
|
47
|
-
if (!
|
|
48
|
-
console.warn(`Encryption
|
|
46
|
+
const declared = await remoteStore.markCollectionEncrypted(collectionId);
|
|
47
|
+
if (!declared.ok) {
|
|
48
|
+
console.warn(`Encryption descriptor PUT not authorized for "${collectionId}" (status ${declared.status ?? 'n/a'}).`);
|
|
49
49
|
}
|
|
50
50
|
const indexes = await remoteStore.declareCollectionIndexes(collectionId);
|
|
51
51
|
if (!indexes.ok) {
|
|
52
52
|
console.warn(`Indexes declaration PUT not authorized for "${collectionId}" (status ${indexes.status ?? 'n/a'}).`);
|
|
53
53
|
}
|
|
54
54
|
}));
|
|
55
|
-
// Fetch each granted private collection's encryption
|
|
55
|
+
// Fetch each granted private collection's encryption descriptor: rebuild that
|
|
56
56
|
// collection's cipher when its epoch roster differs from what the local store
|
|
57
57
|
// opened with (a wallet-side rotation, or first-ever epochs), and hand the
|
|
58
|
-
// fresh set to the
|
|
58
|
+
// fresh set to the descriptor-cache refresher so an offline session can rebuild
|
|
59
59
|
// its epoch-aware ciphers without a live read.
|
|
60
60
|
const privateIds = collections
|
|
61
61
|
.filter(collection => collection.visibility !== 'public')
|
|
62
62
|
.map(collection => collection.id)
|
|
63
63
|
.filter(id => parsed.byCollectionId[id] !== undefined);
|
|
64
|
-
const
|
|
64
|
+
const descriptors = {};
|
|
65
65
|
await Promise.all(privateIds.map(async (collectionId) => {
|
|
66
66
|
const encryption = await remoteStore.readCollectionEncryption(collectionId);
|
|
67
67
|
if (encryption) {
|
|
68
|
-
|
|
69
|
-
await localStore.
|
|
68
|
+
descriptors[collectionId] = encryption;
|
|
69
|
+
await localStore.applyRemoteDescriptor({ collectionId, encryption });
|
|
70
70
|
}
|
|
71
71
|
}));
|
|
72
72
|
// Install the one-shot epoch refresher so a decrypt that meets an unseen epoch
|
|
73
|
-
// (a rotation on another device) re-reads the
|
|
73
|
+
// (a rotation on another device) re-reads the descriptor and rebuilds the cipher.
|
|
74
74
|
localStore.setEpochRefresher(collectionId => remoteStore.readCollectionEncryption(collectionId));
|
|
75
|
-
if (
|
|
76
|
-
await
|
|
75
|
+
if (onDescriptorsFetched) {
|
|
76
|
+
await onDescriptorsFetched(descriptors);
|
|
77
77
|
}
|
|
78
78
|
// Shared collections stay entirely out of replication: one read-only reader
|
|
79
79
|
// each, opened over the delegated read zcap and the collection's epoch
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasSync.js","sourceRoot":"","sources":["../../src/storage/wasSync.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AAcpE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EACjC,MAAM,EACN,UAAU,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,cAAc,EACd,iBAAiB,GAAG,EAAE,EACtB,YAAY,EACZ,WAAW,EACX,
|
|
1
|
+
{"version":3,"file":"wasSync.js","sourceRoot":"","sources":["../../src/storage/wasSync.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/docCipher.d.ts
CHANGED
|
@@ -79,10 +79,10 @@ export declare function createPlaintextDocCodec({ collectionId }: {
|
|
|
79
79
|
* (constant bump / toggle / re-categorize edits).
|
|
80
80
|
*
|
|
81
81
|
* Delegates to `@interop/was-client`'s `createEdvDocCipher`: with no
|
|
82
|
-
* `encryption`
|
|
82
|
+
* `encryption` descriptor (or a descriptor with no key epochs) the cipher is
|
|
83
83
|
* single-recipient (the key-agreement key encrypts and decrypts directly, the
|
|
84
|
-
* behavior every collection has had); with epochs on the
|
|
85
|
-
* becomes multi-recipient -- writes stamp the
|
|
84
|
+
* behavior every collection has had); with epochs on the descriptor the cipher
|
|
85
|
+
* becomes multi-recipient -- writes stamp the descriptor's current epoch and reads
|
|
86
86
|
* route by the envelope's recipient key id, while a pre-epoch envelope still
|
|
87
87
|
* decrypts through the single-key path (a permanent tolerance, not a migration
|
|
88
88
|
* shim). The returned cipher's shape matches {@link DocCipher} exactly; only the
|
|
@@ -93,7 +93,7 @@ export declare function createPlaintextDocCodec({ collectionId }: {
|
|
|
93
93
|
* @param options.keyResolver {IKeyResolver}
|
|
94
94
|
* @param options.collectionId {string} labels errors; the codec is agnostic
|
|
95
95
|
* @param [options.encryption] {CollectionEncryption} the collection's
|
|
96
|
-
* encryption
|
|
96
|
+
* encryption descriptor; when it carries key epochs the cipher becomes
|
|
97
97
|
* multi-recipient
|
|
98
98
|
* @returns {Promise<DocCipher>}
|
|
99
99
|
*/
|
package/dist/sync/docCipher.js
CHANGED
|
@@ -65,10 +65,10 @@ export function createPlaintextDocCodec({ collectionId }) {
|
|
|
65
65
|
* (constant bump / toggle / re-categorize edits).
|
|
66
66
|
*
|
|
67
67
|
* Delegates to `@interop/was-client`'s `createEdvDocCipher`: with no
|
|
68
|
-
* `encryption`
|
|
68
|
+
* `encryption` descriptor (or a descriptor with no key epochs) the cipher is
|
|
69
69
|
* single-recipient (the key-agreement key encrypts and decrypts directly, the
|
|
70
|
-
* behavior every collection has had); with epochs on the
|
|
71
|
-
* becomes multi-recipient -- writes stamp the
|
|
70
|
+
* behavior every collection has had); with epochs on the descriptor the cipher
|
|
71
|
+
* becomes multi-recipient -- writes stamp the descriptor's current epoch and reads
|
|
72
72
|
* route by the envelope's recipient key id, while a pre-epoch envelope still
|
|
73
73
|
* decrypts through the single-key path (a permanent tolerance, not a migration
|
|
74
74
|
* shim). The returned cipher's shape matches {@link DocCipher} exactly; only the
|
|
@@ -79,7 +79,7 @@ export function createPlaintextDocCodec({ collectionId }) {
|
|
|
79
79
|
* @param options.keyResolver {IKeyResolver}
|
|
80
80
|
* @param options.collectionId {string} labels errors; the codec is agnostic
|
|
81
81
|
* @param [options.encryption] {CollectionEncryption} the collection's
|
|
82
|
-
* encryption
|
|
82
|
+
* encryption descriptor; when it carries key epochs the cipher becomes
|
|
83
83
|
* multi-recipient
|
|
84
84
|
* @returns {Promise<DocCipher>}
|
|
85
85
|
*/
|
|
@@ -30,7 +30,7 @@ import { type WasSyncBasePort } from './types.js';
|
|
|
30
30
|
* Extracts an HTTP status from a raw ky/ezcap error. `was.request()` rejects on
|
|
31
31
|
* any non-2xx with `err.status` set (see `@interop/http-client`'s error
|
|
32
32
|
* normaliser); this reads it defensively from either location. Shared with the
|
|
33
|
-
* remote store's
|
|
33
|
+
* remote store's descriptor PUT and the dev-grant provisioner, which need the raw
|
|
34
34
|
* status for diagnostics rather than the mapped sync error.
|
|
35
35
|
*
|
|
36
36
|
* @param err {unknown}
|
|
@@ -40,7 +40,7 @@ export declare function errorStatus(err: unknown): number | undefined;
|
|
|
40
40
|
/**
|
|
41
41
|
* Normalizes an unknown caught error into a display string: the `Error`'s
|
|
42
42
|
* `message` when it is one, else its `String(...)` coercion. Shared by the
|
|
43
|
-
* remote store's
|
|
43
|
+
* remote store's descriptor PUT and the session activation error path.
|
|
44
44
|
*
|
|
45
45
|
* @param err {unknown}
|
|
46
46
|
* @returns {string}
|
package/dist/sync/wasSyncPort.js
CHANGED
|
@@ -29,7 +29,7 @@ import { WasSyncAuthError, WasSyncConflictError } from './types.js';
|
|
|
29
29
|
* Extracts an HTTP status from a raw ky/ezcap error. `was.request()` rejects on
|
|
30
30
|
* any non-2xx with `err.status` set (see `@interop/http-client`'s error
|
|
31
31
|
* normaliser); this reads it defensively from either location. Shared with the
|
|
32
|
-
* remote store's
|
|
32
|
+
* remote store's descriptor PUT and the dev-grant provisioner, which need the raw
|
|
33
33
|
* status for diagnostics rather than the mapped sync error.
|
|
34
34
|
*
|
|
35
35
|
* @param err {unknown}
|
|
@@ -42,7 +42,7 @@ export function errorStatus(err) {
|
|
|
42
42
|
/**
|
|
43
43
|
* Normalizes an unknown caught error into a display string: the `Error`'s
|
|
44
44
|
* `message` when it is one, else its `String(...)` coercion. Shared by the
|
|
45
|
-
* remote store's
|
|
45
|
+
* remote store's descriptor PUT and the session activation error path.
|
|
46
46
|
*
|
|
47
47
|
* @param err {unknown}
|
|
48
48
|
* @returns {string}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interop/was-react",
|
|
3
3
|
"description": "React library for building 'Bring Your Own Everything' (BYOE) apps on Wallet Attached Storage: DID Auth login via CHAPI wallet, local-first encrypted storage, and background sync to a WAS server.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.7.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "pnpm run clear && tsc",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"@interop/security-document-loader": "^9.5.0",
|
|
54
54
|
"@interop/vc": "^11.0.6",
|
|
55
55
|
"@interop/verifier-core": "^3.5.0",
|
|
56
|
-
"@interop/wallet-core": "^0.
|
|
57
|
-
"@interop/was-client": "^0.
|
|
56
|
+
"@interop/wallet-core": "^0.8.0",
|
|
57
|
+
"@interop/was-client": "^0.23.0",
|
|
58
58
|
"@interop/webkms-client": "^14.7.1",
|
|
59
59
|
"@interop/x25519-key-agreement-key": "^5.2.1",
|
|
60
60
|
"@scure/base": "^2.2.0",
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"typescript-eslint": "^8.59.4",
|
|
111
111
|
"vite": "^8.0.14",
|
|
112
112
|
"vitest": "^4.1.7",
|
|
113
|
-
"was-teaching-server": "^0.
|
|
113
|
+
"was-teaching-server": "^0.16.0",
|
|
114
114
|
"zustand": "^5.0.12"
|
|
115
115
|
},
|
|
116
116
|
"publishConfig": {
|