keri-ts 2.2.4 → 2.2.5
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/esm/keri/npm/src/_dnt.polyfills.js +14 -14
- package/esm/keri/npm/src/acdc/registering.js +19 -0
- package/esm/keri/npm/src/acdc/salting.js +4 -0
- package/esm/keri/npm/src/app/bootstrap/authenticating.js +32 -10
- package/esm/keri/npm/src/app/bootstrap/oobiery.js +363 -30
- package/esm/keri/npm/src/app/credentials/credential-importing.js +33 -4
- package/esm/keri/npm/src/app/credentials/root-replicator.js +27 -15
- package/esm/keri/npm/src/app/credentials/schema-resolving.js +5 -1
- package/esm/keri/npm/src/app/credentials/tel-publishing.js +16 -7
- package/esm/keri/npm/src/app/delivery/forwarding.js +177 -43
- package/esm/keri/npm/src/app/delivery/relaying.js +232 -0
- package/esm/keri/npm/src/app/delivery/respondant.js +8 -5
- package/esm/keri/npm/src/app/exchanges/exchange-messaging.js +1 -1
- package/esm/keri/npm/src/app/exchanges/exchanging.js +65 -9
- package/esm/keri/npm/src/app/identity/delegating.js +66 -9
- package/esm/keri/npm/src/app/identity/habbing.js +190 -71
- package/esm/keri/npm/src/app/identity/keeping.js +111 -39
- package/esm/keri/npm/src/app/identity/retire-identifier.js +98 -0
- package/esm/keri/npm/src/app/ipex/disclosure-replaying.js +116 -0
- package/esm/keri/npm/src/app/ipex/group-ipex.js +122 -25
- package/esm/keri/npm/src/app/ipex/group-issuance.js +109 -23
- package/esm/keri/npm/src/app/ipex/ipex-discloser.js +36 -22
- package/esm/keri/npm/src/app/ipex/ipex-grouping.js +53 -3
- package/esm/keri/npm/src/app/ipex/ipex-v2.js +7 -2
- package/esm/keri/npm/src/app/ipex/issuance.js +131 -35
- package/esm/keri/npm/src/app/ipex/pending-presentations.js +4 -2
- package/esm/keri/npm/src/app/ipex/presenting.js +3 -18
- package/esm/keri/npm/src/app/ipex/receive-issuance.js +2 -1
- package/esm/keri/npm/src/app/ipex/unblinding-workflow.js +16 -3
- package/esm/keri/npm/src/app/mailbox/agent-inbox.js +292 -0
- package/esm/keri/npm/src/app/mailbox/forward-handler.js +298 -52
- package/esm/keri/npm/src/app/mailbox/kel-publisher.js +26 -31
- package/esm/keri/npm/src/app/mailbox/mailbox-poller.js +70 -62
- package/esm/keri/npm/src/app/mailbox/mailboxing.js +20 -4
- package/esm/keri/npm/src/app/multisig/counseling.js +71 -27
- package/esm/keri/npm/src/app/multisig/group-members.js +41 -5
- package/esm/keri/npm/src/app/multisig/grouping.js +50 -2
- package/esm/keri/npm/src/app/multisig/multisig-workflows.js +3 -18
- package/esm/keri/npm/src/app/multisig/proposing.js +1 -16
- package/esm/keri/npm/src/app/multisig/rejoin-group.js +99 -0
- package/esm/keri/npm/src/app/multisig/replace-member.js +29 -8
- package/esm/keri/npm/src/app/protocol/parsering.js +45 -17
- package/esm/keri/npm/src/app/protocol/protocol-processing.js +47 -21
- package/esm/keri/npm/src/app/queries/query-replies.js +0 -22
- package/esm/keri/npm/src/app/queries/relay-refresh.js +81 -0
- package/esm/keri/npm/src/app/queries/witness-inquisitor.js +180 -34
- package/esm/keri/npm/src/app/runtime/agent-runtime.js +41 -72
- package/esm/keri/npm/src/app/runtime/cue-runtime.js +45 -5
- package/esm/keri/npm/src/app/runtime/operation-owners.js +26 -56
- package/esm/keri/npm/src/app/runtime/workflow-contract.js +7 -4
- package/esm/keri/npm/src/app/transport/http-client.js +20 -2
- package/esm/keri/npm/src/app/transport/message-source.js +2 -1
- package/esm/keri/npm/src/app/transport/messengering.js +39 -8
- package/esm/keri/npm/src/app/witness/ingress.js +7 -0
- package/esm/keri/npm/src/app/witness/receipt-client.js +43 -16
- package/esm/keri/npm/src/app/witness/receipting.js +62 -20
- package/esm/keri/npm/src/cli/messaging/multisig.js +4 -3
- package/esm/keri/npm/src/core/errors.js +73 -0
- package/esm/keri/npm/src/core/kel/delegation-ancestry.js +11 -2
- package/esm/keri/npm/src/core/kel/eventing.js +25 -28
- package/esm/keri/npm/src/core/kel/kever.js +15 -9
- package/esm/keri/npm/src/core/mailbox/kram-policy.js +8 -0
- package/esm/keri/npm/src/core/mailbox/kram-pruning.js +25 -6
- package/esm/keri/npm/src/core/mailbox/kram-time.js +34 -6
- package/esm/keri/npm/src/core/mailbox/kraming.js +58 -2
- package/esm/keri/npm/src/core/routing.js +18 -25
- package/esm/keri/npm/src/core/scheming.js +12 -5
- package/esm/keri/npm/src/core/wire-fields.js +126 -0
- package/esm/keri/npm/src/db/basing.js +4 -13
- package/esm/keri/npm/src/db/core/indexeddb-persistence.js +3 -2
- package/esm/keri/npm/src/db/core/webdber.js +85 -27
- package/esm/keri/npm/src/db/mailbox/mailboxing.js +13 -0
- package/esm/keri/npm/src/db/subing.js +4 -0
- package/esm/keri/npm/src/runtime/index.js +11 -5
- package/esm/keri/npm/src/time/mod.js +5 -0
- package/esm/keri/npm/src/vdr/credential-tsn-record.js +2 -7
- package/esm/keri/npm/src/vdr/eventing.js +28 -19
- package/esm/keri/npm/src/vdr/registry-tsn-record.js +3 -13
- package/esm/keri/npm/src/version.js +2 -2
- package/package.json +1 -1
- package/types/_dnt.polyfills.d.ts +9 -9
- package/types/_dnt.polyfills.d.ts.map +1 -1
- package/types/acdc/registering.d.ts +6 -0
- package/types/acdc/registering.d.ts.map +1 -1
- package/types/acdc/salting.d.ts.map +1 -1
- package/types/app/bootstrap/authenticating.d.ts +12 -2
- package/types/app/bootstrap/authenticating.d.ts.map +1 -1
- package/types/app/bootstrap/oobiery.d.ts +144 -7
- package/types/app/bootstrap/oobiery.d.ts.map +1 -1
- package/types/app/credentials/credential-importing.d.ts +8 -0
- package/types/app/credentials/credential-importing.d.ts.map +1 -1
- package/types/app/credentials/root-replicator.d.ts +19 -8
- package/types/app/credentials/root-replicator.d.ts.map +1 -1
- package/types/app/credentials/schema-resolving.d.ts.map +1 -1
- package/types/app/credentials/tel-publishing.d.ts +4 -2
- package/types/app/credentials/tel-publishing.d.ts.map +1 -1
- package/types/app/delivery/forwarding.d.ts +69 -5
- package/types/app/delivery/forwarding.d.ts.map +1 -1
- package/types/app/delivery/relaying.d.ts +144 -0
- package/types/app/delivery/relaying.d.ts.map +1 -0
- package/types/app/delivery/respondant.d.ts +9 -2
- package/types/app/delivery/respondant.d.ts.map +1 -1
- package/types/app/exchanges/exchanging.d.ts +36 -0
- package/types/app/exchanges/exchanging.d.ts.map +1 -1
- package/types/app/identity/delegating.d.ts +6 -0
- package/types/app/identity/delegating.d.ts.map +1 -1
- package/types/app/identity/habbing.d.ts +106 -19
- package/types/app/identity/habbing.d.ts.map +1 -1
- package/types/app/identity/keeping.d.ts +54 -19
- package/types/app/identity/keeping.d.ts.map +1 -1
- package/types/app/identity/retire-identifier.d.ts +24 -0
- package/types/app/identity/retire-identifier.d.ts.map +1 -0
- package/types/app/ipex/disclosure-replaying.d.ts +61 -0
- package/types/app/ipex/disclosure-replaying.d.ts.map +1 -0
- package/types/app/ipex/group-ipex.d.ts +60 -14
- package/types/app/ipex/group-ipex.d.ts.map +1 -1
- package/types/app/ipex/group-issuance.d.ts +48 -6
- package/types/app/ipex/group-issuance.d.ts.map +1 -1
- package/types/app/ipex/ipex-discloser.d.ts +14 -2
- package/types/app/ipex/ipex-discloser.d.ts.map +1 -1
- package/types/app/ipex/ipex-grouping.d.ts +23 -2
- package/types/app/ipex/ipex-grouping.d.ts.map +1 -1
- package/types/app/ipex/ipex-v2.d.ts +5 -2
- package/types/app/ipex/ipex-v2.d.ts.map +1 -1
- package/types/app/ipex/issuance.d.ts +35 -11
- package/types/app/ipex/issuance.d.ts.map +1 -1
- package/types/app/ipex/pending-presentations.d.ts +4 -2
- package/types/app/ipex/pending-presentations.d.ts.map +1 -1
- package/types/app/ipex/presenting.d.ts.map +1 -1
- package/types/app/ipex/receive-issuance.d.ts +2 -1
- package/types/app/ipex/receive-issuance.d.ts.map +1 -1
- package/types/app/ipex/unblinding-workflow.d.ts +4 -1
- package/types/app/ipex/unblinding-workflow.d.ts.map +1 -1
- package/types/app/mailbox/agent-inbox.d.ts +126 -0
- package/types/app/mailbox/agent-inbox.d.ts.map +1 -0
- package/types/app/mailbox/forward-handler.d.ts +114 -14
- package/types/app/mailbox/forward-handler.d.ts.map +1 -1
- package/types/app/mailbox/kel-publisher.d.ts +12 -22
- package/types/app/mailbox/kel-publisher.d.ts.map +1 -1
- package/types/app/mailbox/mailbox-poller.d.ts +40 -24
- package/types/app/mailbox/mailbox-poller.d.ts.map +1 -1
- package/types/app/mailbox/mailboxing.d.ts +19 -5
- package/types/app/mailbox/mailboxing.d.ts.map +1 -1
- package/types/app/multisig/counseling.d.ts +32 -11
- package/types/app/multisig/counseling.d.ts.map +1 -1
- package/types/app/multisig/group-members.d.ts +17 -1
- package/types/app/multisig/group-members.d.ts.map +1 -1
- package/types/app/multisig/grouping.d.ts +17 -1
- package/types/app/multisig/grouping.d.ts.map +1 -1
- package/types/app/multisig/multisig-workflows.d.ts +0 -8
- package/types/app/multisig/multisig-workflows.d.ts.map +1 -1
- package/types/app/multisig/proposing.d.ts +4 -19
- package/types/app/multisig/proposing.d.ts.map +1 -1
- package/types/app/multisig/rejoin-group.d.ts +119 -0
- package/types/app/multisig/rejoin-group.d.ts.map +1 -0
- package/types/app/multisig/replace-member.d.ts +15 -1
- package/types/app/multisig/replace-member.d.ts.map +1 -1
- package/types/app/protocol/parsering.d.ts +21 -2
- package/types/app/protocol/parsering.d.ts.map +1 -1
- package/types/app/protocol/protocol-processing.d.ts +25 -5
- package/types/app/protocol/protocol-processing.d.ts.map +1 -1
- package/types/app/queries/query-replies.d.ts +4 -8
- package/types/app/queries/query-replies.d.ts.map +1 -1
- package/types/app/queries/relay-refresh.d.ts +26 -0
- package/types/app/queries/relay-refresh.d.ts.map +1 -0
- package/types/app/queries/witness-inquisitor.d.ts +56 -5
- package/types/app/queries/witness-inquisitor.d.ts.map +1 -1
- package/types/app/runtime/agent-runtime.d.ts +34 -3
- package/types/app/runtime/agent-runtime.d.ts.map +1 -1
- package/types/app/runtime/cue-runtime.d.ts +15 -3
- package/types/app/runtime/cue-runtime.d.ts.map +1 -1
- package/types/app/runtime/operation-owners.d.ts +16 -26
- package/types/app/runtime/operation-owners.d.ts.map +1 -1
- package/types/app/runtime/workflow-contract.d.ts +21 -6
- package/types/app/runtime/workflow-contract.d.ts.map +1 -1
- package/types/app/transport/http-client.d.ts +9 -0
- package/types/app/transport/http-client.d.ts.map +1 -1
- package/types/app/transport/message-source.d.ts +6 -3
- package/types/app/transport/message-source.d.ts.map +1 -1
- package/types/app/transport/messengering.d.ts +10 -1
- package/types/app/transport/messengering.d.ts.map +1 -1
- package/types/app/witness/ingress.d.ts +1 -0
- package/types/app/witness/ingress.d.ts.map +1 -1
- package/types/app/witness/receipt-client.d.ts +19 -1
- package/types/app/witness/receipt-client.d.ts.map +1 -1
- package/types/app/witness/receipting.d.ts +24 -1
- package/types/app/witness/receipting.d.ts.map +1 -1
- package/types/cli/messaging/multisig.d.ts.map +1 -1
- package/types/core/cues.d.ts +53 -1
- package/types/core/cues.d.ts.map +1 -1
- package/types/core/errors.d.ts +32 -0
- package/types/core/errors.d.ts.map +1 -1
- package/types/core/kel/delegation-ancestry.d.ts.map +1 -1
- package/types/core/kel/eventing.d.ts.map +1 -1
- package/types/core/kel/kever-decisions.d.ts +3 -1
- package/types/core/kel/kever-decisions.d.ts.map +1 -1
- package/types/core/kel/kever.d.ts +7 -1
- package/types/core/kel/kever.d.ts.map +1 -1
- package/types/core/mailbox/kram-policy.d.ts +6 -0
- package/types/core/mailbox/kram-policy.d.ts.map +1 -1
- package/types/core/mailbox/kram-pruning.d.ts +5 -1
- package/types/core/mailbox/kram-pruning.d.ts.map +1 -1
- package/types/core/mailbox/kram-time.d.ts +26 -2
- package/types/core/mailbox/kram-time.d.ts.map +1 -1
- package/types/core/mailbox/kraming.d.ts +14 -1
- package/types/core/mailbox/kraming.d.ts.map +1 -1
- package/types/core/routing.d.ts +3 -7
- package/types/core/routing.d.ts.map +1 -1
- package/types/core/scheming.d.ts.map +1 -1
- package/types/core/wire-fields.d.ts +56 -0
- package/types/core/wire-fields.d.ts.map +1 -0
- package/types/db/basing.d.ts.map +1 -1
- package/types/db/core/indexeddb-persistence.d.ts +3 -2
- package/types/db/core/indexeddb-persistence.d.ts.map +1 -1
- package/types/db/core/webdber.d.ts +32 -6
- package/types/db/core/webdber.d.ts.map +1 -1
- package/types/db/exchange/exchange-records.d.ts +4 -0
- package/types/db/exchange/exchange-records.d.ts.map +1 -1
- package/types/db/mailbox/mailboxing.d.ts +10 -1
- package/types/db/mailbox/mailboxing.d.ts.map +1 -1
- package/types/db/subing.d.ts +2 -0
- package/types/db/subing.d.ts.map +1 -1
- package/types/runtime/index.d.ts +20 -14
- package/types/runtime/index.d.ts.map +1 -1
- package/types/time/mod.d.ts +2 -0
- package/types/time/mod.d.ts.map +1 -1
- package/types/vdr/credential-tsn-record.d.ts.map +1 -1
- package/types/vdr/eventing.d.ts.map +1 -1
- package/types/vdr/registry-tsn-record.d.ts.map +1 -1
- package/types/version.d.ts +2 -2
- package/esm/keri/npm/src/app/runtime/signer-conditions.js +0 -51
- package/types/app/runtime/signer-conditions.d.ts +0 -32
- package/types/app/runtime/signer-conditions.d.ts.map +0 -1
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guarded readers for the field values of remote messages.
|
|
3
|
+
*
|
|
4
|
+
* A remote message can parse and verify its SAID while a field value is still not a valid value for its type: a
|
|
5
|
+
* non-hex or over-wide sequence number, a key that is not a verification key, a next-key digest that is not a digest,
|
|
6
|
+
* a prefix that is not a prefix. The cesr accessors and primitive constructors throw on such values, and a throw out
|
|
7
|
+
* of a processor ends its loop (the mailbox poller, the escrow doer, HTTP ingress). Processor boundaries therefore read
|
|
8
|
+
* remote field values through these readers and turn a null into their own typed refusal (ADR-0005) before any escrow
|
|
9
|
+
* decision or store write: `Kevery.decideEvent` and `processReceipt`, the reply route handlers and `Revery`'s
|
|
10
|
+
* datetime read, `Exchanger` admission and `queryEnvelopeFromDispatch`. Accepted KEL events are remote-authored too:
|
|
11
|
+
* their raw `a` seals are read through `readEventSeal` wherever an anchor is searched.
|
|
12
|
+
*
|
|
13
|
+
* Only the cesr codec's own malformed-input taxonomy (`ParserError` and its subclasses) is read as malformed input, and
|
|
14
|
+
* only while constructing a primitive from a string the message carried. That construction reads no store, so a
|
|
15
|
+
* `ParserError` there cannot be corrupt durable state or I/O; every other error propagates. Numbers are checked as
|
|
16
|
+
* text before any `BigInt` conversion, so cesr's `SyntaxError`/`RangeError` for bad hex is never relied on.
|
|
17
|
+
*/
|
|
18
|
+
import { Dater, Diger, Ilks, NumberPrimitive, ParserError, Prefixer, SealEvent, Verfer, } from "cesr-ts";
|
|
19
|
+
import { encodeDateTimeToDater } from "../time/mod.js";
|
|
20
|
+
/** Construct `Type` from qualified text, or null when the text is not a valid value of that type. */
|
|
21
|
+
function readQualified(Type, value) {
|
|
22
|
+
if (typeof value !== "string" || !value)
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
return new Type({ qb64: value });
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error instanceof ParserError)
|
|
29
|
+
return null;
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Read an identifier prefix (`i`, `di`, `cid`, `eid`, ...), or null when it is not one. */
|
|
34
|
+
export function readPrefixer(value) {
|
|
35
|
+
return readQualified(Prefixer, value);
|
|
36
|
+
}
|
|
37
|
+
/** Read a digest (`d` of a key state notice, a next-key digest), or null when it is not one. */
|
|
38
|
+
export function readDiger(value) {
|
|
39
|
+
return readQualified(Diger, value);
|
|
40
|
+
}
|
|
41
|
+
/** Read a verification key (a current key, a witness), or null when it is not one. */
|
|
42
|
+
export function readVerfer(value) {
|
|
43
|
+
return readQualified(Verfer, value);
|
|
44
|
+
}
|
|
45
|
+
/** Read a datetime (`dt`) as a Dater, or null when it does not encode as one. */
|
|
46
|
+
export function readDater(value) {
|
|
47
|
+
return typeof value === "string" ? readQualified(Dater, encodeDateTimeToDater(value)) : null;
|
|
48
|
+
}
|
|
49
|
+
/** Read a URL, or null when it does not parse. */
|
|
50
|
+
export function readUrl(value) {
|
|
51
|
+
return URL.canParse(value) ? new URL(value) : null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Read a KERI ordinal: lower- or upper-case hex text, or a non-negative integer number or bigint, as cesr's numeric
|
|
55
|
+
* ladder accepts them. Null when it is none of those or exceeds `Number.MAX_SAFE_INTEGER`, the largest value the KEL
|
|
56
|
+
* processors can compare exactly as a number.
|
|
57
|
+
*/
|
|
58
|
+
export function readOrdinal(value) {
|
|
59
|
+
let ordinal;
|
|
60
|
+
if (typeof value === "string") {
|
|
61
|
+
if (!/^[0-9a-f]+$/iu.test(value))
|
|
62
|
+
return null;
|
|
63
|
+
ordinal = BigInt(`0x${value}`);
|
|
64
|
+
}
|
|
65
|
+
else if (typeof value === "number") {
|
|
66
|
+
if (!Number.isSafeInteger(value) || value < 0)
|
|
67
|
+
return null;
|
|
68
|
+
ordinal = BigInt(value);
|
|
69
|
+
}
|
|
70
|
+
else if (typeof value === "bigint") {
|
|
71
|
+
ordinal = value;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return ordinal >= 0n && ordinal <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(ordinal) : null;
|
|
77
|
+
}
|
|
78
|
+
/** Read a message's `s`, which cesr's `sner` reads only as hex text; null when absent or malformed. */
|
|
79
|
+
export function readSequenceNumber(serder) {
|
|
80
|
+
const sn = serder.ked?.s;
|
|
81
|
+
return typeof sn === "string" ? readOrdinal(sn) : null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Name the first field of a KEL event whose value the key-state machine would fail to decode, or null when all decode.
|
|
85
|
+
*
|
|
86
|
+
* Covers what `Kever` and escrow persistence decode beyond `i` and `s` (which `decideEvent` reads first): current keys
|
|
87
|
+
* `k` and next-key digests `n` of establishment events, witnesses `b` and witness changes `br`/`ba`, the witness
|
|
88
|
+
* threshold `bt`, and the delegator `di` of a delegated inception. Thresholds (`kt`, `nt`) already decode to null and are
|
|
89
|
+
* rejected by `Kever`; raw seals in `a` are not decoded here.
|
|
90
|
+
*/
|
|
91
|
+
export function kelEventFieldDefect(serder) {
|
|
92
|
+
const ked = serder.ked ?? {};
|
|
93
|
+
const ilk = serder.ilk;
|
|
94
|
+
const bad = (label, values, read) => {
|
|
95
|
+
const value = values.find((entry) => read(entry) === null);
|
|
96
|
+
return value === undefined ? null : `${label} ${JSON.stringify(value)}`;
|
|
97
|
+
};
|
|
98
|
+
return bad("key", serder.keys, readVerfer)
|
|
99
|
+
?? bad("next key digest", serder.ndigs, readDiger)
|
|
100
|
+
?? bad("witness", serder.backs, readVerfer)
|
|
101
|
+
?? bad("witness cut", serder.cuts, readVerfer)
|
|
102
|
+
?? bad("witness add", serder.adds, readVerfer)
|
|
103
|
+
?? (ked.bt !== undefined && ked.bt !== null && readOrdinal(ked.bt) === null
|
|
104
|
+
? `witness threshold ${JSON.stringify(ked.bt)}`
|
|
105
|
+
: null)
|
|
106
|
+
?? (ilk === Ilks.dip && serder.delpre !== null && !readPrefixer(serder.delpre)
|
|
107
|
+
? `delegator ${JSON.stringify(serder.delpre)}`
|
|
108
|
+
: null);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Read one raw `a` entry as an event seal `{i, s, d}`, or null when it is another seal shape or carries a value that
|
|
112
|
+
* does not decode.
|
|
113
|
+
*
|
|
114
|
+
* An accepted event's seals are not value-checked at acceptance (KERIpy keeps them as raw dicts), so any identifier can
|
|
115
|
+
* anchor junk in its own KEL. Anchor searches (delegation approval, sealing-event lookup) therefore read each entry
|
|
116
|
+
* through this reader and skip a null instead of throwing. KERIpy filters by the same field shape
|
|
117
|
+
* (`tuple(seal) == SealEvent._fields`) and compares raw strings, so a malformed value can never match a real event.
|
|
118
|
+
*/
|
|
119
|
+
export function readEventSeal(value) {
|
|
120
|
+
if (!SealEvent.isSad(value))
|
|
121
|
+
return null;
|
|
122
|
+
const pre = readPrefixer(value.i);
|
|
123
|
+
const sn = readOrdinal(value.s);
|
|
124
|
+
const said = readDiger(value.d);
|
|
125
|
+
return pre && sn !== null && said ? SealEvent.fromTuple([pre, NumberPrimitive.fromNum(BigInt(sn)), said]) : null;
|
|
126
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/** KERI event-log databaser built on `LMDBer` composition. */
|
|
2
|
-
import { b, Cigar, Dater, Diger, Ilks, Labeler, Noncer, NumberPrimitive, NumDex, Prefixer, Saider,
|
|
2
|
+
import { b, Cigar, Dater, Diger, Ilks, Labeler, Noncer, NumberPrimitive, NumDex, Prefixer, Saider, SerderKERI, Siger, t, Texter, Verfer, Verser, Vrsn_1_0, } from "cesr-ts";
|
|
3
3
|
import { action } from "effection";
|
|
4
4
|
import { attachmentCounterPayloadQb64b, attachmentCounterQb64b, attachmentOrdinal, resolveAttachmentGvrsn, } from "../core/attachment-countering.js";
|
|
5
5
|
import { DatabaseOperationError, ValidationError } from "../core/errors.js";
|
|
6
6
|
import { Kever } from "../core/kel/kever.js";
|
|
7
7
|
import { consoleLogger } from "../core/logger.js";
|
|
8
8
|
import { CacheTypeRecord, EndpointRecord, EventSourceRecord, HabitatRecord, KelPublishedRecord, KeyStateRecord, LocationRecord, MsgCacheRecord, ObservedRecord, OobiRecord, RootSentRecord, TopicsRecord, TxnMsgCacheRecord, WellKnownAuthN, } from "../core/records.js";
|
|
9
|
+
import { readEventSeal } from "../core/wire-fields.js";
|
|
9
10
|
import { encodeDateTimeToDater, makeNowIso8601 } from "../time/mod.js";
|
|
10
11
|
import { dgKey, splitOnKey } from "./core/keys.js";
|
|
11
12
|
import { StoreOwner } from "./core/store-owner.js";
|
|
@@ -29,19 +30,9 @@ function isEventSealRecord(value) {
|
|
|
29
30
|
&& value.s instanceof NumberPrimitive
|
|
30
31
|
&& value.d instanceof Diger;
|
|
31
32
|
}
|
|
33
|
+
/** Accept an already-typed event seal, or read a raw `{i, s, d}` entry; null for other shapes or bad values. */
|
|
32
34
|
function normalizeEventSeal(value) {
|
|
33
|
-
|
|
34
|
-
return value;
|
|
35
|
-
}
|
|
36
|
-
if (!SealEvent.isSad(value)) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
try {
|
|
40
|
-
return SealEvent.fromSad(value);
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
35
|
+
return isEventSealRecord(value) ? value : readEventSeal(value);
|
|
45
36
|
}
|
|
46
37
|
function eventSealsEqual(left, right) {
|
|
47
38
|
return left.i.qb64 === right.i.qb64
|
|
@@ -25,8 +25,9 @@
|
|
|
25
25
|
*
|
|
26
26
|
* Another tab's upgrade or delete fires `versionchange` here. The connection
|
|
27
27
|
* closes at once so that tab is never blocked, and this adapter is then lost:
|
|
28
|
-
* its next `load` or `write` rejects,
|
|
29
|
-
*
|
|
28
|
+
* its next `load` or `write` rejects, and so does every retry of it (a write never
|
|
29
|
+
* reconnects), which latches the queue, because writing on after another context
|
|
30
|
+
* deleted the database would break prefix durability.
|
|
30
31
|
* Recovery is a new open, whose `meta` reconnects. Single-writer exclusion is
|
|
31
32
|
* the composition's job, not this adapter's.
|
|
32
33
|
*
|
|
@@ -9,50 +9,84 @@
|
|
|
9
9
|
* Invariant: once the queue is joined with no failure, the mirror and the
|
|
10
10
|
* persisted rows are byte-identical, which is why `reopen` joins before it loads.
|
|
11
11
|
*/
|
|
12
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
13
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
14
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
15
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
16
|
-
};
|
|
17
12
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
18
13
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
19
14
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
20
15
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
21
16
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
22
17
|
};
|
|
23
|
-
var
|
|
18
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
19
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
20
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
21
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
22
|
+
};
|
|
23
|
+
var _PersistenceQueue_instances, _PersistenceQueue_tail, _PersistenceQueue_failure, _PersistenceQueue_retrying, _PersistenceQueue_retryDelays, _PersistenceQueue_append, _PersistenceQueue_attempt, _PersistenceQueue_latched, _PersistenceQueue_settled, _WebDBer_instances, _WebDBer_persistence, _WebDBer_queue, _WebDBer_pendingTables, _WebDBer_connected, _WebDBer_enqueue, _WebDBer_takePendingTables, _WebDBer_carryPendingTables;
|
|
24
24
|
import { bytesEqual, bytesHex } from "cesr-ts";
|
|
25
25
|
import { call, ensure } from "effection";
|
|
26
|
-
import {
|
|
26
|
+
import { PersistenceLatchedError, PersistenceReadError } from "../../core/errors.js";
|
|
27
27
|
import { MemStore } from "./memstore.js";
|
|
28
|
+
/** Delays in milliseconds before each retry of a failed task: four attempts in about half a second. */
|
|
29
|
+
export const PERSISTENCE_RETRY_DELAYS = Object.freeze([25, 100, 400]);
|
|
30
|
+
const pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
28
31
|
/**
|
|
29
32
|
* The persistence order of one composition. Tasks run strictly one at a time,
|
|
30
33
|
* outside any Effection scope, so cancelling a waiter never cancels a write.
|
|
31
34
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
35
|
+
* A failed task is retried in place on a fixed short schedule while it holds
|
|
36
|
+
* the head of the queue, so no later task runs ahead of it. Every task the
|
|
37
|
+
* library enqueues is safe to re-run: an adapter `write` applies one batch
|
|
38
|
+
* atomically and idempotently, `clear` deletes what may already be gone, and
|
|
39
|
+
* `close` releases what may already be released. A task that fails through its
|
|
40
|
+
* retries latches the queue for good: every later task is skipped, because
|
|
41
|
+
* applying a later batch over a lost earlier one would break prefix
|
|
42
|
+
* durability. Recovery is a new composition with a new queue.
|
|
34
43
|
*/
|
|
35
44
|
export class PersistenceQueue {
|
|
36
|
-
|
|
45
|
+
/** @param retryDelays Delays before each retry; its length is the number of retries. */
|
|
46
|
+
constructor(retryDelays = PERSISTENCE_RETRY_DELAYS) {
|
|
37
47
|
_PersistenceQueue_instances.add(this);
|
|
38
48
|
_PersistenceQueue_tail.set(this, Promise.resolve());
|
|
39
49
|
_PersistenceQueue_failure.set(this, null);
|
|
50
|
+
_PersistenceQueue_retrying.set(this, false);
|
|
51
|
+
_PersistenceQueue_retryDelays.set(this, void 0);
|
|
52
|
+
__classPrivateFieldSet(this, _PersistenceQueue_retryDelays, [...retryDelays], "f");
|
|
40
53
|
}
|
|
41
|
-
/** Append a task,
|
|
54
|
+
/** Append a task, retried on failure; skipped once the queue has latched. Run only re-runnable tasks here. */
|
|
42
55
|
enqueue(task) {
|
|
43
56
|
__classPrivateFieldGet(this, _PersistenceQueue_instances, "m", _PersistenceQueue_append).call(this, task, false);
|
|
44
57
|
}
|
|
45
|
-
/** Append connection teardown, which still runs after a
|
|
58
|
+
/** Append connection teardown, which still runs, once, after a latch so a handle is not left open. */
|
|
46
59
|
release(task) {
|
|
47
60
|
__classPrivateFieldGet(this, _PersistenceQueue_instances, "m", _PersistenceQueue_append).call(this, task, true);
|
|
48
61
|
}
|
|
49
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Run `task` after everything enqueued before this call, and resolve with its result. It sees every earlier
|
|
64
|
+
* commit durable, except after a latch, when it runs anyway and sees only the durable prefix; check `status()`.
|
|
65
|
+
* Nothing enqueued after it runs until it settles. A throwing `task` rejects only this caller, with
|
|
66
|
+
* `PersistenceReadError`; it is not retried and never latches the queue.
|
|
67
|
+
*/
|
|
68
|
+
read(task) {
|
|
69
|
+
const result = __classPrivateFieldGet(this, _PersistenceQueue_tail, "f").then(async () => {
|
|
70
|
+
try {
|
|
71
|
+
return await task();
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
throw new PersistenceReadError("Persistence read failed", { cause: error });
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
__classPrivateFieldSet(this, _PersistenceQueue_tail, result.then(() => { }, () => { }), "f");
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
/** The queue's state now; `retrying` lasts only while the head task is between attempts. */
|
|
81
|
+
status() {
|
|
82
|
+
if (__classPrivateFieldGet(this, _PersistenceQueue_failure, "f"))
|
|
83
|
+
return "latched";
|
|
84
|
+
return __classPrivateFieldGet(this, _PersistenceQueue_retrying, "f") ? "retrying" : "healthy";
|
|
85
|
+
}
|
|
86
|
+
/** Refuse new work once latched, with `PersistenceLatchedError` whose cause is the original failure. */
|
|
50
87
|
assertHealthy() {
|
|
51
|
-
if (__classPrivateFieldGet(this, _PersistenceQueue_failure, "f"))
|
|
52
|
-
throw
|
|
53
|
-
cause: __classPrivateFieldGet(this, _PersistenceQueue_failure, "f").error,
|
|
54
|
-
});
|
|
55
|
-
}
|
|
88
|
+
if (__classPrivateFieldGet(this, _PersistenceQueue_failure, "f"))
|
|
89
|
+
throw __classPrivateFieldGet(this, _PersistenceQueue_instances, "m", _PersistenceQueue_latched).call(this, __classPrivateFieldGet(this, _PersistenceQueue_failure, "f").error);
|
|
56
90
|
}
|
|
57
91
|
/** Wait until everything enqueued before this call is durable. Halting cancels only the wait. */
|
|
58
92
|
*flushed() {
|
|
@@ -68,22 +102,46 @@ export class PersistenceQueue {
|
|
|
68
102
|
});
|
|
69
103
|
}
|
|
70
104
|
}
|
|
71
|
-
_PersistenceQueue_tail = new WeakMap(), _PersistenceQueue_failure = new WeakMap(), _PersistenceQueue_instances = new WeakSet(), _PersistenceQueue_append = function _PersistenceQueue_append(task, always) {
|
|
105
|
+
_PersistenceQueue_tail = new WeakMap(), _PersistenceQueue_failure = new WeakMap(), _PersistenceQueue_retrying = new WeakMap(), _PersistenceQueue_retryDelays = new WeakMap(), _PersistenceQueue_instances = new WeakSet(), _PersistenceQueue_append = function _PersistenceQueue_append(task, always) {
|
|
72
106
|
__classPrivateFieldSet(this, _PersistenceQueue_tail, __classPrivateFieldGet(this, _PersistenceQueue_tail, "f").then(async () => {
|
|
73
|
-
if (__classPrivateFieldGet(this, _PersistenceQueue_failure, "f")
|
|
107
|
+
if (!__classPrivateFieldGet(this, _PersistenceQueue_failure, "f"))
|
|
108
|
+
return await __classPrivateFieldGet(this, _PersistenceQueue_instances, "m", _PersistenceQueue_attempt).call(this, task);
|
|
109
|
+
if (!always)
|
|
74
110
|
return;
|
|
75
111
|
try {
|
|
76
112
|
await task();
|
|
77
113
|
}
|
|
78
|
-
catch
|
|
79
|
-
|
|
114
|
+
catch {
|
|
115
|
+
// Already latched; the recorded failure is the one reported.
|
|
80
116
|
}
|
|
81
117
|
}), "f");
|
|
118
|
+
}, _PersistenceQueue_attempt =
|
|
119
|
+
/** Run `task`, retrying it in place on the schedule, and latch with its first failure when every attempt fails. */
|
|
120
|
+
async function _PersistenceQueue_attempt(task) {
|
|
121
|
+
let first = null;
|
|
122
|
+
try {
|
|
123
|
+
for (let attempt = 0;; attempt++) {
|
|
124
|
+
try {
|
|
125
|
+
return await task();
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
first ??= { error };
|
|
129
|
+
if (attempt >= __classPrivateFieldGet(this, _PersistenceQueue_retryDelays, "f").length) {
|
|
130
|
+
__classPrivateFieldSet(this, _PersistenceQueue_failure, first, "f");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
__classPrivateFieldSet(this, _PersistenceQueue_retrying, true, "f");
|
|
135
|
+
await pause(__classPrivateFieldGet(this, _PersistenceQueue_retryDelays, "f")[attempt]);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
__classPrivateFieldSet(this, _PersistenceQueue_retrying, false, "f");
|
|
140
|
+
}
|
|
141
|
+
}, _PersistenceQueue_latched = function _PersistenceQueue_latched(cause) {
|
|
142
|
+
return new PersistenceLatchedError("Persistence failed; this composition accepts no more commits", { cause });
|
|
82
143
|
}, _PersistenceQueue_settled = function _PersistenceQueue_settled() {
|
|
83
|
-
return __classPrivateFieldGet(this, _PersistenceQueue_tail, "f").then(() =>
|
|
84
|
-
if (__classPrivateFieldGet(this, _PersistenceQueue_failure, "f"))
|
|
85
|
-
throw __classPrivateFieldGet(this, _PersistenceQueue_failure, "f").error;
|
|
86
|
-
});
|
|
144
|
+
return __classPrivateFieldGet(this, _PersistenceQueue_tail, "f").then(() => this.assertHealthy());
|
|
87
145
|
};
|
|
88
146
|
function sameValue(a, c) {
|
|
89
147
|
return a === null || c === null ? a === c : bytesEqual(a, c);
|
|
@@ -120,7 +178,7 @@ function netVersion(changes) {
|
|
|
120
178
|
* readable even though it was never persisted, and every later transaction
|
|
121
179
|
* throws before touching the mirror, so the mirror stops changing. The durable
|
|
122
180
|
* state is a prefix of the commit sequence. Recovery is a new composition, with
|
|
123
|
-
* a new queue, loading that prefix;
|
|
181
|
+
* a new queue, loading that prefix; the queue's own retries happen before it latches.
|
|
124
182
|
*/
|
|
125
183
|
export class WebDBer extends MemStore {
|
|
126
184
|
constructor(options, persistence, queue) {
|
|
@@ -15,8 +15,21 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { Diger, MtrDex } from "cesr-ts";
|
|
17
17
|
import { DatabaseNotOpenError } from "../../core/errors.js";
|
|
18
|
+
import { MAX_KEY_BYTES } from "../core/dber.js";
|
|
19
|
+
import { onKey } from "../core/keys.js";
|
|
18
20
|
import { StoreOwner } from "../core/store-owner.js";
|
|
19
21
|
import { CesrOnSuber, Suber } from "../subing.js";
|
|
22
|
+
/**
|
|
23
|
+
* Whether `topic` can index a stored message: its `.tpcs` row key, `<topic>.<32 hex ordinal>`, fits the store's key
|
|
24
|
+
* limit (ADR-0015). A longer topic makes {@link Mailboxer.storeMsg} fail with `DatabaseKeyError`, a store fault, so a
|
|
25
|
+
* caller holding a topic another party chose checks it here before storing.
|
|
26
|
+
*
|
|
27
|
+
* @param topic Complete mailbox topic key, as `mailboxTopicKey` builds it.
|
|
28
|
+
* @returns True when a message can be stored under the topic.
|
|
29
|
+
*/
|
|
30
|
+
export function storableTopic(topic) {
|
|
31
|
+
return onKey(topic, 0).length <= MAX_KEY_BYTES;
|
|
32
|
+
}
|
|
20
33
|
/** Raw-byte value family used for stored mailbox message bodies. */
|
|
21
34
|
class BytesSuber extends Suber {
|
|
22
35
|
_ser(val) {
|
|
@@ -838,6 +838,10 @@ export class CryptSignerSuber extends SignerSuber {
|
|
|
838
838
|
: val;
|
|
839
839
|
return this.db.setVal(this.sdb, this._tokey(keys), signerToStored(stored));
|
|
840
840
|
}
|
|
841
|
+
/** Whether a signer is stored at `keys`; reads the raw row and never decrypts it. */
|
|
842
|
+
has(keys) {
|
|
843
|
+
return this.db.getVal(this.sdb, this._tokey(keys)) !== null;
|
|
844
|
+
}
|
|
841
845
|
/**
|
|
842
846
|
* Read one signer, decrypting the stored ciphertext when a decrypter exists.
|
|
843
847
|
*
|
|
@@ -33,6 +33,7 @@ export { importCredentialStream, } from "../app/credentials/credential-importing
|
|
|
33
33
|
export { deliverCredentialRevocation, revokeCredential, } from "../app/credentials/credential-revoking.js";
|
|
34
34
|
export { createCredential, credentialRegistryRecords, credentialRegistryStatus, exportCredentialStream, inceptCredentialRegistry, listCredentials, pinSchemaBytes, } from "../app/credentials/credential-workflows.js";
|
|
35
35
|
export { Poster, } from "../app/delivery/forwarding.js";
|
|
36
|
+
export { assertRelay, relayAuthorized, relayEndpoint, relayOnboarding, RelayOnlyError, relayOnlyHttpClient, relayRefusal, RelayUnauthorizedError, RelayUnresolvedError, } from "../app/delivery/relaying.js";
|
|
36
37
|
export { EssrRecipient, } from "../app/exchanges/essr.js";
|
|
37
38
|
export { createExchangeMessage, sendExchangeMessage, } from "../app/exchanges/exchange-messaging.js";
|
|
38
39
|
export { Exchanger, RouteRefuser, } from "../app/exchanges/exchanging.js";
|
|
@@ -43,15 +44,17 @@ export { beginDelegation, completeEvent, DELEGATION_WAIT_TIMEOUT_MS, delegationS
|
|
|
43
44
|
export { acceptedEventReplayMessage, Hab, Habery, openHabery, } from "../app/identity/habbing.js";
|
|
44
45
|
export { Algos, Manager, SignerNotHeldError, } from "../app/identity/keeping.js";
|
|
45
46
|
export { Organizer, } from "../app/identity/organizing.js";
|
|
47
|
+
export { exportDisclosureStream, listGroupDisclosures, } from "../app/ipex/disclosure-replaying.js";
|
|
46
48
|
export { IpexAdmitter } from "../app/ipex/ipex-admitting.js";
|
|
47
49
|
export { ipexExnBody, prepareIpexExn } from "../app/ipex/ipex-building.js";
|
|
48
50
|
export { credentialPresentationArtifacts, credentialSaidFromGrant, ipexCredentialAdmit, ipexCredentialGrant, processCredentialPresentationArtifacts, storedGrantArtifacts, } from "../app/ipex/ipex-credentialing.js";
|
|
49
|
-
export { anchorExchange as anchorIpexExchange, exchangeWire, IpexDiscloser, storedExchangeWire, } from "../app/ipex/ipex-discloser.js";
|
|
51
|
+
export { anchorExchange as anchorIpexExchange, attachPresentationProof, exchangeWire, IpexDiscloser, storedExchangeWire, } from "../app/ipex/ipex-discloser.js";
|
|
50
52
|
export { walkIpexGraph } from "../app/ipex/ipex-graph.js";
|
|
51
53
|
export { approveStoredMultisigIpexWrappers, prepareAcdcV2GroupIpex, publishInitialGroupIpex, requireAcdcV2GroupUse, sendCompletedGroupIpex, } from "../app/ipex/ipex-grouping.js";
|
|
52
54
|
export { acceptedRegistryEvidence, authenticateIpexNode, issuedNodeVerdict, } from "../app/ipex/ipex-node-authentication.js";
|
|
53
55
|
export { ipexGrantWalk } from "../app/ipex/ipex-v2.js";
|
|
54
56
|
export { IPEX_GRANT_ROUTE, IPEX_ROUTES, ipexAdmitExn, ipexAgreeExn, ipexApplyExn, ipexGrantExn, ipexOfferExn, ipexSpurnExn, } from "../app/ipex/ipexing.js";
|
|
57
|
+
export { keepRawArrival } from "../app/mailbox/agent-inbox.js";
|
|
55
58
|
export { KEL_PUBLISHER_PACING, KEL_PUBLISHER_SWEEP_TOCKS, KEL_PUBLISHER_TOCK_MS, KelPublisher, kelPublisherDo, } from "../app/mailbox/kel-publisher.js";
|
|
56
59
|
export { addMailbox, completeGroupMailbox, completeMailboxAdmin, mailboxAdminUrl, mailboxStatus, proposeGroupMailbox, removeMailbox, requireMailboxEndpointUrl, waitForMailboxState, } from "../app/mailbox/mailbox-admin.js";
|
|
57
60
|
export { MailboxDirector, } from "../app/mailbox/mailbox-director.js";
|
|
@@ -64,11 +67,11 @@ export { Multiplexor, MULTISIG_ROUTES, multisigExn, multisigExnBody, multisigInc
|
|
|
64
67
|
export { signGroupMessage } from "../app/multisig/multisig-messaging.js";
|
|
65
68
|
export { approveAcdcV2Registry, publishAcdcV2Registry } from "../app/multisig/multisig-workflows.js";
|
|
66
69
|
export { approveGroupProposal, dismissGroupProposal, findGroupProposal, listGroupProposals, } from "../app/multisig/proposals.js";
|
|
67
|
-
export { proposeCredentialIssue, proposeCredentialRegistry, proposeCredentialRevocation, proposeGroupInception, proposeGroupInteraction, proposeGroupRotation, proposeRegistryEvent,
|
|
70
|
+
export { proposeCredentialIssue, proposeCredentialRegistry, proposeCredentialRevocation, proposeGroupInception, proposeGroupInteraction, proposeGroupRotation, proposeRegistryEvent, } from "../app/multisig/proposing.js";
|
|
71
|
+
export { rejoinGroup, } from "../app/multisig/rejoin-group.js";
|
|
68
72
|
export { replaceGroupMember, } from "../app/multisig/replace-member.js";
|
|
69
73
|
export { Notifier, } from "../app/notifications/notifying.js";
|
|
70
74
|
export { Signal, Signaler, } from "../app/notifications/signaling.js";
|
|
71
|
-
export { SignerConditions } from "../app/runtime/signer-conditions.js";
|
|
72
75
|
export { RawRecord } from "../core/records.js";
|
|
73
76
|
export { Verifier, } from "../app/credentials/verifying.js";
|
|
74
77
|
export { witnessKeyStateGet, witnessQueryGet, witnessReceiptGet, witnessReceiptPost, } from "../app/witness/http-endpoints.js";
|
|
@@ -87,12 +90,13 @@ export { deliverRegistryRoots, replicateRootCopies, replicateRootCopy, resealRoo
|
|
|
87
90
|
export { RootReplicator, } from "../app/credentials/root-replicator.js";
|
|
88
91
|
export { publishPendingTel } from "../app/credentials/tel-publishing.js";
|
|
89
92
|
export { Deck } from "../core/deck.js";
|
|
90
|
-
export { AppError, DatabaseError, DatabaseKeyError, DatabaseNotOpenError, DatabaseOperationError, InvalidPathNameError, PathError, PresentationClosedError, ValidationError, } from "../core/errors.js";
|
|
93
|
+
export { AppError, DatabaseError, DatabaseKeyError, DatabaseNotOpenError, DatabaseOperationError, InvalidPathNameError, KramRefusedError, MissingDurableStateError, PathError, PersistenceLatchedError, PersistenceReadError, PresentationClosedError, ValidationError, } from "../core/errors.js";
|
|
91
94
|
export { verifyExchangeProofs } from "../core/exchange/exchange-proofing.js";
|
|
92
95
|
export { exchange } from "../core/exchange/protocol-exchanging.js";
|
|
93
96
|
export { Kevery, } from "../core/kel/eventing.js";
|
|
94
97
|
export { Kever, } from "../core/kel/kever.js";
|
|
95
98
|
export { consoleLogger, getLogLevel, LOG_LEVELS, noopLogger, setLogLevel, } from "../core/logger.js";
|
|
99
|
+
export { isKramLateReason, } from "../core/mailbox/kram-time.js";
|
|
96
100
|
export { DEFAULT_KRAM_CACHES, Kramer } from "../core/mailbox/kraming.js";
|
|
97
101
|
export { CREDENTIAL_MAILBOX_TOPIC, DELEGATE_MAILBOX_TOPIC, normalizeMbxTopicCursor, OOBI_MAILBOX_TOPIC, RECEIPT_MAILBOX_TOPIC, REPLAY_MAILBOX_TOPIC, REPLY_MAILBOX_TOPIC, } from "../core/mailbox/mailbox-topics.js";
|
|
98
102
|
export { incept, interact, query, reply, rotate } from "../core/protocol-eventing.js";
|
|
@@ -145,13 +149,15 @@ export { abandonUnblinding, answerUnblind, requestUnblind, unblindingKey, Unblin
|
|
|
145
149
|
// Fixed-tock doers.
|
|
146
150
|
export { doEvery } from "../app/runtime/doing.js";
|
|
147
151
|
// Operations owners composed by the runtime.
|
|
148
|
-
export { OWNER_PACING, OWNER_SWEEP_TOCKS, OWNER_TOCK_MS,
|
|
152
|
+
export { OWNER_PACING, OWNER_SWEEP_TOCKS, OWNER_TOCK_MS, } from "../app/runtime/operation-owners.js";
|
|
149
153
|
// Library delegator approval (list, approve, status, wait, dismiss).
|
|
150
154
|
export { approveDelegation, DELEGATION_APPROVAL_TIMEOUT_MS, delegationApprovalStatus, dismissDelegation, listPendingDelegations, proposeGroupDelegationApproval, requestDelegatedEvent, settleDelegationApproval, waitForDelegationAnchor, waitForDelegationApproval, waitForPendingDelegation, } from "../app/identity/delegation-approval.js";
|
|
151
155
|
// Library TEL completion status/waits and challenge respond/status/wait.
|
|
152
156
|
export { REGISTRY_WAIT_POLL_MS, registryEventRef, registryEventStatus, settleRegistryEvent, waitForRegistryEvent, } from "../app/credentials/registry-settling.js";
|
|
153
157
|
export { issuedCredentialStatus, telEventStatus, waitForIssuedCredential, waitForTelEvent, } from "../app/credentials/tel-completion.js";
|
|
154
158
|
export { challengeStatus, respondToChallenge, waitForChallengeResponse, } from "../app/identity/challenging.js";
|
|
159
|
+
// Runtime-level retirement: retireHab plus mailbox workers, cursors and KEL publisher rows.
|
|
160
|
+
export { retireIdentifier, retireIdentifierRefusal, } from "../app/identity/retire-identifier.js";
|
|
155
161
|
// Library legacy IPEX conversation (apply, offer, agree, spurn; status and wait).
|
|
156
162
|
export { ipexExchangeStatus, requireIpexPrior, requireIpexSender, sendIpexAgree, sendIpexApply, sendIpexOffer, sendIpexSpurn, waitForIpexExchange, } from "../app/ipex/ipex-conversation.js";
|
|
157
163
|
// Library legacy IPEX grant, admit and credential settle.
|
|
@@ -44,3 +44,8 @@ export function timestampMicros(value) {
|
|
|
44
44
|
const epoch = Date.parse(`${base}${zone}`);
|
|
45
45
|
return Number.isFinite(epoch) ? BigInt(epoch) * 1000n + BigInt(fraction.padEnd(6, "0")) : null;
|
|
46
46
|
}
|
|
47
|
+
/** Format epoch microseconds in the same fixed-width UTC text as `makeNowIso8601`, keeping microsecond precision. */
|
|
48
|
+
export function timestampFromMicros(micros) {
|
|
49
|
+
const whole = makeNowIso8601(new Date(Number(micros / 1000n)));
|
|
50
|
+
return whole.replace(/\.\d{6}/, `.${(micros % 1000000n).toString().padStart(6, "0")}`);
|
|
51
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Diger } from "cesr-ts";
|
|
2
1
|
import { VcStateRecord } from "../core/records.js";
|
|
2
|
+
import { readDiger } from "../core/wire-fields.js";
|
|
3
3
|
import { timestampMicros } from "../time/mod.js";
|
|
4
4
|
import { qualifiedPrefix } from "./registry-tsn-record.js";
|
|
5
5
|
/** Legacy storage ordinals are safe integers even though protocol numbers may be wider. */
|
|
@@ -9,12 +9,7 @@ function ordinal(value) {
|
|
|
9
9
|
}
|
|
10
10
|
/** Require the full qualified digest rather than accepting trailing bytes. */
|
|
11
11
|
function qualifiedDigest(value) {
|
|
12
|
-
|
|
13
|
-
return typeof value === "string" && new Diger({ qb64: value }).qb64 === value;
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
12
|
+
return readDiger(value)?.qb64 === value;
|
|
18
13
|
}
|
|
19
14
|
/** Validate unknown fields and construct an owned record without erasing its guarantees. */
|
|
20
15
|
export function credentialRecord(data) {
|
|
@@ -17,8 +17,9 @@ import { Kever } from "../core/kel/kever.js";
|
|
|
17
17
|
import { consoleLogger } from "../core/logger.js";
|
|
18
18
|
import { projectRegistrySeal, state as registryState, vcstate as credentialState, } from "../core/protocol-vdr-eventing.js";
|
|
19
19
|
import { acceptReplyDecision, unverifiedReplyDecision, } from "../core/routing.js";
|
|
20
|
+
import { readDater, readSequenceNumber } from "../core/wire-fields.js";
|
|
20
21
|
import { dgKey } from "../db/core/keys.js";
|
|
21
|
-
import { encodeDateTimeToDater, makeNowIso8601
|
|
22
|
+
import { encodeDateTimeToDater, makeNowIso8601 } from "../time/mod.js";
|
|
22
23
|
import { backerThreshold, resolveBackerState } from "./backer-state.js";
|
|
23
24
|
import { credentialRecord } from "./credential-tsn-record.js";
|
|
24
25
|
import { qualifiedPrefix, registryRecord } from "./registry-tsn-record.js";
|
|
@@ -43,17 +44,21 @@ function okSaid(serder) {
|
|
|
43
44
|
}
|
|
44
45
|
return serder.said;
|
|
45
46
|
}
|
|
47
|
+
/** The event's `i`, which must be exactly one qualified prefix: TEL escrows key rows by it and split keys on `.`. */
|
|
46
48
|
function okPre(serder) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
const pre = serder.pre;
|
|
50
|
+
if (!qualifiedPrefix(pre)) {
|
|
51
|
+
throw new ValidationError(`TEL event prefix ${JSON.stringify(pre)} is missing or not a qualified prefix.`);
|
|
49
52
|
}
|
|
50
|
-
return
|
|
53
|
+
return pre;
|
|
51
54
|
}
|
|
55
|
+
/** The event's hex `s`, read without cesr's throwing `sn` getter; a missing, non-hex or unsafe value is refused. */
|
|
52
56
|
function okSn(serder) {
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
const sn = readSequenceNumber(serder);
|
|
58
|
+
if (sn === null) {
|
|
59
|
+
throw new ValidationError(`TEL event sequence number ${JSON.stringify(serder.ked?.s)} is missing or malformed.`);
|
|
55
60
|
}
|
|
56
|
-
return
|
|
61
|
+
return sn;
|
|
57
62
|
}
|
|
58
63
|
function okKed(serder) {
|
|
59
64
|
if (!serder.ked) {
|
|
@@ -785,6 +790,10 @@ export class Tevery {
|
|
|
785
790
|
try {
|
|
786
791
|
decision = this.reger.transaction(() => {
|
|
787
792
|
const serder = args.serder;
|
|
793
|
+
// Parsed wire bodies are not SAID-checked by the parser. An unverified body would be stored in escrow, then
|
|
794
|
+
// fail re-parsing on every escrow pass, and could pre-empt the genuine event holding the same anchored `d`.
|
|
795
|
+
if (!serder.verify())
|
|
796
|
+
return reject("TEL event body does not verify against its SAID.", serder);
|
|
788
797
|
const ilk = telIlk(serder);
|
|
789
798
|
const pre = okPre(serder);
|
|
790
799
|
const sn = okSn(serder);
|
|
@@ -951,8 +960,9 @@ export class Tevery {
|
|
|
951
960
|
processReplyRegistryTxnState({ serder, diger, route, aid, cigars = [], tsgs = [] }) {
|
|
952
961
|
const rvy = this.replyVerifier();
|
|
953
962
|
const record = registryRecord(serder.ked?.a);
|
|
954
|
-
|
|
955
|
-
|
|
963
|
+
// A `dt` that parses as a timestamp can still fail to encode as a Dater (no fraction, `Z`); read it once here.
|
|
964
|
+
const dater = readDater(serder.ked?.dt);
|
|
965
|
+
if (!record || !qualifiedPrefix(aid) || !dater
|
|
956
966
|
|| route !== `/tsn/registry/${aid}`
|
|
957
967
|
|| serder.said !== diger.qb64 || !serder.verify()) {
|
|
958
968
|
return unverifiedReplyDecision("Invalid registry transaction-state notice.");
|
|
@@ -991,7 +1001,7 @@ export class Tevery {
|
|
|
991
1001
|
aid,
|
|
992
1002
|
serder,
|
|
993
1003
|
diger,
|
|
994
|
-
dater
|
|
1004
|
+
dater,
|
|
995
1005
|
cigars,
|
|
996
1006
|
tsgs,
|
|
997
1007
|
});
|
|
@@ -1061,7 +1071,6 @@ export class Tevery {
|
|
|
1061
1071
|
if (fields.some((key) => JSON.stringify(record[key]) !== JSON.stringify(stored[key]))) {
|
|
1062
1072
|
return reject("Registry state metadata mismatch.");
|
|
1063
1073
|
}
|
|
1064
|
-
const dater = new Dater({ qb64: encodeDateTimeToDater(stamp) });
|
|
1065
1074
|
const cues = [{ kin: "txnStateSaved", record }];
|
|
1066
1075
|
rvy.writeReply(proof);
|
|
1067
1076
|
this.reger.txnsb.updateReply(aid, serder, diger, dater);
|
|
@@ -1077,8 +1086,8 @@ export class Tevery {
|
|
|
1077
1086
|
processReplyCredentialTxnState({ serder, diger, route, aid, cigars = [], tsgs = [] }) {
|
|
1078
1087
|
const rvy = this.replyVerifier();
|
|
1079
1088
|
const record = credentialRecord(serder.ked?.a);
|
|
1080
|
-
const
|
|
1081
|
-
if (!record || !qualifiedPrefix(aid) ||
|
|
1089
|
+
const dater = readDater(serder.ked?.dt);
|
|
1090
|
+
if (!record || !qualifiedPrefix(aid) || !dater
|
|
1082
1091
|
|| route !== `/tsn/credential/${aid}` || serder.said !== diger.qb64 || !serder.verify())
|
|
1083
1092
|
return unverifiedReplyDecision("Invalid credential transaction-state notice.");
|
|
1084
1093
|
const vci = record.i, regk = record.ri, sn = Number.parseInt(record.s, 16);
|
|
@@ -1118,7 +1127,7 @@ export class Tevery {
|
|
|
1118
1127
|
aid,
|
|
1119
1128
|
serder,
|
|
1120
1129
|
diger,
|
|
1121
|
-
dater
|
|
1130
|
+
dater,
|
|
1122
1131
|
cigars,
|
|
1123
1132
|
tsgs,
|
|
1124
1133
|
});
|
|
@@ -1198,7 +1207,7 @@ export class Tevery {
|
|
|
1198
1207
|
return reject("Credential state does not match current accepted TEL and anchors.");
|
|
1199
1208
|
const cues = [{ kin: "txnStateSaved", record }];
|
|
1200
1209
|
rvy.writeReply(proof);
|
|
1201
|
-
this.reger.txnsb.updateReply(aid, serder, diger,
|
|
1210
|
+
this.reger.txnsb.updateReply(aid, serder, diger, dater);
|
|
1202
1211
|
if (previous?.qb64 !== diger.qb64)
|
|
1203
1212
|
rvy.removeReply(previous);
|
|
1204
1213
|
if (queryCues.length)
|
|
@@ -1335,8 +1344,8 @@ export class Tevery {
|
|
|
1335
1344
|
case Ilks.iss:
|
|
1336
1345
|
case Ilks.rev: {
|
|
1337
1346
|
const regk = stringField(okKed(serder), "ri");
|
|
1338
|
-
if (!regk) {
|
|
1339
|
-
throw new ValidationError("TEL credential event missing ri.");
|
|
1347
|
+
if (!qualifiedPrefix(regk)) {
|
|
1348
|
+
throw new ValidationError("TEL credential event missing or malformed ri.");
|
|
1340
1349
|
}
|
|
1341
1350
|
return regk;
|
|
1342
1351
|
}
|
|
@@ -1344,8 +1353,8 @@ export class Tevery {
|
|
|
1344
1353
|
case Ilks.brv: {
|
|
1345
1354
|
const ra = sealRecord(okKed(serder).ra);
|
|
1346
1355
|
const regk = ra && "i" in ra && typeof ra.i === "string" ? ra.i : null;
|
|
1347
|
-
if (!regk) {
|
|
1348
|
-
throw new ValidationError("Backer TEL event missing ra.i.");
|
|
1356
|
+
if (!qualifiedPrefix(regk)) {
|
|
1357
|
+
throw new ValidationError("Backer TEL event missing or malformed ra.i.");
|
|
1349
1358
|
}
|
|
1350
1359
|
return regk;
|
|
1351
1360
|
}
|