@interop/wallet-core 0.83.1 → 0.85.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 +13 -3
- package/dist/menders/derive.d.ts +1 -0
- package/dist/menders/derive.d.ts.map +1 -1
- package/dist/menders/derive.js +4 -1
- package/dist/menders/derive.js.map +1 -1
- package/dist/menders/ids.d.ts +1 -1
- package/dist/menders/ids.d.ts.map +1 -1
- package/dist/menders/ids.js +3 -1
- package/dist/menders/ids.js.map +1 -1
- package/dist/menders/vocabulary.d.ts +4 -2
- package/dist/menders/vocabulary.d.ts.map +1 -1
- package/dist/menders/vocabulary.js +5 -2
- package/dist/menders/vocabulary.js.map +1 -1
- package/dist/space/collections.d.ts +17 -2
- package/dist/space/collections.d.ts.map +1 -1
- package/dist/space/collections.js +26 -2
- package/dist/space/collections.js.map +1 -1
- package/dist/space/index.d.ts +1 -1
- package/dist/space/index.d.ts.map +1 -1
- package/dist/space/index.js +1 -1
- package/dist/space/index.js.map +1 -1
- package/dist/sync/engine.d.ts +11 -0
- package/dist/sync/engine.d.ts.map +1 -1
- package/dist/sync/engine.js +2 -0
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/pull.d.ts +8 -2
- package/dist/sync/pull.d.ts.map +1 -1
- package/dist/sync/pull.js +55 -4
- package/dist/sync/pull.js.map +1 -1
- package/dist/sync/push.d.ts +4 -1
- package/dist/sync/push.d.ts.map +1 -1
- package/dist/sync/push.js +22 -8
- package/dist/sync/push.js.map +1 -1
- package/dist/sync/types.d.ts +22 -0
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/writers/entry.d.ts +95 -0
- package/dist/writers/entry.d.ts.map +1 -0
- package/dist/writers/entry.js +90 -0
- package/dist/writers/entry.js.map +1 -0
- package/dist/writers/index.d.ts +17 -0
- package/dist/writers/index.d.ts.map +1 -0
- package/dist/writers/index.js +14 -0
- package/dist/writers/index.js.map +1 -0
- package/dist/writers/roster.d.ts +152 -0
- package/dist/writers/roster.d.ts.map +1 -0
- package/dist/writers/roster.js +365 -0
- package/dist/writers/roster.js.map +1 -0
- package/dist/writers/store.d.ts +71 -0
- package/dist/writers/store.d.ts.map +1 -0
- package/dist/writers/store.js +55 -0
- package/dist/writers/store.js.map +1 -0
- package/package.json +10 -4
package/dist/sync/push.d.ts
CHANGED
|
@@ -9,15 +9,18 @@ import type { ResolveConflict, SyncStore, WasSyncPort } from './types.js';
|
|
|
9
9
|
* @param options.port {WasSyncPort}
|
|
10
10
|
* @param options.store {SyncStore}
|
|
11
11
|
* @param [options.resolveConflict] {ResolveConflict} mutable-collection policy
|
|
12
|
+
* @param [options.writerId] {string} this writer's attribution label, sent
|
|
13
|
+
* as `Writer-Id` on every write and delete; absent sends none
|
|
12
14
|
* @param [options.signal] {AbortSignal}
|
|
13
15
|
* @returns {Promise<{ pushed: number; conflictsResolved: number }>} dirty rows
|
|
14
16
|
* processed this cycle, and how many invoked the LWW resolver (a positive
|
|
15
17
|
* count means the caller should rerun so a local-wins re-push settles)
|
|
16
18
|
*/
|
|
17
|
-
export declare function runPush({ port, store, resolveConflict, signal }: {
|
|
19
|
+
export declare function runPush({ port, store, resolveConflict, writerId, signal }: {
|
|
18
20
|
port: WasSyncPort;
|
|
19
21
|
store: SyncStore;
|
|
20
22
|
resolveConflict?: ResolveConflict;
|
|
23
|
+
writerId?: string;
|
|
21
24
|
signal?: AbortSignal;
|
|
22
25
|
}): Promise<{
|
|
23
26
|
pushed: number;
|
package/dist/sync/push.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAQ,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAqM/E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,OAAO,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,eAAe,EACf,QAAQ,EACR,MAAM,EACP,EAAE;IACD,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,EAAE,SAAS,CAAA;IAChB,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC,CAyBzD"}
|
package/dist/sync/push.js
CHANGED
|
@@ -24,6 +24,13 @@
|
|
|
24
24
|
* folding a `putMeta` diff into this loop would add an untested code path with
|
|
25
25
|
* no collection to exercise it. The `WasSyncPort.putMeta` capability stays
|
|
26
26
|
* optional on the port for the driver that needs it.
|
|
27
|
+
*
|
|
28
|
+
* Every content write and delete carries the engine's injected `writerId`, when
|
|
29
|
+
* one was injected, as the `Writer-Id` header (the WAS writer-attribution
|
|
30
|
+
* label). The label is minted app-side; this loop never mints, persists, or
|
|
31
|
+
* derives one. The server's declare-or-clear rule means a write without it
|
|
32
|
+
* clears the stored label, so an engine run without a `writerId` attributes
|
|
33
|
+
* nothing rather than leaving a previous writer's label in place.
|
|
27
34
|
*/
|
|
28
35
|
import { isSyncConflictError, isSyncNotFoundError } from '@interop/was-client/sync';
|
|
29
36
|
/**
|
|
@@ -46,12 +53,13 @@ import { isSyncConflictError, isSyncNotFoundError } from '@interop/was-client/sy
|
|
|
46
53
|
* absent/tombstone -> deletion wins, adopt the tombstone and delete the
|
|
47
54
|
* projection (a later re-add re-encrypts to a fresh id, so nothing is blocked).
|
|
48
55
|
*/
|
|
49
|
-
async function pushUpsert({ port, store, row, resolveConflict }) {
|
|
56
|
+
async function pushUpsert({ port, store, row, resolveConflict, writerId }) {
|
|
50
57
|
try {
|
|
51
58
|
const ack = await port.putContent({
|
|
52
59
|
id: row.id,
|
|
53
60
|
data: row.data ?? null,
|
|
54
|
-
...(row.version > 0 ? { ifMatch: row.etag } : { ifNoneMatch: true })
|
|
61
|
+
...(row.version > 0 ? { ifMatch: row.etag } : { ifNoneMatch: true }),
|
|
62
|
+
...(writerId !== undefined && { writerId })
|
|
55
63
|
});
|
|
56
64
|
await store.markPushed({
|
|
57
65
|
id: row.id,
|
|
@@ -100,12 +108,13 @@ async function pushUpsert({ port, store, row, resolveConflict }) {
|
|
|
100
108
|
* on a `412` so the caller can re-read and retry. Any other error propagates to
|
|
101
109
|
* the engine's backoff.
|
|
102
110
|
*/
|
|
103
|
-
async function tryDelete({ port, store, id, ifMatch, revision }) {
|
|
111
|
+
async function tryDelete({ port, store, id, ifMatch, revision, writerId }) {
|
|
104
112
|
const revisionAck = revision !== undefined ? { revision } : {};
|
|
105
113
|
try {
|
|
106
114
|
const ack = await port.deleteContent({
|
|
107
115
|
id,
|
|
108
|
-
...(ifMatch !== undefined && { ifMatch })
|
|
116
|
+
...(ifMatch !== undefined && { ifMatch }),
|
|
117
|
+
...(writerId !== undefined && { writerId })
|
|
109
118
|
});
|
|
110
119
|
await store.markDeletedPushed({
|
|
111
120
|
id,
|
|
@@ -136,7 +145,7 @@ async function tryDelete({ port, store, id, ifMatch, revision }) {
|
|
|
136
145
|
* refreshes its `version` / `etag` via the dirty-deleted-vs-live rule, so the
|
|
137
146
|
* retry's `If-Match` becomes current).
|
|
138
147
|
*/
|
|
139
|
-
async function pushDelete({ port, store, row }) {
|
|
148
|
+
async function pushDelete({ port, store, row, writerId }) {
|
|
140
149
|
const revisionAck = row.revision !== undefined ? { revision: row.revision } : {};
|
|
141
150
|
const firstIfMatch = row.version > 0 ? row.etag : undefined;
|
|
142
151
|
if (await tryDelete({
|
|
@@ -144,6 +153,7 @@ async function pushDelete({ port, store, row }) {
|
|
|
144
153
|
store,
|
|
145
154
|
id: row.id,
|
|
146
155
|
ifMatch: firstIfMatch,
|
|
156
|
+
writerId,
|
|
147
157
|
...revisionAck
|
|
148
158
|
})) {
|
|
149
159
|
return;
|
|
@@ -162,6 +172,7 @@ async function pushDelete({ port, store, row }) {
|
|
|
162
172
|
store,
|
|
163
173
|
id: row.id,
|
|
164
174
|
ifMatch: master.etag,
|
|
175
|
+
writerId,
|
|
165
176
|
...revisionAck
|
|
166
177
|
});
|
|
167
178
|
}
|
|
@@ -175,12 +186,14 @@ async function pushDelete({ port, store, row }) {
|
|
|
175
186
|
* @param options.port {WasSyncPort}
|
|
176
187
|
* @param options.store {SyncStore}
|
|
177
188
|
* @param [options.resolveConflict] {ResolveConflict} mutable-collection policy
|
|
189
|
+
* @param [options.writerId] {string} this writer's attribution label, sent
|
|
190
|
+
* as `Writer-Id` on every write and delete; absent sends none
|
|
178
191
|
* @param [options.signal] {AbortSignal}
|
|
179
192
|
* @returns {Promise<{ pushed: number; conflictsResolved: number }>} dirty rows
|
|
180
193
|
* processed this cycle, and how many invoked the LWW resolver (a positive
|
|
181
194
|
* count means the caller should rerun so a local-wins re-push settles)
|
|
182
195
|
*/
|
|
183
|
-
export async function runPush({ port, store, resolveConflict, signal }) {
|
|
196
|
+
export async function runPush({ port, store, resolveConflict, writerId, signal }) {
|
|
184
197
|
const rows = await store.getDirtyRows();
|
|
185
198
|
let pushed = 0;
|
|
186
199
|
let conflictsResolved = 0;
|
|
@@ -189,14 +202,15 @@ export async function runPush({ port, store, resolveConflict, signal }) {
|
|
|
189
202
|
break;
|
|
190
203
|
}
|
|
191
204
|
if (row.deleted) {
|
|
192
|
-
await pushDelete({ port, store, row });
|
|
205
|
+
await pushDelete({ port, store, row, writerId });
|
|
193
206
|
}
|
|
194
207
|
else {
|
|
195
208
|
const { conflictResolved } = await pushUpsert({
|
|
196
209
|
port,
|
|
197
210
|
store,
|
|
198
211
|
row,
|
|
199
|
-
resolveConflict
|
|
212
|
+
resolveConflict,
|
|
213
|
+
writerId
|
|
200
214
|
});
|
|
201
215
|
if (conflictResolved) {
|
|
202
216
|
conflictsResolved += 1;
|
package/dist/sync/push.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/types.d.ts
CHANGED
|
@@ -165,6 +165,28 @@ export interface SyncStore {
|
|
|
165
165
|
latest: MasterState | null;
|
|
166
166
|
projection: ProjectionAction;
|
|
167
167
|
}): Promise<void>;
|
|
168
|
+
/**
|
|
169
|
+
* Which of these feed revisions does the replica already hold? Answers with
|
|
170
|
+
* the ids whose local row records exactly that `etag` as its validator (the
|
|
171
|
+
* one a push ack or an earlier pull recorded). The pull loop asks it only
|
|
172
|
+
* about live feed documents carrying the engine's own `writerId`, and skips
|
|
173
|
+
* the decrypt of each confirmed one, applying it with a `none` projection
|
|
174
|
+
* (see `pull.ts`). The label is host-visible plaintext, so the skip also
|
|
175
|
+
* requires the `etag` match. That match limits the skip to a revision the
|
|
176
|
+
* replica already records. It does not authenticate the label or the
|
|
177
|
+
* envelope, since the `etag` is host-supplied too. A host that replays an
|
|
178
|
+
* older envelope under the current `etag` gets the local projection left
|
|
179
|
+
* as it was, where a decrypt would have rolled it back.
|
|
180
|
+
*
|
|
181
|
+
* Optional: a store that omits it turns echo suppression off, and every
|
|
182
|
+
* echo is decrypted as before.
|
|
183
|
+
*/
|
|
184
|
+
heldRevisions?(options: {
|
|
185
|
+
documents: {
|
|
186
|
+
id: string;
|
|
187
|
+
etag: string;
|
|
188
|
+
}[];
|
|
189
|
+
}): Promise<Set<string>>;
|
|
168
190
|
/**
|
|
169
191
|
* Replaces the body of a pending row (dirty, never-acked, live -- no feed
|
|
170
192
|
* existence) with a re-minted envelope, re-keying the row from `id` to
|
package/dist/sync/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The version-1 roster entry. A type alias rather than an interface, so it
|
|
3
|
+
* is assignable to was-client's `JsonObject`.
|
|
4
|
+
*/
|
|
5
|
+
export type RegisteredWriterEntry = {
|
|
6
|
+
version: 1;
|
|
7
|
+
/**
|
|
8
|
+
* The writer's `writerId`, verbatim. The resource id is a hash of it, so a
|
|
9
|
+
* reader takes the id from here.
|
|
10
|
+
*/
|
|
11
|
+
writerId: string;
|
|
12
|
+
/**
|
|
13
|
+
* An enrolled wallet client's own signing-key multibase, the key the
|
|
14
|
+
* client-labels record and `listAccountClients` rows are keyed by. Absent
|
|
15
|
+
* for a non-wallet writer.
|
|
16
|
+
*/
|
|
17
|
+
signingKeyMultibase?: string;
|
|
18
|
+
/**
|
|
19
|
+
* A coarse platform self-description, or the user's rename of it.
|
|
20
|
+
*/
|
|
21
|
+
label: string;
|
|
22
|
+
/**
|
|
23
|
+
* ISO 8601 UTC timestamp of the writer's latest liveness touch.
|
|
24
|
+
*/
|
|
25
|
+
lastSeen: string;
|
|
26
|
+
/**
|
|
27
|
+
* `false` once a sweep found `lastSeen` past the inactivity TTL. The writer's
|
|
28
|
+
* next touch sets it back to `true`.
|
|
29
|
+
*/
|
|
30
|
+
active: boolean;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The expiry and liveness policy of the roster. Every replica that sweeps
|
|
34
|
+
* must use the same values, or two sweepers disagree about which entries are
|
|
35
|
+
* orphans.
|
|
36
|
+
*/
|
|
37
|
+
export interface RegisteredWriterPolicy {
|
|
38
|
+
/**
|
|
39
|
+
* How long an entry may go untouched before a sweep marks it inactive.
|
|
40
|
+
*/
|
|
41
|
+
inactiveAfterMs: number;
|
|
42
|
+
/**
|
|
43
|
+
* The entry count past which a sweep (or an enrollment) deletes the
|
|
44
|
+
* oldest-`lastSeen` entries.
|
|
45
|
+
*/
|
|
46
|
+
maxEntries: number;
|
|
47
|
+
/**
|
|
48
|
+
* The least time between two liveness touches by the same writer.
|
|
49
|
+
*/
|
|
50
|
+
touchIntervalMs: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The default policy: inactive after 90 days, at most 64 entries, touched at
|
|
54
|
+
* most once a day. A wallet that overrides any of these passes the same
|
|
55
|
+
* override on every replica.
|
|
56
|
+
*/
|
|
57
|
+
export declare const REGISTERED_WRITER_POLICY: RegisteredWriterPolicy;
|
|
58
|
+
/**
|
|
59
|
+
* The domain label of the resource id hash.
|
|
60
|
+
*/
|
|
61
|
+
export declare const REGISTERED_WRITER_ID_LABEL = "registered-writers/v1";
|
|
62
|
+
/**
|
|
63
|
+
* The resource id of one writer's entry under one account: the first 16
|
|
64
|
+
* bytes of `sha256(utf8('registered-writers/v1|' + accountDid + '|' +
|
|
65
|
+
* writerId))`, formatted as an EDV document id.
|
|
66
|
+
*
|
|
67
|
+
* The id is deterministic, so a registration and a touch are idempotent
|
|
68
|
+
* upserts. It hides the `writerId` from the storage host and does not link
|
|
69
|
+
* one `writerId` across accounts.
|
|
70
|
+
*
|
|
71
|
+
* @param options {object}
|
|
72
|
+
* @param options.accountDid {string} the account whose Space holds the roster
|
|
73
|
+
* @param options.writerId {string}
|
|
74
|
+
* @returns {string}
|
|
75
|
+
*/
|
|
76
|
+
export declare function registeredWriterResourceId({ accountDid, writerId }: {
|
|
77
|
+
accountDid: string;
|
|
78
|
+
writerId: string;
|
|
79
|
+
}): string;
|
|
80
|
+
/**
|
|
81
|
+
* Resolves a partial policy override against the defaults.
|
|
82
|
+
*
|
|
83
|
+
* @param [policy] {Partial<RegisteredWriterPolicy>}
|
|
84
|
+
* @returns {RegisteredWriterPolicy}
|
|
85
|
+
*/
|
|
86
|
+
export declare function registeredWriterPolicy(policy?: Partial<RegisteredWriterPolicy>): RegisteredWriterPolicy;
|
|
87
|
+
/**
|
|
88
|
+
* Reads a stored body as a roster entry, or `undefined` when it is not one.
|
|
89
|
+
* A malformed entry is skipped by every reader, and never repaired.
|
|
90
|
+
*
|
|
91
|
+
* @param body {unknown}
|
|
92
|
+
* @returns {RegisteredWriterEntry | undefined}
|
|
93
|
+
*/
|
|
94
|
+
export declare function parseRegisteredWriterEntry(body: unknown): RegisteredWriterEntry | undefined;
|
|
95
|
+
//# sourceMappingURL=entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/writers/entry.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,CAAC,CAAA;IACV;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,eAAe,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAA;CACxB;AAID;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,sBAItC,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,0BAA0B,0BAA0B,CAAA;AAEjE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,UAAU,EACV,QAAQ,EACT,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;CACjB,GAAG,MAAM,CAKT;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,GACvC,sBAAsB,CAExB;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,OAAO,GACZ,qBAAqB,GAAG,SAAS,CA2BnC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The writer roster's entry: its version-1 shape, the shape check every
|
|
6
|
+
* reader runs, the resource id an entry lives at, and the expiry policy both
|
|
7
|
+
* wallets sweep under.
|
|
8
|
+
*
|
|
9
|
+
* An entry is advisory display data. Its writer asserts every field about
|
|
10
|
+
* itself, and nothing checks them beyond shape. `signingKeyMultibase` links a
|
|
11
|
+
* wallet writer to its enrolled client only when the verified did:webvh
|
|
12
|
+
* document lists that key, and no field is an input to any authorization.
|
|
13
|
+
*/
|
|
14
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
15
|
+
import { edvIdFromBytes } from '@interop/was-client/edv/cipher';
|
|
16
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
17
|
+
/**
|
|
18
|
+
* The default policy: inactive after 90 days, at most 64 entries, touched at
|
|
19
|
+
* most once a day. A wallet that overrides any of these passes the same
|
|
20
|
+
* override on every replica.
|
|
21
|
+
*/
|
|
22
|
+
export const REGISTERED_WRITER_POLICY = {
|
|
23
|
+
inactiveAfterMs: 90 * DAY_MS,
|
|
24
|
+
maxEntries: 64,
|
|
25
|
+
touchIntervalMs: DAY_MS
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The domain label of the resource id hash.
|
|
29
|
+
*/
|
|
30
|
+
export const REGISTERED_WRITER_ID_LABEL = 'registered-writers/v1';
|
|
31
|
+
/**
|
|
32
|
+
* The resource id of one writer's entry under one account: the first 16
|
|
33
|
+
* bytes of `sha256(utf8('registered-writers/v1|' + accountDid + '|' +
|
|
34
|
+
* writerId))`, formatted as an EDV document id.
|
|
35
|
+
*
|
|
36
|
+
* The id is deterministic, so a registration and a touch are idempotent
|
|
37
|
+
* upserts. It hides the `writerId` from the storage host and does not link
|
|
38
|
+
* one `writerId` across accounts.
|
|
39
|
+
*
|
|
40
|
+
* @param options {object}
|
|
41
|
+
* @param options.accountDid {string} the account whose Space holds the roster
|
|
42
|
+
* @param options.writerId {string}
|
|
43
|
+
* @returns {string}
|
|
44
|
+
*/
|
|
45
|
+
export function registeredWriterResourceId({ accountDid, writerId }) {
|
|
46
|
+
const input = new TextEncoder().encode(`${REGISTERED_WRITER_ID_LABEL}|${accountDid}|${writerId}`);
|
|
47
|
+
return edvIdFromBytes(sha256(input).subarray(0, 16));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolves a partial policy override against the defaults.
|
|
51
|
+
*
|
|
52
|
+
* @param [policy] {Partial<RegisteredWriterPolicy>}
|
|
53
|
+
* @returns {RegisteredWriterPolicy}
|
|
54
|
+
*/
|
|
55
|
+
export function registeredWriterPolicy(policy) {
|
|
56
|
+
return { ...REGISTERED_WRITER_POLICY, ...policy };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Reads a stored body as a roster entry, or `undefined` when it is not one.
|
|
60
|
+
* A malformed entry is skipped by every reader, and never repaired.
|
|
61
|
+
*
|
|
62
|
+
* @param body {unknown}
|
|
63
|
+
* @returns {RegisteredWriterEntry | undefined}
|
|
64
|
+
*/
|
|
65
|
+
export function parseRegisteredWriterEntry(body) {
|
|
66
|
+
if (body === null || typeof body !== 'object') {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
const { version, writerId, signingKeyMultibase, label, lastSeen, active } = body;
|
|
70
|
+
if (version !== 1 ||
|
|
71
|
+
typeof writerId !== 'string' ||
|
|
72
|
+
writerId === '' ||
|
|
73
|
+
typeof label !== 'string' ||
|
|
74
|
+
typeof lastSeen !== 'string' ||
|
|
75
|
+
Number.isNaN(Date.parse(lastSeen)) ||
|
|
76
|
+
typeof active !== 'boolean' ||
|
|
77
|
+
(signingKeyMultibase !== undefined &&
|
|
78
|
+
typeof signingKeyMultibase !== 'string')) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
version: 1,
|
|
83
|
+
writerId,
|
|
84
|
+
...(signingKeyMultibase !== undefined && { signingKeyMultibase }),
|
|
85
|
+
label,
|
|
86
|
+
lastSeen,
|
|
87
|
+
active
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/writers/entry.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;GASG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAuD/D,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAElC;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAA2B;IAC9D,eAAe,EAAE,EAAE,GAAG,MAAM;IAC5B,UAAU,EAAE,EAAE;IACd,eAAe,EAAE,MAAM;CACxB,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,uBAAuB,CAAA;AAEjE;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,0BAA0B,CAAC,EACzC,UAAU,EACV,QAAQ,EAIT;IACC,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CACpC,GAAG,0BAA0B,IAAI,UAAU,IAAI,QAAQ,EAAE,CAC1D,CAAA;IACD,OAAO,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AACtD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAwC;IAExC,OAAO,EAAE,GAAG,wBAAwB,EAAE,GAAG,MAAM,EAAE,CAAA;AACnD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,0BAA0B,CACxC,IAAa;IAEb,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,GACvE,IAA+B,CAAA;IACjC,IACE,OAAO,KAAK,CAAC;QACb,OAAO,QAAQ,KAAK,QAAQ;QAC5B,QAAQ,KAAK,EAAE;QACf,OAAO,KAAK,KAAK,QAAQ;QACzB,OAAO,QAAQ,KAAK,QAAQ;QAC5B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,MAAM,KAAK,SAAS;QAC3B,CAAC,mBAAmB,KAAK,SAAS;YAChC,OAAO,mBAAmB,KAAK,QAAQ,CAAC,EAC1C,CAAC;QACD,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO;QACL,OAAO,EAAE,CAAC;QACV,QAAQ;QACR,GAAG,CAAC,mBAAmB,KAAK,SAAS,IAAI,EAAE,mBAAmB,EAAE,CAAC;QACjE,KAAK;QACL,QAAQ;QACR,MAAM;KACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The writer roster: the `registered-writers` collection's entry shape, its
|
|
6
|
+
* resource id, the storage seam and WAS adapter, lazy registration with the
|
|
7
|
+
* throttled liveness touch, the sweep-on-read with two-phase expiry, and the
|
|
8
|
+
* join a history view resolves a revision's `writerId` through. Every field
|
|
9
|
+
* is advisory display data, and none is an input to any decision.
|
|
10
|
+
*/
|
|
11
|
+
export { REGISTERED_WRITER_ID_LABEL, REGISTERED_WRITER_POLICY, parseRegisteredWriterEntry, registeredWriterPolicy, registeredWriterResourceId } from './entry.js';
|
|
12
|
+
export type { RegisteredWriterEntry, RegisteredWriterPolicy } from './entry.js';
|
|
13
|
+
export { wasRegisteredWritersStore } from './store.js';
|
|
14
|
+
export type { RegisteredWritersStore, StoredRegisteredWriter } from './store.js';
|
|
15
|
+
export { registerWriterOnSecondSession, renameRegisteredWriter, resolveRegisteredWriter, sweepRegisteredWriters } from './roster.js';
|
|
16
|
+
export type { RegisteredWritersSweep, ResolvedWriter, WriterRegistrationOutcome, WriterFirstSeenRecord, WriterFirstSeenStore } from './roster.js';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/writers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;GAMG;AACH,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,0BAA0B,EAC3B,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAC/E,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA;AACtD,YAAY,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAChF,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,sBAAsB,EACtB,cAAc,EACd,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The writer roster: the `registered-writers` collection's entry shape, its
|
|
6
|
+
* resource id, the storage seam and WAS adapter, lazy registration with the
|
|
7
|
+
* throttled liveness touch, the sweep-on-read with two-phase expiry, and the
|
|
8
|
+
* join a history view resolves a revision's `writerId` through. Every field
|
|
9
|
+
* is advisory display data, and none is an input to any decision.
|
|
10
|
+
*/
|
|
11
|
+
export { REGISTERED_WRITER_ID_LABEL, REGISTERED_WRITER_POLICY, parseRegisteredWriterEntry, registeredWriterPolicy, registeredWriterResourceId } from './entry.js';
|
|
12
|
+
export { wasRegisteredWritersStore } from './store.js';
|
|
13
|
+
export { registerWriterOnSecondSession, renameRegisteredWriter, resolveRegisteredWriter, sweepRegisteredWriters } from './roster.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/writers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;GAMG;AACH,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,0BAA0B,EAC3B,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA;AAEtD,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { RegisteredWriterEntry, RegisteredWriterPolicy } from './entry.js';
|
|
2
|
+
import type { RegisteredWritersStore } from './store.js';
|
|
3
|
+
/**
|
|
4
|
+
* The writer first-seen record, kept client-local: the account and
|
|
5
|
+
* `writerId` this client's writer first appeared under, and when it last
|
|
6
|
+
* touched its roster entry. One slot, so a writer that moves to another
|
|
7
|
+
* account starts over.
|
|
8
|
+
*/
|
|
9
|
+
export interface WriterFirstSeenRecord {
|
|
10
|
+
accountDid: string;
|
|
11
|
+
writerId: string;
|
|
12
|
+
/**
|
|
13
|
+
* ISO 8601 UTC start of the session the record was written in.
|
|
14
|
+
*/
|
|
15
|
+
firstSessionAt: string;
|
|
16
|
+
/**
|
|
17
|
+
* ISO 8601 UTC time of the latest successful registration or touch.
|
|
18
|
+
*/
|
|
19
|
+
lastTouchedAt?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The client-local seam for the writer first-seen record. Where it lives is
|
|
23
|
+
* the wallet's choice. A forget of this client's local state clears it along with
|
|
24
|
+
* the `writerId`.
|
|
25
|
+
*/
|
|
26
|
+
export interface WriterFirstSeenStore {
|
|
27
|
+
get(): Promise<unknown>;
|
|
28
|
+
put(record: WriterFirstSeenRecord): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* What {@link registerWriterOnSecondSession} did.
|
|
32
|
+
*
|
|
33
|
+
* - `deferred` -- the writer has not yet been encountered in a second session
|
|
34
|
+
* under this account; the first-seen record is (re)written and the roster
|
|
35
|
+
* is untouched.
|
|
36
|
+
* - `fresh` -- the latest touch is within the touch interval; no I/O.
|
|
37
|
+
* - `registered` -- a new entry was written (or a malformed one replaced).
|
|
38
|
+
* - `touched` -- the existing entry's `lastSeen` was advanced.
|
|
39
|
+
* - `raced` -- every attempt lost a conditional write; the next call retries.
|
|
40
|
+
*/
|
|
41
|
+
export type WriterRegistrationOutcome = 'deferred' | 'fresh' | 'registered' | 'touched' | 'raced';
|
|
42
|
+
/**
|
|
43
|
+
* Registers this client's writer in the roster once it is encountered in a
|
|
44
|
+
* second session under the account, and touches its `lastSeen` at most once
|
|
45
|
+
* per touch interval after that. Call it on the wallet's connect or sync path;
|
|
46
|
+
* calls within the interval cost no I/O.
|
|
47
|
+
*
|
|
48
|
+
* A new entry takes `label`. A touch keeps the stored label, so a rename
|
|
49
|
+
* stands, and refreshes `signingKeyMultibase` when one is given. Registering
|
|
50
|
+
* a new entry first makes room under the entry cap, deleting the
|
|
51
|
+
* oldest-`lastSeen` entries.
|
|
52
|
+
*
|
|
53
|
+
* @param options {object}
|
|
54
|
+
* @param options.store {RegisteredWritersStore}
|
|
55
|
+
* @param options.local {WriterFirstSeenStore}
|
|
56
|
+
* @param options.accountDid {string} the account whose Space holds the roster
|
|
57
|
+
* @param options.writerId {string} this client's writer
|
|
58
|
+
* @param options.label {string} the coarse platform self-description a new
|
|
59
|
+
* entry takes
|
|
60
|
+
* @param options.sessionStartedAt {Date} when the current session began; a
|
|
61
|
+
* first-seen record written at or after it is this session's own
|
|
62
|
+
* @param [options.signingKeyMultibase] {string} an enrolled wallet client's
|
|
63
|
+
* own signing-key multibase
|
|
64
|
+
* @param [options.now] {Date}
|
|
65
|
+
* @param [options.policy] {Partial<RegisteredWriterPolicy>}
|
|
66
|
+
* @returns {Promise<WriterRegistrationOutcome>}
|
|
67
|
+
*/
|
|
68
|
+
export declare function registerWriterOnSecondSession({ store, local, accountDid, writerId, label, sessionStartedAt, signingKeyMultibase, now, policy }: {
|
|
69
|
+
store: RegisteredWritersStore;
|
|
70
|
+
local: WriterFirstSeenStore;
|
|
71
|
+
accountDid: string;
|
|
72
|
+
writerId: string;
|
|
73
|
+
label: string;
|
|
74
|
+
sessionStartedAt: Date;
|
|
75
|
+
signingKeyMultibase?: string;
|
|
76
|
+
now?: Date;
|
|
77
|
+
policy?: Partial<RegisteredWriterPolicy>;
|
|
78
|
+
}): Promise<WriterRegistrationOutcome>;
|
|
79
|
+
/**
|
|
80
|
+
* Renames this client's writer. The rename lands only on a registered entry;
|
|
81
|
+
* before registration there is nothing to rename, and the call returns
|
|
82
|
+
* `false`.
|
|
83
|
+
*
|
|
84
|
+
* @param options {object}
|
|
85
|
+
* @param options.store {RegisteredWritersStore}
|
|
86
|
+
* @param options.accountDid {string}
|
|
87
|
+
* @param options.writerId {string}
|
|
88
|
+
* @param options.label {string} the new label; blank is refused
|
|
89
|
+
* @returns {Promise<boolean>} whether an entry was renamed
|
|
90
|
+
*/
|
|
91
|
+
export declare function renameRegisteredWriter({ store, accountDid, writerId, label }: {
|
|
92
|
+
store: RegisteredWritersStore;
|
|
93
|
+
accountDid: string;
|
|
94
|
+
writerId: string;
|
|
95
|
+
label: string;
|
|
96
|
+
}): Promise<boolean>;
|
|
97
|
+
/**
|
|
98
|
+
* The outcome of a sweep: the entries left standing, and what it changed.
|
|
99
|
+
*/
|
|
100
|
+
export interface RegisteredWritersSweep {
|
|
101
|
+
entries: RegisteredWriterEntry[];
|
|
102
|
+
markedInactive: string[];
|
|
103
|
+
deleted: string[];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Reads the roster and sweeps it: the sweep-on-read every history view runs.
|
|
107
|
+
* Safe to run from any replica, and concurrently.
|
|
108
|
+
*
|
|
109
|
+
* @param options {object}
|
|
110
|
+
* @param options.store {RegisteredWritersStore}
|
|
111
|
+
* @param options.accountDid {string} the account whose Space holds the roster
|
|
112
|
+
* @param [options.now] {Date}
|
|
113
|
+
* @param [options.policy] {Partial<RegisteredWriterPolicy>}
|
|
114
|
+
* @returns {Promise<RegisteredWritersSweep>}
|
|
115
|
+
*/
|
|
116
|
+
export declare function sweepRegisteredWriters({ store, accountDid, now, policy }: {
|
|
117
|
+
store: RegisteredWritersStore;
|
|
118
|
+
accountDid: string;
|
|
119
|
+
now?: Date;
|
|
120
|
+
policy?: Partial<RegisteredWriterPolicy>;
|
|
121
|
+
}): Promise<RegisteredWritersSweep>;
|
|
122
|
+
/**
|
|
123
|
+
* How a history view renders one revision's writer. `undefined` from
|
|
124
|
+
* {@link resolveRegisteredWriter} means no entry: the view renders its
|
|
125
|
+
* fallback label ("another session").
|
|
126
|
+
*/
|
|
127
|
+
export interface ResolvedWriter {
|
|
128
|
+
label: string;
|
|
129
|
+
active: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Present only when the entry's `signingKeyMultibase` is an enrolled
|
|
132
|
+
* client's key in the verified account document. The view may then link
|
|
133
|
+
* the revision to that client's row. Absent, the label stands unlinked.
|
|
134
|
+
*/
|
|
135
|
+
clientSigningKeyMultibase?: string;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Resolves a revision's `writerId` against the swept roster.
|
|
139
|
+
*
|
|
140
|
+
* @param options {object}
|
|
141
|
+
* @param options.writerId {string}
|
|
142
|
+
* @param options.entries {RegisteredWriterEntry[]} a sweep's `entries`
|
|
143
|
+
* @param options.enrolledSigningKeys {ReadonlySet<string>} the signing-key
|
|
144
|
+
* multibases of the enrolled clients in the verified account document
|
|
145
|
+
* @returns {ResolvedWriter | undefined}
|
|
146
|
+
*/
|
|
147
|
+
export declare function resolveRegisteredWriter({ writerId, entries, enrolledSigningKeys }: {
|
|
148
|
+
writerId: string;
|
|
149
|
+
entries: RegisteredWriterEntry[];
|
|
150
|
+
enrolledSigningKeys: ReadonlySet<string>;
|
|
151
|
+
}): ResolvedWriter | undefined;
|
|
152
|
+
//# sourceMappingURL=roster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roster.d.ts","sourceRoot":"","sources":["../../src/writers/roster.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAA0B,MAAM,YAAY,CAAA;AAEhF;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,cAAc,EAAE,MAAM,CAAA;IACtB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACvB,GAAG,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClD;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,yBAAyB,GACnC,UAAU,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,GAAG,OAAO,CAAA;AAyI3D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,6BAA6B,CAAC,EAClD,KAAK,EACL,KAAK,EACL,UAAU,EACV,QAAQ,EACR,KAAK,EACL,gBAAgB,EAChB,mBAAmB,EACnB,GAAgB,EAChB,MAAM,EACP,EAAE;IACD,KAAK,EAAE,sBAAsB,CAAA;IAC7B,KAAK,EAAE,oBAAoB,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,gBAAgB,EAAE,IAAI,CAAA;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,GAAG,CAAC,EAAE,IAAI,CAAA;IACV,MAAM,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA;CACzC,GAAG,OAAO,CAAC,yBAAyB,CAAC,CA0ErC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAAC,EAC3C,KAAK,EACL,UAAU,EACV,QAAQ,EACR,KAAK,EACN,EAAE;IACD,KAAK,EAAE,sBAAsB,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CACd,GAAG,OAAO,CAAC,OAAO,CAAC,CAoBnB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,qBAAqB,EAAE,CAAA;IAChC,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAiGD;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAAC,EAC3C,KAAK,EACL,UAAU,EACV,GAAgB,EAChB,MAAM,EACP,EAAE;IACD,KAAK,EAAE,sBAAsB,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,IAAI,CAAA;IACV,MAAM,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA;CACzC,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAUlC;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf;;;;OAIG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAA;CACnC;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,OAAO,EACP,mBAAmB,EACpB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,qBAAqB,EAAE,CAAA;IAChC,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CACzC,GAAG,cAAc,GAAG,SAAS,CAa7B"}
|