@plane31/blind-relay 0.1.3 → 0.3.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/adapters/index.d.ts +4 -3
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +2 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/audience.d.ts +1 -1
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +7 -6
- package/dist/audience.js.map +1 -1
- package/dist/client.d.ts +159 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1112 -102
- package/dist/client.js.map +1 -1
- package/dist/codec.d.ts +25 -1
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +44 -0
- package/dist/codec.js.map +1 -1
- package/dist/crypto/noble.d.ts.map +1 -1
- package/dist/crypto/noble.js +19 -1
- package/dist/crypto/noble.js.map +1 -1
- package/dist/crypto.d.ts +1 -1
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js.map +1 -1
- package/dist/errors.d.ts +9 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -1
- package/dist/errors.js.map +1 -1
- package/dist/identity.d.ts +8 -2
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +7 -3
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/policy.d.ts +13 -0
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +12 -1
- package/dist/policy.js.map +1 -1
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +2 -0
- package/dist/rows.js.map +1 -1
- package/dist/store.d.ts +116 -3
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +2 -0
- package/dist/store.js.map +1 -1
- package/dist/succession.d.ts +108 -0
- package/dist/succession.d.ts.map +1 -0
- package/dist/succession.js +205 -0
- package/dist/succession.js.map +1 -0
- package/dist/testing/clock.d.ts.map +1 -1
- package/dist/testing/clock.js +1 -0
- package/dist/testing/clock.js.map +1 -1
- package/dist/testing/fakeHost.d.ts +60 -1
- package/dist/testing/fakeHost.d.ts.map +1 -1
- package/dist/testing/fakeHost.js +201 -31
- package/dist/testing/fakeHost.js.map +1 -1
- package/dist/testing/faults.d.ts +7 -3
- package/dist/testing/faults.d.ts.map +1 -1
- package/dist/testing/faults.js +27 -3
- package/dist/testing/faults.js.map +1 -1
- package/dist/transactions.d.ts +6 -0
- package/dist/transactions.d.ts.map +1 -1
- package/dist/transactions.js +11 -5
- package/dist/transactions.js.map +1 -1
- package/dist/transport.d.ts +66 -2
- package/dist/transport.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/adapters/index.ts +14 -0
- package/src/audience.ts +7 -6
- package/src/client.ts +1165 -108
- package/src/codec.ts +64 -1
- package/src/crypto/noble.ts +18 -1
- package/src/crypto.ts +1 -0
- package/src/errors.ts +13 -1
- package/src/identity.ts +13 -3
- package/src/index.ts +10 -3
- package/src/policy.ts +23 -1
- package/src/rows.ts +2 -0
- package/src/store.ts +113 -3
- package/src/succession.ts +270 -0
- package/src/testing/clock.ts +1 -0
- package/src/testing/fakeHost.ts +204 -28
- package/src/testing/faults.ts +32 -7
- package/src/transactions.ts +13 -6
- package/src/transport.ts +69 -2
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account succession (protocol section 4, revision 9; amendment A1): the host's authority binds
|
|
3
|
+
* an account to new keys with continuity of its relationships. This module is the verifier a
|
|
4
|
+
* peer runs on a type 9 document and the chain it keeps per account, in the order the
|
|
5
|
+
* specification gives: an accepted transition stays trusted; a received document is
|
|
6
|
+
* authenticated under the current key list; its transition is compared with the recorded ones;
|
|
7
|
+
* only a new transition meets the pin, generation, retirement and certificate checks.
|
|
8
|
+
*/
|
|
9
|
+
import { equalBytes, toHex } from "./bytes.js";
|
|
10
|
+
import { DocumentType, expectType, parseDocument, verifyDocument } from "./codec.js";
|
|
11
|
+
import { identityId } from "./crypto.js";
|
|
12
|
+
import { KavachError } from "./errors.js";
|
|
13
|
+
import { pinFromCertificate } from "./identity.js";
|
|
14
|
+
import { acceptsSuccession } from "./policy.js";
|
|
15
|
+
import { big, pinToRow, rowToPin, unbig } from "./rows.js";
|
|
16
|
+
import { t3ApplyChange } from "./transactions.js";
|
|
17
|
+
export function transitionOf(doc) {
|
|
18
|
+
return {
|
|
19
|
+
accountName: doc.accountName,
|
|
20
|
+
accountId: toHex(doc.accountId),
|
|
21
|
+
successionId: toHex(doc.successionId),
|
|
22
|
+
previousIdentityId: toHex(doc.previousIdentityId),
|
|
23
|
+
newIdentityId: toHex(doc.newIdentityId),
|
|
24
|
+
previousGeneration: doc.previousGeneration,
|
|
25
|
+
newGeneration: doc.newGeneration,
|
|
26
|
+
newCertificateHash: toHex(doc.newCertificateHash)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function sameTransition(a, b) {
|
|
30
|
+
return (a.accountName === b.accountName &&
|
|
31
|
+
a.accountId === b.accountId &&
|
|
32
|
+
a.successionId === b.successionId &&
|
|
33
|
+
a.previousIdentityId === b.previousIdentityId &&
|
|
34
|
+
a.newIdentityId === b.newIdentityId &&
|
|
35
|
+
a.previousGeneration === b.previousGeneration &&
|
|
36
|
+
a.newGeneration === b.newGeneration &&
|
|
37
|
+
a.newCertificateHash === b.newCertificateHash);
|
|
38
|
+
}
|
|
39
|
+
function rowTransition(r) {
|
|
40
|
+
return { accountName: r.accountName, accountId: r.accountId, successionId: r.successionId, previousIdentityId: r.previousIdentityId, newIdentityId: r.newIdentityId, previousGeneration: unbig(r.previousGeneration), newGeneration: unbig(r.newGeneration), newCertificateHash: r.newCertificateHash };
|
|
41
|
+
}
|
|
42
|
+
export function successionKey(accountId, previousGeneration) {
|
|
43
|
+
return `${accountId}:${previousGeneration.toString().padStart(20, "0")}`;
|
|
44
|
+
}
|
|
45
|
+
/** The state of an account nobody has pinned yet: its root, with what the reset trust already retired. */
|
|
46
|
+
export function rootState(accountId, accountName, trust) {
|
|
47
|
+
return { accountId: toHex(accountId), accountName, identityId: toHex(accountId), generation: 0n, retired: new Set(trust.state.retired), deviceIds: new Set() };
|
|
48
|
+
}
|
|
49
|
+
/** The state at a pin: its current identity and generation, the identities this store retired, and its device ids. */
|
|
50
|
+
export function pinnedState(tx, pin, trust) {
|
|
51
|
+
const accountId = toHex(pin.accountId);
|
|
52
|
+
const retired = new Set(trust.state.retired);
|
|
53
|
+
for (const [k, r] of tx.list("identities"))
|
|
54
|
+
if (r.accountId === accountId && r.retired)
|
|
55
|
+
retired.add(k);
|
|
56
|
+
return { accountId, accountName: pin.accountName, identityId: toHex(pin.identityId), generation: pin.generation, retired, deviceIds: new Set(pin.deviceIds.map(toHex)) };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The transition rules (section 4, order four), applied to one parsed succession and the
|
|
60
|
+
* certificate served with it against a state. Throws the protocol code; returns the next state.
|
|
61
|
+
* Authentication (order two) and the comparison with recorded transitions (orders one and three)
|
|
62
|
+
* are the caller's, since only a store knows what it recorded.
|
|
63
|
+
*/
|
|
64
|
+
export function validateTransition(doc, certificate, state) {
|
|
65
|
+
const stage = "succession";
|
|
66
|
+
const t = transitionOf(doc);
|
|
67
|
+
if (t.accountName !== state.accountName || t.accountId !== state.accountId)
|
|
68
|
+
throw new KavachError("SUCCESSION_BINDING", stage, "account name or id does not match");
|
|
69
|
+
if (t.previousIdentityId !== state.identityId)
|
|
70
|
+
throw new KavachError("SUCCESSION_BINDING", stage, "previous identity is not the account's current identity");
|
|
71
|
+
if (t.previousGeneration < state.generation)
|
|
72
|
+
throw new KavachError("ROLLBACK", stage, "previous generation below the current one");
|
|
73
|
+
if (state.retired.has(t.previousIdentityId) || state.retired.has(t.newIdentityId))
|
|
74
|
+
throw new KavachError("SUPERSEDED_IDENTITY", stage, "a retired identity cannot be previous or new");
|
|
75
|
+
const cert = expectType(verifyDocument(certificate), DocumentType.AccountDevice, stage);
|
|
76
|
+
if (toHex(cert.bodyHash) !== t.newCertificateHash || cert.accountName !== t.accountName || cert.generation !== t.newGeneration || toHex(identityId(cert.accountName, cert.accountKey)) !== t.newIdentityId) {
|
|
77
|
+
throw new KavachError("SUCCESSION_BINDING", stage, "the certificate does not bind to the succession");
|
|
78
|
+
}
|
|
79
|
+
if (state.deviceIds.has(toHex(cert.deviceId)))
|
|
80
|
+
throw new KavachError("DEVICE_ID_REUSED", stage);
|
|
81
|
+
const retired = new Set(state.retired);
|
|
82
|
+
retired.add(t.previousIdentityId);
|
|
83
|
+
const deviceIds = new Set(state.deviceIds);
|
|
84
|
+
deviceIds.add(toHex(cert.deviceId));
|
|
85
|
+
return { next: { ...state, identityId: t.newIdentityId, generation: t.newGeneration, retired, deviceIds }, cert };
|
|
86
|
+
}
|
|
87
|
+
/** Authenticate an attestation under the current list (order two). Returns the verified document. */
|
|
88
|
+
export function authenticateSuccession(wire, trust, now) {
|
|
89
|
+
const stage = "succession";
|
|
90
|
+
const parsed = expectType(parseDocument(wire), DocumentType.AccountSuccession, stage);
|
|
91
|
+
if (now === undefined || now < trust.state.timeHighWater)
|
|
92
|
+
throw new KavachError("RESET_CLOCK_UNTRUSTED", stage);
|
|
93
|
+
const list = trust.state.current;
|
|
94
|
+
if (!list || !trust.fresh(now))
|
|
95
|
+
throw new KavachError("RESET_KEYS_REQUIRED", stage, "no fresh key list");
|
|
96
|
+
const signer = list.list.keys.find((k) => equalBytes(k.keyId, parsed.authorityKeyId));
|
|
97
|
+
if (!signer)
|
|
98
|
+
throw new KavachError("RESET_KEY_REVOKED", stage, "the signing key is not in the current list");
|
|
99
|
+
return expectType(verifyDocument(wire, signer.publicKey), DocumentType.AccountSuccession, stage);
|
|
100
|
+
}
|
|
101
|
+
/** The account id an identity belongs to, as the chain knows it; an identity with no row is its own account (a root never succeeded, or one pinned before revision 9). */
|
|
102
|
+
export function accountIdOf(tx, identityHex) {
|
|
103
|
+
return tx.get("identities", identityHex)?.accountId ?? identityHex;
|
|
104
|
+
}
|
|
105
|
+
/** Every identity retired by a succession or a reset, as hex. */
|
|
106
|
+
export function retiredIdentities(tx) {
|
|
107
|
+
return new Set(tx.list("identities").filter(([, r]) => r.retired).map(([k]) => k));
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Verify links in order from a state, with the same rules a pinned contact applies: each
|
|
111
|
+
* attested under the current list, each transition valid against the state the previous one
|
|
112
|
+
* produced. Nothing is written; the caller records the links once the chain is complete.
|
|
113
|
+
*/
|
|
114
|
+
export function verifyChain(links, input) {
|
|
115
|
+
const out = [];
|
|
116
|
+
let state = input.state;
|
|
117
|
+
for (const link of links) {
|
|
118
|
+
const doc = authenticateSuccession(link.wire, input.trust, input.now);
|
|
119
|
+
state = validateTransition(doc, link.certificate, state).next;
|
|
120
|
+
out.push({ doc, wire: link.wire, certificate: link.certificate });
|
|
121
|
+
}
|
|
122
|
+
return { links: out, state };
|
|
123
|
+
}
|
|
124
|
+
/** Keep a verified chain as evidence: succession rows, identity rows (retired ones with the keys the chain shows) and key-change rows. */
|
|
125
|
+
export function recordChainIn(tx, chain, now) {
|
|
126
|
+
for (const { doc, wire, certificate } of chain) {
|
|
127
|
+
const t = transitionOf(doc);
|
|
128
|
+
const cert = expectType(parseDocument(certificate), DocumentType.AccountDevice, "chain");
|
|
129
|
+
const row = { accountId: t.accountId, accountName: t.accountName, successionId: t.successionId, previousIdentityId: t.previousIdentityId, newIdentityId: t.newIdentityId, previousGeneration: big(t.previousGeneration), newGeneration: big(t.newGeneration), newCertificateHash: t.newCertificateHash, authorityKeyId: toHex(doc.authorityKeyId), wire: toHex(wire), acceptedAt: big(now) };
|
|
130
|
+
tx.put("successions", successionKey(t.accountId, t.previousGeneration), row);
|
|
131
|
+
const prev = tx.get("identities", t.previousIdentityId);
|
|
132
|
+
tx.put("identities", t.previousIdentityId, { accountId: t.accountId, accountName: t.accountName, ...(prev?.accountKey ? { accountKey: prev.accountKey } : {}), sinceGeneration: prev?.sinceGeneration ?? big(1n), retired: true });
|
|
133
|
+
const next = tx.get("identities", t.newIdentityId);
|
|
134
|
+
tx.put("identities", t.newIdentityId, { accountId: t.accountId, accountName: t.accountName, accountKey: toHex(cert.accountKey), sinceGeneration: big(t.newGeneration), retired: next?.retired ?? false });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/** The root identity's row with its key, from a certificate under the root key the host served, when it is one. */
|
|
138
|
+
export function rootIdentityIn(tx, accountId, accountName, rootCertificate) {
|
|
139
|
+
if (!rootCertificate)
|
|
140
|
+
return;
|
|
141
|
+
let cert;
|
|
142
|
+
try {
|
|
143
|
+
cert = expectType(verifyDocument(rootCertificate), DocumentType.AccountDevice, "chain");
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (cert.accountName !== accountName || !equalBytes(identityId(cert.accountName, cert.accountKey), accountId))
|
|
149
|
+
return;
|
|
150
|
+
const key = toHex(accountId);
|
|
151
|
+
const row = tx.get("identities", key);
|
|
152
|
+
// Whether the root is retired is the chain's to say (recordChainIn runs first); a root with no
|
|
153
|
+
// succession recorded yet is current.
|
|
154
|
+
tx.put("identities", key, { accountId: key, accountName, accountKey: toHex(cert.accountKey), sinceGeneration: row?.sinceGeneration ?? big(1n), retired: row?.retired ?? false, ...(row?.resetAt !== undefined ? { resetAt: row.resetAt } : {}) });
|
|
155
|
+
}
|
|
156
|
+
export function applySuccession(tx, input) {
|
|
157
|
+
const stage = "succession";
|
|
158
|
+
if (!acceptsSuccession(input.policy))
|
|
159
|
+
throw new KavachError("UNSUPPORTED_TYPE", stage, "this deployment does not accept successions");
|
|
160
|
+
const parsed = expectType(parseDocument(input.wire), DocumentType.AccountSuccession, stage);
|
|
161
|
+
const t = transitionOf(parsed);
|
|
162
|
+
// Order 1: authenticate the attestation under the current list. A failure here records nothing
|
|
163
|
+
// and changes nothing, so an obsolete attestation of an accepted transition is merely dropped.
|
|
164
|
+
const now = input.now;
|
|
165
|
+
authenticateSuccession(input.wire, input.trust, now);
|
|
166
|
+
if (now === undefined)
|
|
167
|
+
throw new KavachError("RESET_CLOCK_UNTRUSTED", stage);
|
|
168
|
+
// Order 2: compare the transition with the recorded ones for this account.
|
|
169
|
+
const recorded = tx.list("successions", t.accountId + ":").map(([, r]) => r);
|
|
170
|
+
const atState = recorded.find((r) => unbig(r.previousGeneration) === t.previousGeneration && r.previousIdentityId === t.previousIdentityId);
|
|
171
|
+
const byId = recorded.find((r) => r.successionId === t.successionId);
|
|
172
|
+
const pinRow = tx.get("pins", t.accountId);
|
|
173
|
+
if (atState) {
|
|
174
|
+
if (sameTransition(rowTransition(atState), t)) {
|
|
175
|
+
if (!pinRow)
|
|
176
|
+
throw new KavachError("STORAGE_FAILURE", stage, "a recorded succession without its pin");
|
|
177
|
+
return { outcome: "DUPLICATE", accountId: parsed.accountId, accountName: t.accountName, previousIdentityId: parsed.previousIdentityId, newIdentityId: parsed.newIdentityId, generation: t.newGeneration, transition: t, pin: rowToPin(pinRow) };
|
|
178
|
+
}
|
|
179
|
+
throw new KavachError("EQUIVOCATION", stage, "two successors for one account state");
|
|
180
|
+
}
|
|
181
|
+
if (byId && !sameTransition(rowTransition(byId), t))
|
|
182
|
+
throw new KavachError("EQUIVOCATION", stage, "a known succession id with a different transition");
|
|
183
|
+
// Order 3: a new transition against the pinned state, with the one validator every path uses.
|
|
184
|
+
if (!pinRow)
|
|
185
|
+
throw new KavachError("SUCCESSION_BINDING", stage, "no pin for the account");
|
|
186
|
+
const pin = rowToPin(pinRow);
|
|
187
|
+
const { cert } = validateTransition(parsed, input.newCertificate, pinnedState(tx, pin, input.trust));
|
|
188
|
+
// Accept, all in this transaction: the pin, the certificates, the identities, the transition,
|
|
189
|
+
// the durable notice, and the rotation (T3) that moves the audience to the new key.
|
|
190
|
+
const next = pinFromCertificate(cert, pin);
|
|
191
|
+
tx.put("pins", t.accountId, pinToRow(next));
|
|
192
|
+
const previousCert = tx.get("certificates", toHex(pin.certificateHash));
|
|
193
|
+
if (previousCert)
|
|
194
|
+
tx.put("certificates", toHex(pin.certificateHash), { ...previousCert, current: false });
|
|
195
|
+
tx.put("certificates", t.newCertificateHash, { identityId: t.accountId, certificateHash: t.newCertificateHash, signingKey: toHex(next.signingKey), boxKey: toHex(next.boxKey), streamId: toHex(next.streamId), generation: big(next.generation), wire: toHex(input.newCertificate), current: true });
|
|
196
|
+
const previousIdentity = tx.get("identities", t.previousIdentityId);
|
|
197
|
+
tx.put("identities", t.previousIdentityId, { accountId: t.accountId, accountName: t.accountName, accountKey: previousIdentity?.accountKey ?? toHex(pin.accountKey), sinceGeneration: previousIdentity?.sinceGeneration ?? big(1n), retired: true });
|
|
198
|
+
tx.put("identities", t.newIdentityId, { accountId: t.accountId, accountName: t.accountName, accountKey: toHex(cert.accountKey), sinceGeneration: big(t.newGeneration), retired: false });
|
|
199
|
+
tx.put("successions", successionKey(t.accountId, t.previousGeneration), { accountId: t.accountId, accountName: t.accountName, successionId: t.successionId, previousIdentityId: t.previousIdentityId, newIdentityId: t.newIdentityId, previousGeneration: big(t.previousGeneration), newGeneration: big(t.newGeneration), newCertificateHash: t.newCertificateHash, authorityKeyId: toHex(parsed.authorityKeyId), wire: toHex(input.wire), acceptedAt: big(now) });
|
|
200
|
+
const notice = { accountId: t.accountId, accountName: t.accountName, previousIdentityId: t.previousIdentityId, newIdentityId: t.newIdentityId, generation: big(t.newGeneration), reason: "succession", successionId: t.successionId, acceptedAt: big(now) };
|
|
201
|
+
tx.put("keyChanges", `${now.toString().padStart(20, "0")}:${t.accountId}:${t.successionId}`, notice);
|
|
202
|
+
t3ApplyChange(tx, { kind: "deviceChanged", identityId: parsed.accountId, certificateHash: cert.bodyHash });
|
|
203
|
+
return { outcome: "ACCEPTED", accountId: parsed.accountId, accountName: t.accountName, previousIdentityId: parsed.previousIdentityId, newIdentityId: parsed.newIdentityId, generation: t.newGeneration, transition: t, pin: next };
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=succession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"succession.js","sourceRoot":"","sources":["../src/succession.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../src/testing/clock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../src/testing/clock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,eAaxB,CAAC;AAEF,4BAA4B;AAC5B,qBAAa,SAAS;IACpB,CAAC,SAAsB;IACvB,GAAG,QAAO,MAAM,CAAW;IAC3B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;CAG1B"}
|
package/dist/testing/clock.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clock.js","sourceRoot":"","sources":["../../src/testing/clock.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAoB;IACzC,OAAO,EAAE,CAAC;IACV,gBAAgB,EAAE,SAAW;IAC7B,mBAAmB,EAAE,UAAY;IACjC,iBAAiB,EAAE,WAAc;IACjC,gBAAgB,EAAE,IAAI;IACtB,cAAc,EAAE,CAAC,IAAI,EAAE;IACvB,KAAK,EAAE;QACL,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,SAAW,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE;QACpG,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,WAAc,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE;QACxG,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,SAAW,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE;KACzG;CACF,CAAC;AAEF,4BAA4B;AAC5B,MAAM,OAAO,SAAS;IACpB,CAAC,GAAG,cAAkB,CAAC;IACvB,GAAG,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAU;QAChB,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACf,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"clock.js","sourceRoot":"","sources":["../../src/testing/clock.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAoB;IACzC,OAAO,EAAE,CAAC;IACV,WAAW,EAAE,MAAM;IACnB,gBAAgB,EAAE,SAAW;IAC7B,mBAAmB,EAAE,UAAY;IACjC,iBAAiB,EAAE,WAAc;IACjC,gBAAgB,EAAE,IAAI;IACtB,cAAc,EAAE,CAAC,IAAI,EAAE;IACvB,KAAK,EAAE;QACL,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,SAAW,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE;QACpG,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,WAAc,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE;QACxG,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,SAAW,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE;KACzG;CACF,CAAC;AAEF,4BAA4B;AAC5B,MAAM,OAAO,SAAS;IACpB,CAAC,GAAG,cAAkB,CAAC;IACvB,GAAG,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAU;QAChB,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACf,CAAC;CACF"}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { type RecordKind } from "../codec.js";
|
|
2
2
|
import { type SigningKeypair } from "../crypto.js";
|
|
3
|
-
import type { AppendOutcome, JoinRequest, Transport } from "../transport.js";
|
|
3
|
+
import type { AppendOutcome, JoinRequest, SuccessionLink, Transport } from "../transport.js";
|
|
4
4
|
interface Account {
|
|
5
5
|
accountName: string;
|
|
6
6
|
accountKey: Uint8Array;
|
|
7
|
+
/** The identity of the current key. */
|
|
7
8
|
identityId: string;
|
|
9
|
+
/** The account id: the root of the succession chain; what circles, manifests and streams name. */
|
|
10
|
+
accountId: string;
|
|
11
|
+
/** The chain from the root, oldest first; empty until a succession. */
|
|
12
|
+
successions: SuccessionLink[];
|
|
13
|
+
/** The certificate the first succession replaced: a certificate under the root key. */
|
|
14
|
+
rootCertificate: Uint8Array | undefined;
|
|
8
15
|
certificate: Uint8Array;
|
|
9
16
|
certificateHash: string;
|
|
10
17
|
generation: bigint;
|
|
@@ -85,6 +92,40 @@ export declare class FakeHost {
|
|
|
85
92
|
readonly streams: Map<string, StreamState>;
|
|
86
93
|
readonly notifications: Notification[];
|
|
87
94
|
readonly receipts: Map<string, Uint8Array<ArrayBufferLike>>;
|
|
95
|
+
/** Successions by succession id: the committed document and the certificate hash it bound, for idempotent commits. */
|
|
96
|
+
readonly successionLog: Map<string, {
|
|
97
|
+
accountName: string;
|
|
98
|
+
certificateHash: string;
|
|
99
|
+
wire: Uint8Array;
|
|
100
|
+
}>;
|
|
101
|
+
/** Replacement authorizations the product's fresh authentication issued (`authorizeReplacement`), single use. */
|
|
102
|
+
readonly authorizations: Map<string, {
|
|
103
|
+
accountName: string;
|
|
104
|
+
successionId: string;
|
|
105
|
+
expectedCertificateHash: string;
|
|
106
|
+
certificateHash: string;
|
|
107
|
+
expiresAt: bigint;
|
|
108
|
+
used: boolean;
|
|
109
|
+
}>;
|
|
110
|
+
/** Sharing preferences per (account id, circle id), with the revision that orders them. */
|
|
111
|
+
readonly preferences: Map<string, {
|
|
112
|
+
enabled: boolean;
|
|
113
|
+
revision: bigint;
|
|
114
|
+
}>;
|
|
115
|
+
authorizationTtlMs: bigint;
|
|
116
|
+
successionPageSize: number;
|
|
117
|
+
circlePageSize: number;
|
|
118
|
+
/** Re-attest a link under the current operational key when its original signer is no longer it (section 7). */
|
|
119
|
+
reattest: boolean;
|
|
120
|
+
/** Test switch: the n-th call to listCircles (1-based) fails with a transport error, once. */
|
|
121
|
+
failCircleListAt: number | undefined;
|
|
122
|
+
circleListCalls: number;
|
|
123
|
+
/** Every getSuccessions call, for tests that check where a peer resumes a chain. */
|
|
124
|
+
readonly successionCalls: {
|
|
125
|
+
accountId: string;
|
|
126
|
+
afterGeneration: bigint;
|
|
127
|
+
limit: number;
|
|
128
|
+
}[];
|
|
88
129
|
resetKeyList: Uint8Array | undefined;
|
|
89
130
|
resetSigner: {
|
|
90
131
|
key: SigningKeypair;
|
|
@@ -106,6 +147,24 @@ export declare class FakeHost {
|
|
|
106
147
|
counter: number;
|
|
107
148
|
}[];
|
|
108
149
|
accountByIdentity(iid: string): Account | undefined;
|
|
150
|
+
/** The account an id names today: its account id, its current identity, or an identity it retired. */
|
|
151
|
+
accountByAnyId(id: string): Account | undefined;
|
|
152
|
+
/**
|
|
153
|
+
* The product's fresh authentication, as a test hook: an authorization bound to the proposal
|
|
154
|
+
* (account, succession id, expected certificate, the certificate's hash), single use, expiring.
|
|
155
|
+
*/
|
|
156
|
+
authorizeReplacement(input: {
|
|
157
|
+
accountName: string;
|
|
158
|
+
successionId: Uint8Array;
|
|
159
|
+
expectedCertificateHash: Uint8Array;
|
|
160
|
+
certificate: Uint8Array;
|
|
161
|
+
}): Uint8Array;
|
|
162
|
+
private resolvedOf;
|
|
163
|
+
private successionPage;
|
|
164
|
+
/** A link as served: re-attested under the current operational key when its signer changed and re-attestation is on. */
|
|
165
|
+
private served;
|
|
166
|
+
/** The circle fence: is this certificate the account's current device? A retired device is refused reads too. */
|
|
167
|
+
private isCurrentDevice;
|
|
109
168
|
private stream;
|
|
110
169
|
/** The expiry alarm: delete the expired prefix and advance the watermark. */
|
|
111
170
|
expire(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fakeHost.d.ts","sourceRoot":"","sources":["../../src/testing/fakeHost.ts"],"names":[],"mappings":"AAOA,OAAO,
|
|
1
|
+
{"version":3,"file":"fakeHost.d.ts","sourceRoot":"","sources":["../../src/testing/fakeHost.ts"],"names":[],"mappings":"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"}
|