@interop/wallet-core 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/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/dist/markers/acquire.d.ts +107 -0
- package/dist/markers/acquire.d.ts.map +1 -0
- package/dist/markers/acquire.js +83 -0
- package/dist/markers/acquire.js.map +1 -0
- package/dist/markers/cipher.d.ts +56 -0
- package/dist/markers/cipher.d.ts.map +1 -0
- package/dist/markers/cipher.js +73 -0
- package/dist/markers/cipher.js.map +1 -0
- package/dist/markers/index.d.ts +30 -0
- package/dist/markers/index.d.ts.map +1 -0
- package/dist/markers/index.js +29 -0
- package/dist/markers/index.js.map +1 -0
- package/dist/markers/refresh.d.ts +60 -0
- package/dist/markers/refresh.d.ts.map +1 -0
- package/dist/markers/refresh.js +67 -0
- package/dist/markers/refresh.js.map +1 -0
- package/dist/recovery/index.d.ts +31 -0
- package/dist/recovery/index.d.ts.map +1 -0
- package/dist/recovery/index.js +28 -0
- package/dist/recovery/index.js.map +1 -0
- package/dist/recovery/recoveryCode.d.ts +105 -0
- package/dist/recovery/recoveryCode.d.ts.map +1 -0
- package/dist/recovery/recoveryCode.js +155 -0
- package/dist/recovery/recoveryCode.js.map +1 -0
- package/dist/recovery/recoveryRecord.d.ts +75 -0
- package/dist/recovery/recoveryRecord.d.ts.map +1 -0
- package/dist/recovery/recoveryRecord.js +89 -0
- package/dist/recovery/recoveryRecord.js.map +1 -0
- package/dist/recovery/recoveryWebvh.d.ts +126 -0
- package/dist/recovery/recoveryWebvh.d.ts.map +1 -0
- package/dist/recovery/recoveryWebvh.js +379 -0
- package/dist/recovery/recoveryWebvh.js.map +1 -0
- package/dist/webvh/didWebvh.d.ts +79 -0
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +5 -5
- package/dist/webvh/didWebvh.js.map +1 -1
- package/package.json +13 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The `@interop/wallet-core/recovery` subpath: recovery codes on the roster
|
|
6
|
+
* identity model -- a code as a minimal always-enrolled wallet client.
|
|
7
|
+
*
|
|
8
|
+
* - `generateRecoveryCode` / `formatRecoveryCode` / `normalizeRecoveryCode` /
|
|
9
|
+
* `decodeRecoveryCode` / `RECOVERY_KDF` -- the format layer and the code's
|
|
10
|
+
* own unlock-derivation parameter set (its salt distinct from every other
|
|
11
|
+
* unlock method's).
|
|
12
|
+
* - `recoveryClientFromCode` -- the deterministic client key set:
|
|
13
|
+
* unlock identity, client seed (signing + key-agreement pair), and the
|
|
14
|
+
* single did:webvh update key whose hash stands pre-committed.
|
|
15
|
+
* - `wrapRecoveryRecord` / `unwrapRecoveryRecord` -- the keyring-record
|
|
16
|
+
* sibling carrying the account pointer plus the pre-minted
|
|
17
|
+
* PUT-on-`did.jsonl` delegation (never a seed, never a PUK wrap).
|
|
18
|
+
* - `publishRecoveryKey` / `removeRecoveryKey` / `recoverWebvhClient` -- the
|
|
19
|
+
* document half: issuance's split posture, revocation's removal, and the
|
|
20
|
+
* self-enrolling recovery continuation.
|
|
21
|
+
*
|
|
22
|
+
* Kept out of the root export: this subpath pulls the webkms-client / ezcap /
|
|
23
|
+
* was-client dependency graph (the same isolation pattern as `./keyring`).
|
|
24
|
+
*/
|
|
25
|
+
export { decodeRecoveryCode, formatRecoveryCode, generateRecoveryCode, normalizeRecoveryCode, RECOVERY_CODE_BYTES, RECOVERY_KDF, RecoveryCodeInvalidError, recoveryClientFromCode } from './recoveryCode.js';
|
|
26
|
+
export { unwrapRecoveryRecord, wrapRecoveryRecord } from './recoveryRecord.js';
|
|
27
|
+
export { publishRecoveryKey, recoverWebvhClient, RecoveryKeyNotCommittedError, recoveryVmId, removeRecoveryKey } from './recoveryWebvh.js';
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/recovery/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,YAAY,EACZ,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAG9E,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,4BAA4B,EAC5B,YAAY,EACZ,iBAAiB,EAClB,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { ProfileAgents } from '../identity/agents.js';
|
|
2
|
+
import type { UnlockKdf } from '../keyring/kdf.js';
|
|
3
|
+
/**
|
|
4
|
+
* The byte length of a recovery code: 16 random bytes is ~128 bits, enough
|
|
5
|
+
* that the unlock derivation is a single expansion rather than a stretched
|
|
6
|
+
* KDF (there is nothing to stretch -- the code is already uniform).
|
|
7
|
+
*/
|
|
8
|
+
export declare const RECOVERY_CODE_BYTES = 16;
|
|
9
|
+
/**
|
|
10
|
+
* HKDF parameters for the recovery-code unlock derivation
|
|
11
|
+
* (`unlockSeed = HKDF(codeBytes)`). The salt differs from every other unlock
|
|
12
|
+
* method's salt, so a code and a passphrase that stringify alike can never
|
|
13
|
+
* derive the same unlock Space; as with the other unlock KDFs, `version` pins
|
|
14
|
+
* the parameter set and the salt is permanent.
|
|
15
|
+
*/
|
|
16
|
+
export declare const RECOVERY_KDF: UnlockKdf;
|
|
17
|
+
/**
|
|
18
|
+
* Thrown for text that is not a well-formed recovery code (characters outside
|
|
19
|
+
* the base58 alphabet, or the wrong decoded length). Deliberately distinct
|
|
20
|
+
* from "no account found for this code" -- a malformed code was mistyped; a
|
|
21
|
+
* well-formed code that resolves to nothing was never issued or has been
|
|
22
|
+
* revoked.
|
|
23
|
+
*/
|
|
24
|
+
export declare class RecoveryCodeInvalidError extends Error {
|
|
25
|
+
constructor(message?: string);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Generates a fresh recovery code: 16 random bytes, base58-encoded.
|
|
29
|
+
*
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateRecoveryCode(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Renders a recovery code in dash-separated groups of four for display
|
|
35
|
+
* ("6yCL-Ho5s-..."). Purely cosmetic; `normalizeRecoveryCode` strips the
|
|
36
|
+
* grouping back out on entry.
|
|
37
|
+
*
|
|
38
|
+
* @param options {object}
|
|
39
|
+
* @param options.code {string}
|
|
40
|
+
* @returns {string}
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatRecoveryCode({ code }: {
|
|
43
|
+
code: string;
|
|
44
|
+
}): string;
|
|
45
|
+
/**
|
|
46
|
+
* Normalizes user-entered recovery code text: strips whitespace and the
|
|
47
|
+
* display dashes. Base58 is case-sensitive, so casing is preserved.
|
|
48
|
+
*
|
|
49
|
+
* @param options {object}
|
|
50
|
+
* @param options.input {string}
|
|
51
|
+
* @returns {string}
|
|
52
|
+
*/
|
|
53
|
+
export declare function normalizeRecoveryCode({ input }: {
|
|
54
|
+
input: string;
|
|
55
|
+
}): string;
|
|
56
|
+
/**
|
|
57
|
+
* Decodes a (possibly formatted) recovery code back to its 16 bytes,
|
|
58
|
+
* throwing `RecoveryCodeInvalidError` on anything malformed.
|
|
59
|
+
*
|
|
60
|
+
* @param options {object}
|
|
61
|
+
* @param options.code {string} the user-entered code (grouping tolerated)
|
|
62
|
+
* @returns {Uint8Array}
|
|
63
|
+
*/
|
|
64
|
+
export declare function decodeRecoveryCode({ code }: {
|
|
65
|
+
code: string;
|
|
66
|
+
}): Uint8Array;
|
|
67
|
+
/**
|
|
68
|
+
* The code's full client identity, derived deterministically from
|
|
69
|
+
* its bytes: the 32-byte client seed (behind the code's Ed25519 signing pair
|
|
70
|
+
* and X25519 key-agreement twin), the single did:webvh update-key seed (one
|
|
71
|
+
* key, no staged pair -- a code is spent on use, so it never self-rotates;
|
|
72
|
+
* its recovery continuation commits whatever it needs next), the derived
|
|
73
|
+
* agents, and the public multibases / ids the issuance and recovery flows
|
|
74
|
+
* publish and look up.
|
|
75
|
+
*/
|
|
76
|
+
export interface RecoveryClient {
|
|
77
|
+
codeBytes: Uint8Array;
|
|
78
|
+
clientSeed: Uint8Array;
|
|
79
|
+
updateSeed: Uint8Array;
|
|
80
|
+
agents: ProfileAgents;
|
|
81
|
+
clientDid: string;
|
|
82
|
+
signingKeyMultibase: string;
|
|
83
|
+
keyAgreementKeyMultibase: string;
|
|
84
|
+
updateKeyMultibase: string;
|
|
85
|
+
/**
|
|
86
|
+
* The kid of the code's PUK-roster entry -- its key-agreement key's id
|
|
87
|
+
* exactly as `agentsFromSeed` derives it (`did:key:<ed>#<x>`), so the wrap
|
|
88
|
+
* minted at issuance is the one the recovery flow's roster read looks for.
|
|
89
|
+
*/
|
|
90
|
+
recipientKid: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Derives the code's whole client identity from a (possibly formatted) code.
|
|
94
|
+
* Deterministic: the same code always yields the same key set. Throws
|
|
95
|
+
* `RecoveryCodeInvalidError` on malformed text; whether the derived identity
|
|
96
|
+
* actually unlocks anything is the caller's question.
|
|
97
|
+
*
|
|
98
|
+
* @param options {object}
|
|
99
|
+
* @param options.code {string} the recovery code (grouping tolerated)
|
|
100
|
+
* @returns {Promise<RecoveryClient>}
|
|
101
|
+
*/
|
|
102
|
+
export declare function recoveryClientFromCode({ code }: {
|
|
103
|
+
code: string;
|
|
104
|
+
}): Promise<RecoveryClient>;
|
|
105
|
+
//# sourceMappingURL=recoveryCode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoveryCode.d.ts","sourceRoot":"","sources":["../../src/recovery/recoveryCode.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAGlD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,SAM1B,CAAA;AAWD;;;;;;GAMG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,SAAuC;CAI3D;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAI7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAErE;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAE1E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CAazE;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,UAAU,CAAA;IACrB,UAAU,EAAE,UAAU,CAAA;IACtB,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE,aAAa,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,wBAAwB,EAAE,MAAM,CAAA;IAChC,kBAAkB,EAAE,MAAM,CAAA;IAC1B;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,EAC3C,IAAI,EACL,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,OAAO,CAAC,cAAc,CAAC,CAmC1B"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The recovery-code format layer and its deterministic derivations. A recovery
|
|
6
|
+
* code is 16 random bytes rendered as base58 (Bitcoin alphabet), shown to the
|
|
7
|
+
* user exactly once at issuance. Under the roster identity model the code is a
|
|
8
|
+
* **minimal always-enrolled wallet client**: everything the code needs to
|
|
9
|
+
* act -- the unlock identity that locates its keyring record, the client
|
|
10
|
+
* key set behind its `keyAgreement` verification method and PUK-roster wrap,
|
|
11
|
+
* and the did:webvh update key whose hash stands pre-committed in
|
|
12
|
+
* `nextKeyHashes` -- derives deterministically from the code's bytes, so the
|
|
13
|
+
* key material exists nowhere until the code is typed.
|
|
14
|
+
*
|
|
15
|
+
* The derivations are wire-level: two wallet apps must produce byte-identical
|
|
16
|
+
* output for the same code, or a code issued in one could not recover in the
|
|
17
|
+
* other. Every salt below is therefore permanent -- changing one orphans every
|
|
18
|
+
* issued code.
|
|
19
|
+
*/
|
|
20
|
+
import { base58 } from '@scure/base';
|
|
21
|
+
import { hkdf } from '@noble/hashes/hkdf.js';
|
|
22
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
23
|
+
import { agentsFromSeed } from '../identity/agents.js';
|
|
24
|
+
import { updateKeyMultibase } from '../webvh/didWebvh.js';
|
|
25
|
+
/**
|
|
26
|
+
* The byte length of a recovery code: 16 random bytes is ~128 bits, enough
|
|
27
|
+
* that the unlock derivation is a single expansion rather than a stretched
|
|
28
|
+
* KDF (there is nothing to stretch -- the code is already uniform).
|
|
29
|
+
*/
|
|
30
|
+
export const RECOVERY_CODE_BYTES = 16;
|
|
31
|
+
/**
|
|
32
|
+
* HKDF parameters for the recovery-code unlock derivation
|
|
33
|
+
* (`unlockSeed = HKDF(codeBytes)`). The salt differs from every other unlock
|
|
34
|
+
* method's salt, so a code and a passphrase that stringify alike can never
|
|
35
|
+
* derive the same unlock Space; as with the other unlock KDFs, `version` pins
|
|
36
|
+
* the parameter set and the salt is permanent.
|
|
37
|
+
*/
|
|
38
|
+
export const RECOVERY_KDF = {
|
|
39
|
+
version: 1,
|
|
40
|
+
algorithm: 'HKDF',
|
|
41
|
+
hash: 'SHA-256',
|
|
42
|
+
salt: 'freewallet/keyring/recovery-code/v1',
|
|
43
|
+
info: 'freewallet/unlock-seed'
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* The HKDF salt for the code's client-side key set (distinct from the unlock
|
|
47
|
+
* salt above, so the unlock identity and the client identity can never
|
|
48
|
+
* collide), and the per-key expansion labels. All permanent.
|
|
49
|
+
*/
|
|
50
|
+
const RECOVERY_CLIENT_SALT = 'freewallet/recovery/client-keys/v1';
|
|
51
|
+
const RECOVERY_CLIENT_SEED_INFO = 'client-seed';
|
|
52
|
+
const RECOVERY_UPDATE_SEED_INFO = 'update-key';
|
|
53
|
+
/**
|
|
54
|
+
* Thrown for text that is not a well-formed recovery code (characters outside
|
|
55
|
+
* the base58 alphabet, or the wrong decoded length). Deliberately distinct
|
|
56
|
+
* from "no account found for this code" -- a malformed code was mistyped; a
|
|
57
|
+
* well-formed code that resolves to nothing was never issued or has been
|
|
58
|
+
* revoked.
|
|
59
|
+
*/
|
|
60
|
+
export class RecoveryCodeInvalidError extends Error {
|
|
61
|
+
constructor(message = 'This is not a valid recovery code.') {
|
|
62
|
+
super(message);
|
|
63
|
+
this.name = 'RecoveryCodeInvalidError';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Generates a fresh recovery code: 16 random bytes, base58-encoded.
|
|
68
|
+
*
|
|
69
|
+
* @returns {string}
|
|
70
|
+
*/
|
|
71
|
+
export function generateRecoveryCode() {
|
|
72
|
+
const bytes = new Uint8Array(RECOVERY_CODE_BYTES);
|
|
73
|
+
crypto.getRandomValues(bytes);
|
|
74
|
+
return base58.encode(bytes);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Renders a recovery code in dash-separated groups of four for display
|
|
78
|
+
* ("6yCL-Ho5s-..."). Purely cosmetic; `normalizeRecoveryCode` strips the
|
|
79
|
+
* grouping back out on entry.
|
|
80
|
+
*
|
|
81
|
+
* @param options {object}
|
|
82
|
+
* @param options.code {string}
|
|
83
|
+
* @returns {string}
|
|
84
|
+
*/
|
|
85
|
+
export function formatRecoveryCode({ code }) {
|
|
86
|
+
return code.replace(/(.{4})(?=.)/g, '$1-');
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Normalizes user-entered recovery code text: strips whitespace and the
|
|
90
|
+
* display dashes. Base58 is case-sensitive, so casing is preserved.
|
|
91
|
+
*
|
|
92
|
+
* @param options {object}
|
|
93
|
+
* @param options.input {string}
|
|
94
|
+
* @returns {string}
|
|
95
|
+
*/
|
|
96
|
+
export function normalizeRecoveryCode({ input }) {
|
|
97
|
+
return input.replace(/[\s-]+/g, '');
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Decodes a (possibly formatted) recovery code back to its 16 bytes,
|
|
101
|
+
* throwing `RecoveryCodeInvalidError` on anything malformed.
|
|
102
|
+
*
|
|
103
|
+
* @param options {object}
|
|
104
|
+
* @param options.code {string} the user-entered code (grouping tolerated)
|
|
105
|
+
* @returns {Uint8Array}
|
|
106
|
+
*/
|
|
107
|
+
export function decodeRecoveryCode({ code }) {
|
|
108
|
+
const normalized = normalizeRecoveryCode({ input: code });
|
|
109
|
+
let bytes;
|
|
110
|
+
try {
|
|
111
|
+
// Throws on characters outside the base58 alphabet.
|
|
112
|
+
bytes = base58.decode(normalized);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
throw new RecoveryCodeInvalidError();
|
|
116
|
+
}
|
|
117
|
+
if (bytes.length !== RECOVERY_CODE_BYTES) {
|
|
118
|
+
throw new RecoveryCodeInvalidError();
|
|
119
|
+
}
|
|
120
|
+
return bytes;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Derives the code's whole client identity from a (possibly formatted) code.
|
|
124
|
+
* Deterministic: the same code always yields the same key set. Throws
|
|
125
|
+
* `RecoveryCodeInvalidError` on malformed text; whether the derived identity
|
|
126
|
+
* actually unlocks anything is the caller's question.
|
|
127
|
+
*
|
|
128
|
+
* @param options {object}
|
|
129
|
+
* @param options.code {string} the recovery code (grouping tolerated)
|
|
130
|
+
* @returns {Promise<RecoveryClient>}
|
|
131
|
+
*/
|
|
132
|
+
export async function recoveryClientFromCode({ code }) {
|
|
133
|
+
const codeBytes = decodeRecoveryCode({ code });
|
|
134
|
+
const salt = new TextEncoder().encode(RECOVERY_CLIENT_SALT);
|
|
135
|
+
const clientSeed = hkdf(sha256, codeBytes, salt, new TextEncoder().encode(RECOVERY_CLIENT_SEED_INFO), 32);
|
|
136
|
+
const updateSeed = hkdf(sha256, codeBytes, salt, new TextEncoder().encode(RECOVERY_UPDATE_SEED_INFO), 32);
|
|
137
|
+
const agents = await agentsFromSeed({ seed: clientSeed });
|
|
138
|
+
const { publicKeyMultibase: keyAgreementKeyMultibase } = agents.keyAgreementKey;
|
|
139
|
+
if (!keyAgreementKeyMultibase) {
|
|
140
|
+
throw new Error('The derived key-agreement key has no public multibase.');
|
|
141
|
+
}
|
|
142
|
+
const [, , signingKeyMultibase] = agents.keyAgent.id.split(':');
|
|
143
|
+
return {
|
|
144
|
+
codeBytes,
|
|
145
|
+
clientSeed,
|
|
146
|
+
updateSeed,
|
|
147
|
+
agents,
|
|
148
|
+
clientDid: agents.keyAgent.id,
|
|
149
|
+
signingKeyMultibase: signingKeyMultibase,
|
|
150
|
+
keyAgreementKeyMultibase,
|
|
151
|
+
updateKeyMultibase: await updateKeyMultibase({ seed: updateSeed }),
|
|
152
|
+
recipientKid: `${agents.keyAgent.id}#${keyAgreementKeyMultibase}`
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=recoveryCode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoveryCode.js","sourceRoot":"","sources":["../../src/recovery/recoveryCode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The recovery keyring record codec: the `{ version, wrapped }` envelope
|
|
6
|
+
* stored as the one resource of a recovery code's unlock Space. Its plaintext
|
|
7
|
+
* is the ordinary keyring record's (controller, email, account pointer) PLUS
|
|
8
|
+
* the pre-minted PUT-on-`did.jsonl` delegation -- the narrow zcap bridge that
|
|
9
|
+
* lets the code-derived client write its self-enrolling log continuation. It
|
|
10
|
+
* carries **no key material of any kind**: never a seed, never a PUK wrap
|
|
11
|
+
* (wraps live doc-and-roster only), so the record stays a pure pointer.
|
|
12
|
+
*
|
|
13
|
+
* The wrap reuses the keyring cipher context verbatim, so a recovery record
|
|
14
|
+
* IS a keyring record to every generic consumer (an ordinary
|
|
15
|
+
* `unwrapKeyringRecord` recovers its pointer and ignores the extra member) --
|
|
16
|
+
* only the recovery flow demands the delegation.
|
|
17
|
+
*/
|
|
18
|
+
import type { IKeyAgreementKey, IKeyResolver, IZcap } from '@interop/data-integrity-core';
|
|
19
|
+
import type { AccountPointer } from '../keyring/record.js';
|
|
20
|
+
/**
|
|
21
|
+
* The unwrapped contents of a recovery keyring record: the ordinary record
|
|
22
|
+
* members plus the required delegation. `pointer` is required -- a recovery
|
|
23
|
+
* record exists only on WAS deployments (there is nothing to recover toward
|
|
24
|
+
* without a Space).
|
|
25
|
+
*/
|
|
26
|
+
export interface RecoveryRecordContents {
|
|
27
|
+
controller: string;
|
|
28
|
+
email?: string;
|
|
29
|
+
pointer: AccountPointer;
|
|
30
|
+
delegation: IZcap;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Wraps the recovery record: controller, email, pointer, and the pre-minted
|
|
34
|
+
* `did.jsonl` PUT delegation, encrypted under the code's unlock KAK via the
|
|
35
|
+
* keyring EDV cipher context.
|
|
36
|
+
*
|
|
37
|
+
* @param options {object}
|
|
38
|
+
* @param options.controller {string} the account did:key
|
|
39
|
+
* @param [options.email] {string} the account email, when known
|
|
40
|
+
* @param options.pointer {AccountPointer} the account pointer
|
|
41
|
+
* @param options.delegation {IZcap} the PUT-on-`did.jsonl` delegation to the
|
|
42
|
+
* code-derived signing DID
|
|
43
|
+
* @param options.keyAgreementKey {IKeyAgreementKey} the code's unlock KAK
|
|
44
|
+
* @param options.keyResolver {IKeyResolver}
|
|
45
|
+
* @returns {Promise<{ version: number, wrapped: unknown }>}
|
|
46
|
+
*/
|
|
47
|
+
export declare function wrapRecoveryRecord({ controller, email, pointer, delegation, keyAgreementKey, keyResolver }: {
|
|
48
|
+
controller: string;
|
|
49
|
+
email?: string;
|
|
50
|
+
pointer: AccountPointer;
|
|
51
|
+
delegation: IZcap;
|
|
52
|
+
keyAgreementKey: IKeyAgreementKey;
|
|
53
|
+
keyResolver: IKeyResolver;
|
|
54
|
+
}): Promise<{
|
|
55
|
+
version: number;
|
|
56
|
+
wrapped: unknown;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Unwraps and validates a recovery record: the ordinary keyring-record checks
|
|
60
|
+
* plus the required pointer and delegation. A record without a delegation is
|
|
61
|
+
* not a recovery record (an ordinary keyring record found under a code's
|
|
62
|
+
* unlock Space would mean a corrupted issuance) and is refused.
|
|
63
|
+
*
|
|
64
|
+
* @param options {object}
|
|
65
|
+
* @param options.record {unknown} the stored `{ version, wrapped }` envelope
|
|
66
|
+
* @param options.keyAgreementKey {IKeyAgreementKey} the code's unlock KAK
|
|
67
|
+
* @param options.keyResolver {IKeyResolver}
|
|
68
|
+
* @returns {Promise<RecoveryRecordContents>}
|
|
69
|
+
*/
|
|
70
|
+
export declare function unwrapRecoveryRecord({ record, keyAgreementKey, keyResolver }: {
|
|
71
|
+
record: unknown;
|
|
72
|
+
keyAgreementKey: IKeyAgreementKey;
|
|
73
|
+
keyResolver: IKeyResolver;
|
|
74
|
+
}): Promise<RecoveryRecordContents>;
|
|
75
|
+
//# sourceMappingURL=recoveryRecord.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoveryRecord.d.ts","sourceRoot":"","sources":["../../src/recovery/recoveryRecord.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,KAAK,EACN,MAAM,8BAA8B,CAAA;AAOrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE1D;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,cAAc,CAAA;IACvB,UAAU,EAAE,KAAK,CAAA;CAClB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,UAAU,EACV,KAAK,EACL,OAAO,EACP,UAAU,EACV,eAAe,EACf,WAAW,EACZ,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,cAAc,CAAA;IACvB,UAAU,EAAE,KAAK,CAAA;IACjB,eAAe,EAAE,gBAAgB,CAAA;IACjC,WAAW,EAAE,YAAY,CAAA;CAC1B,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAqBjD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,EACzC,MAAM,EACN,eAAe,EACf,WAAW,EACZ,EAAE;IACD,MAAM,EAAE,OAAO,CAAA;IACf,eAAe,EAAE,gBAAgB,CAAA;IACjC,WAAW,EAAE,YAAY,CAAA;CAC1B,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA+ClC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createEdvDocCipher } from '@interop/was-client/edv';
|
|
2
|
+
import { KEYRING_COLLECTION } from '../space/collections.js';
|
|
3
|
+
import { KEYRING_RECORD_VERSION, parseRecordPointer } from '../keyring/record.js';
|
|
4
|
+
/**
|
|
5
|
+
* Wraps the recovery record: controller, email, pointer, and the pre-minted
|
|
6
|
+
* `did.jsonl` PUT delegation, encrypted under the code's unlock KAK via the
|
|
7
|
+
* keyring EDV cipher context.
|
|
8
|
+
*
|
|
9
|
+
* @param options {object}
|
|
10
|
+
* @param options.controller {string} the account did:key
|
|
11
|
+
* @param [options.email] {string} the account email, when known
|
|
12
|
+
* @param options.pointer {AccountPointer} the account pointer
|
|
13
|
+
* @param options.delegation {IZcap} the PUT-on-`did.jsonl` delegation to the
|
|
14
|
+
* code-derived signing DID
|
|
15
|
+
* @param options.keyAgreementKey {IKeyAgreementKey} the code's unlock KAK
|
|
16
|
+
* @param options.keyResolver {IKeyResolver}
|
|
17
|
+
* @returns {Promise<{ version: number, wrapped: unknown }>}
|
|
18
|
+
*/
|
|
19
|
+
export async function wrapRecoveryRecord({ controller, email, pointer, delegation, keyAgreementKey, keyResolver }) {
|
|
20
|
+
const cipher = await createEdvDocCipher({
|
|
21
|
+
keyAgreementKey,
|
|
22
|
+
keyResolver,
|
|
23
|
+
collectionId: KEYRING_COLLECTION.id
|
|
24
|
+
});
|
|
25
|
+
const data = {
|
|
26
|
+
controller,
|
|
27
|
+
...(email ? { email } : {}),
|
|
28
|
+
pointer: {
|
|
29
|
+
...(pointer.did ? { did: pointer.did } : {}),
|
|
30
|
+
spaceId: pointer.spaceId,
|
|
31
|
+
host: pointer.host
|
|
32
|
+
},
|
|
33
|
+
delegation,
|
|
34
|
+
createdAt: new Date().toISOString()
|
|
35
|
+
};
|
|
36
|
+
const { envelope } = await cipher.encrypt({
|
|
37
|
+
data: data
|
|
38
|
+
});
|
|
39
|
+
return { version: KEYRING_RECORD_VERSION, wrapped: envelope };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Unwraps and validates a recovery record: the ordinary keyring-record checks
|
|
43
|
+
* plus the required pointer and delegation. A record without a delegation is
|
|
44
|
+
* not a recovery record (an ordinary keyring record found under a code's
|
|
45
|
+
* unlock Space would mean a corrupted issuance) and is refused.
|
|
46
|
+
*
|
|
47
|
+
* @param options {object}
|
|
48
|
+
* @param options.record {unknown} the stored `{ version, wrapped }` envelope
|
|
49
|
+
* @param options.keyAgreementKey {IKeyAgreementKey} the code's unlock KAK
|
|
50
|
+
* @param options.keyResolver {IKeyResolver}
|
|
51
|
+
* @returns {Promise<RecoveryRecordContents>}
|
|
52
|
+
*/
|
|
53
|
+
export async function unwrapRecoveryRecord({ record, keyAgreementKey, keyResolver }) {
|
|
54
|
+
if (record === null || typeof record !== 'object') {
|
|
55
|
+
throw new Error('Malformed recovery record.');
|
|
56
|
+
}
|
|
57
|
+
const { version, wrapped } = record;
|
|
58
|
+
if (version !== KEYRING_RECORD_VERSION) {
|
|
59
|
+
throw new Error(`Unsupported recovery record version "${String(version)}".`);
|
|
60
|
+
}
|
|
61
|
+
const cipher = await createEdvDocCipher({
|
|
62
|
+
keyAgreementKey,
|
|
63
|
+
keyResolver,
|
|
64
|
+
collectionId: KEYRING_COLLECTION.id
|
|
65
|
+
});
|
|
66
|
+
const plaintext = (await cipher.decrypt({
|
|
67
|
+
envelope: wrapped
|
|
68
|
+
}));
|
|
69
|
+
if (typeof plaintext.controller !== 'string' || !plaintext.controller) {
|
|
70
|
+
throw new Error('Recovery record is missing a controller.');
|
|
71
|
+
}
|
|
72
|
+
const pointer = parseRecordPointer(plaintext.pointer);
|
|
73
|
+
if (!pointer) {
|
|
74
|
+
throw new Error('Recovery record is missing its account pointer.');
|
|
75
|
+
}
|
|
76
|
+
if (plaintext.delegation === null ||
|
|
77
|
+
typeof plaintext.delegation !== 'object') {
|
|
78
|
+
throw new Error('Recovery record is missing its did.jsonl delegation.');
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
controller: plaintext.controller,
|
|
82
|
+
...(typeof plaintext.email === 'string' && plaintext.email
|
|
83
|
+
? { email: plaintext.email }
|
|
84
|
+
: {}),
|
|
85
|
+
pointer,
|
|
86
|
+
delegation: plaintext.delegation
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=recoveryRecord.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoveryRecord.js","sourceRoot":"","sources":["../../src/recovery/recoveryRecord.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { ClientWebvhUpdateKeys, WebvhEnrollmentKeys, WebvhIdStore } from '../webvh/didWebvh.js';
|
|
2
|
+
/**
|
|
3
|
+
* The verification-method id a code's key-agreement key publishes under --
|
|
4
|
+
* the ordinary `<did>#<multibase>` form, indistinguishable by id from any
|
|
5
|
+
* other keyAgreement entry. Consumers that must exclude recovery entries do
|
|
6
|
+
* it structurally (an enrolled client is a `capabilityInvocation` entry; a
|
|
7
|
+
* recovery key never has one) or by the registry's recorded multibase.
|
|
8
|
+
*
|
|
9
|
+
* @param options {object}
|
|
10
|
+
* @param options.did {string} the account's did:webvh
|
|
11
|
+
* @param options.keyAgreementKeyMultibase {string}
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
14
|
+
export declare function recoveryVmId({ did, keyAgreementKeyMultibase }: {
|
|
15
|
+
did: string;
|
|
16
|
+
keyAgreementKeyMultibase: string;
|
|
17
|
+
}): string;
|
|
18
|
+
/**
|
|
19
|
+
* The public halves of a recovery code as the document and log carry them:
|
|
20
|
+
* the X25519 key-agreement key published as the recovery VM, and the update
|
|
21
|
+
* key whose hash stands in `nextKeyHashes`.
|
|
22
|
+
*/
|
|
23
|
+
export interface RecoveryPublicKeys {
|
|
24
|
+
keyAgreementKeyMultibase: string;
|
|
25
|
+
updateKeyMultibase: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Thrown by the recovery continuation when the log carries neither the code's
|
|
29
|
+
* update key nor its committed hash -- the code was revoked (or never
|
|
30
|
+
* issued), so no continuation can verify.
|
|
31
|
+
*/
|
|
32
|
+
export declare class RecoveryKeyNotCommittedError extends Error {
|
|
33
|
+
constructor(message?: string);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The narrow store seam the recovery continuation writes through: a public
|
|
37
|
+
* read of the log and the delegated `did.jsonl` PUT. A subset of
|
|
38
|
+
* {@link WebvhIdStore}, so an app's remote-store class satisfies it too.
|
|
39
|
+
*/
|
|
40
|
+
export type RecoveryLogStore = Pick<WebvhIdStore, 'getIdResourceRaw' | 'putIdResource'>;
|
|
41
|
+
/**
|
|
42
|
+
* ISSUANCE (run by an enrolled client, root authority): publishes a recovery
|
|
43
|
+
* code's split posture into the document -- one entry adding the code's
|
|
44
|
+
* `keyAgreement` verification method (an ordinary, unmarked Multikey entry)
|
|
45
|
+
* and committing its update-key hash in `nextKeyHashes`. The code's update
|
|
46
|
+
* key joins `updateKeys` nowhere. Idempotent: a posture already published is
|
|
47
|
+
* a no-op, so re-running a torn issuance converges.
|
|
48
|
+
*
|
|
49
|
+
* @param options {object}
|
|
50
|
+
* @param options.idStore {WebvhIdStore}
|
|
51
|
+
* @param options.updateKeys {ClientWebvhUpdateKeys} the ISSUING client's
|
|
52
|
+
* own did:webvh update-key seeds
|
|
53
|
+
* @param options.recovery {RecoveryPublicKeys} the code's public halves
|
|
54
|
+
* @returns {Promise<{ did: string }>}
|
|
55
|
+
*/
|
|
56
|
+
export declare function publishRecoveryKey({ idStore, updateKeys, recovery }: {
|
|
57
|
+
idStore: WebvhIdStore;
|
|
58
|
+
updateKeys: ClientWebvhUpdateKeys;
|
|
59
|
+
recovery: RecoveryPublicKeys;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
did: string;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* REVOCATION (run by an enrolled client, root authority): removes a recovery
|
|
65
|
+
* code's posture from the document -- its `keyAgreement` verification method
|
|
66
|
+
* and its committed update-key hash -- in one entry. Idempotent. The
|
|
67
|
+
* roster-side half (rotating the PUK epoch off the code's wrap) is the
|
|
68
|
+
* caller's, and runs after this so the resolver's document no longer backs
|
|
69
|
+
* the removed entry.
|
|
70
|
+
*
|
|
71
|
+
* @param options {object}
|
|
72
|
+
* @param options.idStore {WebvhIdStore}
|
|
73
|
+
* @param options.updateKeys {ClientWebvhUpdateKeys} the REVOKING client's
|
|
74
|
+
* own did:webvh update-key seeds
|
|
75
|
+
* @param options.recovery {RecoveryPublicKeys} the code's public halves
|
|
76
|
+
* @returns {Promise<{ did: string }>}
|
|
77
|
+
*/
|
|
78
|
+
export declare function removeRecoveryKey({ idStore, updateKeys, recovery }: {
|
|
79
|
+
idStore: WebvhIdStore;
|
|
80
|
+
updateKeys: ClientWebvhUpdateKeys;
|
|
81
|
+
recovery: RecoveryPublicKeys;
|
|
82
|
+
}): Promise<{
|
|
83
|
+
did: string;
|
|
84
|
+
}>;
|
|
85
|
+
/**
|
|
86
|
+
* RECOVERY (run by the code-derived client through the delegated `did.jsonl`
|
|
87
|
+
* PUT): writes the self-enrolling continuation described in the module doc --
|
|
88
|
+
* the reveal-and-commit entry signed by the code's pre-committed update key,
|
|
89
|
+
* then the add-and-retire entry signed by the new ordinary client's update
|
|
90
|
+
* key. Resumable from durable state alone: a completed continuation is
|
|
91
|
+
* detected by the new client's update key already being authorized (no-op),
|
|
92
|
+
* a torn one by the standing commitments (the commit step re-runs
|
|
93
|
+
* convergently -- the spent code's hash is deliberately carried through the
|
|
94
|
+
* commit entry, so a resumed commit can re-state the revealed key).
|
|
95
|
+
*
|
|
96
|
+
* @param options {object}
|
|
97
|
+
* @param options.store {RecoveryLogStore} public log read + delegated PUT
|
|
98
|
+
* @param options.recovery {object} the spent code's update seed and public
|
|
99
|
+
* halves
|
|
100
|
+
* @param options.recovery.updateSeed {Uint8Array}
|
|
101
|
+
* @param options.recovery.keyAgreementKeyMultibase {string}
|
|
102
|
+
* @param options.recovery.updateKeyMultibase {string}
|
|
103
|
+
* @param options.newClientKeys {WebvhEnrollmentKeys} the new ordinary
|
|
104
|
+
* client's public halves
|
|
105
|
+
* @param options.newClientUpdateSeeds {ClientWebvhUpdateKeys} the new
|
|
106
|
+
* client's update-key seeds (minted by the recovery flow, which therefore
|
|
107
|
+
* holds them and can sign the add entry)
|
|
108
|
+
* @param options.replacement {RecoveryPublicKeys} the replacement code's
|
|
109
|
+
* public halves, committed and published in the same continuation
|
|
110
|
+
* @returns {Promise<{ did: string, webDoc?: object }>} the account DID and,
|
|
111
|
+
* when the add entry ran here, the final `did.json` projection for the
|
|
112
|
+
* recovered session to republish
|
|
113
|
+
*/
|
|
114
|
+
export declare function recoverWebvhClient({ store, recovery, newClientKeys, newClientUpdateSeeds, replacement }: {
|
|
115
|
+
store: RecoveryLogStore;
|
|
116
|
+
recovery: RecoveryPublicKeys & {
|
|
117
|
+
updateSeed: Uint8Array;
|
|
118
|
+
};
|
|
119
|
+
newClientKeys: WebvhEnrollmentKeys;
|
|
120
|
+
newClientUpdateSeeds: ClientWebvhUpdateKeys;
|
|
121
|
+
replacement: RecoveryPublicKeys;
|
|
122
|
+
}): Promise<{
|
|
123
|
+
did: string;
|
|
124
|
+
webDoc?: object;
|
|
125
|
+
}>;
|
|
126
|
+
//# sourceMappingURL=recoveryWebvh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recoveryWebvh.d.ts","sourceRoot":"","sources":["../../src/recovery/recoveryWebvh.ts"],"names":[],"mappings":"AAkDA,OAAO,KAAK,EACV,qBAAqB,EAErB,mBAAmB,EACnB,YAAY,EACb,MAAM,sBAAsB,CAAA;AAE7B;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EAC3B,GAAG,EACH,wBAAwB,EACzB,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;IACX,wBAAwB,EAAE,MAAM,CAAA;CACjC,GAAG,MAAM,CAET;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,wBAAwB,EAAE,MAAM,CAAA;IAChC,kBAAkB,EAAE,MAAM,CAAA;CAC3B;AAED;;;;GAIG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;gBAEnD,OAAO,SACuC;CAKjD;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,YAAY,EACZ,kBAAkB,GAAG,eAAe,CACrC,CAAA;AA0ED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,OAAO,EACP,UAAU,EACV,QAAQ,EACT,EAAE;IACD,OAAO,EAAE,YAAY,CAAA;IACrB,UAAU,EAAE,qBAAqB,CAAA;IACjC,QAAQ,EAAE,kBAAkB,CAAA;CAC7B,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAyD3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,OAAO,EACP,UAAU,EACV,QAAQ,EACT,EAAE;IACD,OAAO,EAAE,YAAY,CAAA;IACrB,UAAU,EAAE,qBAAqB,CAAA;IACjC,QAAQ,EAAE,kBAAkB,CAAA;CAC7B,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAkD3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,KAAK,EACL,QAAQ,EACR,aAAa,EACb,oBAAoB,EACpB,WAAW,EACZ,EAAE;IACD,KAAK,EAAE,gBAAgB,CAAA;IACvB,QAAQ,EAAE,kBAAkB,GAAG;QAAE,UAAU,EAAE,UAAU,CAAA;KAAE,CAAA;IACzD,aAAa,EAAE,mBAAmB,CAAA;IAClC,oBAAoB,EAAE,qBAAqB,CAAA;IAC3C,WAAW,EAAE,kBAAkB,CAAA;CAChC,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAsI5C"}
|