keri-ts 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/esm/cesr/mod.js +1 -0
- package/esm/cesr/src/core/parser-frame-parser.js +3 -0
- package/esm/cesr/src/primitives/matter.js +7 -0
- package/esm/cesr/src/tables/counter.tables.generated.js +1 -5
- package/esm/cesr/src/tables/hard-code-tables.js +39 -0
- package/esm/cesr/src/tables/indexer.tables.generated.js +1 -9
- package/esm/cesr/src/tables/matter.tables.generated.js +1 -14
- package/esm/cesr/src/version.js +7 -4
- package/esm/keri/src/app/agent-runtime.js +11 -5
- package/esm/keri/src/app/authenticating.js +15 -4
- package/esm/keri/src/app/cli/delegate.js +28 -0
- package/esm/keri/src/app/cli/notifications.js +4 -0
- package/esm/keri/src/app/delegating.js +21 -0
- package/esm/keri/src/app/forwarding.js +59 -13
- package/esm/keri/src/app/habbing.js +1 -0
- package/esm/keri/src/app/httping.js +12 -7
- package/esm/keri/src/app/keeping.js +3 -3
- package/esm/keri/src/app/mailbox-sse.js +11 -9
- package/esm/keri/src/app/notifying.js +11 -0
- package/esm/keri/src/app/oobiery.js +15 -4
- package/esm/keri/src/app/query-transport.js +3 -0
- package/esm/keri/src/app/runtime-services.js +22 -0
- package/esm/keri/src/app/version.js +7 -4
- package/esm/keri/src/core/eventing.js +40 -0
- package/esm/keri/src/core/kever.js +9 -0
- package/esm/keri/src/core/protocol-eventing.js +15 -0
- package/esm/keri/src/db/noting.js +4 -0
- package/esm/keri/src/runtime/index.js +1 -0
- package/package.json +2 -2
- package/types/cesr/mod.d.ts +1 -0
- package/types/cesr/mod.d.ts.map +1 -1
- package/types/cesr/src/core/parser-frame-parser.d.ts.map +1 -1
- package/types/cesr/src/primitives/matter.d.ts.map +1 -1
- package/types/cesr/src/tables/counter.tables.generated.d.ts +1 -1
- package/types/cesr/src/tables/counter.tables.generated.d.ts.map +1 -1
- package/types/cesr/src/tables/hard-code-tables.d.ts +15 -0
- package/types/cesr/src/tables/hard-code-tables.d.ts.map +1 -0
- package/types/cesr/src/tables/indexer.tables.generated.d.ts +1 -1
- package/types/cesr/src/tables/indexer.tables.generated.d.ts.map +1 -1
- package/types/cesr/src/tables/matter.tables.generated.d.ts +1 -1
- package/types/cesr/src/tables/matter.tables.generated.d.ts.map +1 -1
- package/types/cesr/src/version.d.ts +7 -4
- package/types/cesr/src/version.d.ts.map +1 -1
- package/types/keri/src/app/agent-runtime.d.ts +5 -1
- package/types/keri/src/app/agent-runtime.d.ts.map +1 -1
- package/types/keri/src/app/authenticating.d.ts +7 -1
- package/types/keri/src/app/authenticating.d.ts.map +1 -1
- package/types/keri/src/app/cli/delegate.d.ts +14 -0
- package/types/keri/src/app/cli/delegate.d.ts.map +1 -1
- package/types/keri/src/app/cli/notifications.d.ts +10 -0
- package/types/keri/src/app/cli/notifications.d.ts.map +1 -1
- package/types/keri/src/app/delegating.d.ts +23 -0
- package/types/keri/src/app/delegating.d.ts.map +1 -1
- package/types/keri/src/app/forwarding.d.ts +39 -9
- package/types/keri/src/app/forwarding.d.ts.map +1 -1
- package/types/keri/src/app/habbing.d.ts.map +1 -1
- package/types/keri/src/app/httping.d.ts +10 -4
- package/types/keri/src/app/httping.d.ts.map +1 -1
- package/types/keri/src/app/keeping.d.ts +2 -2
- package/types/keri/src/app/mailbox-sse.d.ts +8 -4
- package/types/keri/src/app/mailbox-sse.d.ts.map +1 -1
- package/types/keri/src/app/notifying.d.ts +23 -0
- package/types/keri/src/app/notifying.d.ts.map +1 -1
- package/types/keri/src/app/oobiery.d.ts +7 -3
- package/types/keri/src/app/oobiery.d.ts.map +1 -1
- package/types/keri/src/app/query-transport.d.ts.map +1 -1
- package/types/keri/src/app/runtime-services.d.ts +26 -0
- package/types/keri/src/app/runtime-services.d.ts.map +1 -0
- package/types/keri/src/app/version.d.ts +7 -4
- package/types/keri/src/app/version.d.ts.map +1 -1
- package/types/keri/src/core/eventing.d.ts +30 -0
- package/types/keri/src/core/eventing.d.ts.map +1 -1
- package/types/keri/src/core/kever.d.ts.map +1 -1
- package/types/keri/src/core/protocol-eventing.d.ts +8 -0
- package/types/keri/src/core/protocol-eventing.d.ts.map +1 -1
- package/types/keri/src/db/noting.d.ts +2 -0
- package/types/keri/src/db/noting.d.ts.map +1 -1
- package/types/keri/src/runtime/index.d.ts +1 -0
- package/types/keri/src/runtime/index.d.ts.map +1 -1
package/esm/cesr/mod.js
CHANGED
|
@@ -242,6 +242,9 @@ export class FrameParser {
|
|
|
242
242
|
};
|
|
243
243
|
}
|
|
244
244
|
catch (_error) {
|
|
245
|
+
// Non-native body groups wrap one Matter primitive. If Serder hydration
|
|
246
|
+
// fails, expose the primitive body bytes only; callers that inspect the
|
|
247
|
+
// fallback should not see the surrounding group counter envelope.
|
|
245
248
|
const raw = matter.raw;
|
|
246
249
|
return {
|
|
247
250
|
frame: {
|
|
@@ -41,6 +41,13 @@ function matterNameForCode(code) {
|
|
|
41
41
|
}
|
|
42
42
|
return name;
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Select the concrete variable-length Matter code for the raw payload size.
|
|
46
|
+
*
|
|
47
|
+
* Variable families encode lead bytes and soft-size width in the selector
|
|
48
|
+
* itself. Normalizing once during construction keeps generated qb64/qb2 forms
|
|
49
|
+
* deterministic without leaking that sizing policy to primitive callers.
|
|
50
|
+
*/
|
|
44
51
|
function normalizeVariableMatterCode(code, raw) {
|
|
45
52
|
const sizage = MATTER_SIZES.get(code);
|
|
46
53
|
if (!sizage || sizage.fs !== null) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { COUNTER_HARDS } from "./hard-code-tables.js";
|
|
1
2
|
export const COUNTER_SIZES_V1 = new Map([
|
|
2
3
|
["-_AAA", { hs: 5, ss: 3, fs: 8 }],
|
|
3
4
|
["--L", { hs: 3, ss: 5, fs: 8 }],
|
|
@@ -84,11 +85,6 @@ export const COUNTER_SIZES_V2 = new Map([
|
|
|
84
85
|
["-Y", { hs: 2, ss: 2, fs: 4 }],
|
|
85
86
|
["-Z", { hs: 2, ss: 2, fs: 4 }],
|
|
86
87
|
]);
|
|
87
|
-
export const COUNTER_HARDS = new Map([
|
|
88
|
-
..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("").map((c) => [`-${c}`, 2]),
|
|
89
|
-
["--", 3],
|
|
90
|
-
["-_", 5],
|
|
91
|
-
]);
|
|
92
88
|
export const COUNTER_CODE_NAMES_V1 = {
|
|
93
89
|
"-_AAA": "KERIACDCGenusVersion",
|
|
94
90
|
"--L": "BigPathedMaterialCouples",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source-owned hard-code size tables used by generated CESR lookup modules.
|
|
3
|
+
*
|
|
4
|
+
* KERIpy derives these ranges procedurally rather than listing them alongside
|
|
5
|
+
* the generated size/name dictionaries. Keeping them here avoids embedding
|
|
6
|
+
* static table literals inside the generator while preserving the public
|
|
7
|
+
* generated-module exports.
|
|
8
|
+
*/
|
|
9
|
+
/** Hard-code byte counts for Matter derivation code prefixes. */
|
|
10
|
+
export const MATTER_HARDS = new Map([
|
|
11
|
+
..."ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((c) => [c, 1]),
|
|
12
|
+
..."abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, 1]),
|
|
13
|
+
["0", 2],
|
|
14
|
+
["1", 4],
|
|
15
|
+
["2", 4],
|
|
16
|
+
["3", 4],
|
|
17
|
+
["4", 2],
|
|
18
|
+
["5", 2],
|
|
19
|
+
["6", 2],
|
|
20
|
+
["7", 4],
|
|
21
|
+
["8", 4],
|
|
22
|
+
["9", 4],
|
|
23
|
+
]);
|
|
24
|
+
/** Hard-code byte counts for Indexer derivation code prefixes. */
|
|
25
|
+
export const INDEXER_HARDS = new Map([
|
|
26
|
+
..."ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((c) => [c, 1]),
|
|
27
|
+
..."abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, 1]),
|
|
28
|
+
["0", 2],
|
|
29
|
+
["1", 2],
|
|
30
|
+
["2", 2],
|
|
31
|
+
["3", 2],
|
|
32
|
+
["4", 2],
|
|
33
|
+
]);
|
|
34
|
+
/** Hard-code byte counts for Counter code prefixes. */
|
|
35
|
+
export const COUNTER_HARDS = new Map([
|
|
36
|
+
..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("").map((c) => [`-${c}`, 2]),
|
|
37
|
+
["--", 3],
|
|
38
|
+
["-_", 5],
|
|
39
|
+
]);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { INDEXER_HARDS } from "./hard-code-tables.js";
|
|
1
2
|
export const INDEXER_SIZES = new Map([
|
|
2
3
|
["0A", { hs: 2, ss: 2, os: 1, fs: 156, ls: 0 }],
|
|
3
4
|
["0B", { hs: 2, ss: 2, os: 1, fs: 156, ls: 0 }],
|
|
@@ -61,12 +62,3 @@ export const INDEXER_CODES_BY_NAME = {
|
|
|
61
62
|
"TBD1": "1z",
|
|
62
63
|
"TBD4": "4z",
|
|
63
64
|
};
|
|
64
|
-
export const INDEXER_HARDS = new Map([
|
|
65
|
-
..."ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((c) => [c, 1]),
|
|
66
|
-
..."abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, 1]),
|
|
67
|
-
["0", 2],
|
|
68
|
-
["1", 2],
|
|
69
|
-
["2", 2],
|
|
70
|
-
["3", 2],
|
|
71
|
-
["4", 2],
|
|
72
|
-
]);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { MATTER_HARDS } from "./hard-code-tables.js";
|
|
1
2
|
export const MATTER_SIZES = new Map([
|
|
2
3
|
["0A", { hs: 2, ss: 0, xs: 0, fs: 24, ls: 0 }],
|
|
3
4
|
["0B", { hs: 2, ss: 0, xs: 0, fs: 88, ls: 0 }],
|
|
@@ -334,17 +335,3 @@ export const MATTER_CODES_BY_NAME = {
|
|
|
334
335
|
"X448": "L",
|
|
335
336
|
"Yes": "1AAM",
|
|
336
337
|
};
|
|
337
|
-
export const MATTER_HARDS = new Map([
|
|
338
|
-
..."ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("").map((c) => [c, 1]),
|
|
339
|
-
..."abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, 1]),
|
|
340
|
-
["0", 2],
|
|
341
|
-
["1", 4],
|
|
342
|
-
["2", 4],
|
|
343
|
-
["3", 4],
|
|
344
|
-
["4", 2],
|
|
345
|
-
["5", 2],
|
|
346
|
-
["6", 2],
|
|
347
|
-
["7", 4],
|
|
348
|
-
["8", 4],
|
|
349
|
-
["9", 4],
|
|
350
|
-
]);
|
package/esm/cesr/src/version.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Template used by scripts/generate_versions.ts for package version modules.
|
|
3
|
+
*
|
|
4
|
+
* The generator token-replaces the string placeholders below, then formats and
|
|
5
|
+
* compares the rendered output during version checks. Do not edit generated
|
|
6
|
+
* `src/version.ts` files by hand; edit this template instead.
|
|
4
7
|
*/
|
|
5
8
|
/** Package semantic version copied from the owning package manifest. */
|
|
6
|
-
export const PACKAGE_VERSION = "0.
|
|
9
|
+
export const PACKAGE_VERSION = "0.7.0";
|
|
7
10
|
/** Optional build metadata stamp injected by release/CI workflows. */
|
|
8
|
-
export const BUILD_METADATA = "build.
|
|
11
|
+
export const BUILD_METADATA = "build.12.6aeea4790568f27066636c48ec39d2f098e3c26d";
|
|
9
12
|
/** User-facing version string with build metadata appended when present. */
|
|
10
13
|
export const DISPLAY_VERSION = BUILD_METADATA
|
|
11
14
|
? `${PACKAGE_VERSION}+${BUILD_METADATA}`
|
|
@@ -5,7 +5,7 @@ import { Authenticator } from "./authenticating.js";
|
|
|
5
5
|
import { loadChallengeHandlers } from "./challenging.js";
|
|
6
6
|
import { cueDo, processCuesOnce } from "./cue-runtime.js";
|
|
7
7
|
import { Anchorer, loadDelegationHandlers } from "./delegating.js";
|
|
8
|
-
import { ForwardHandler, MailboxPoller, mailboxTopicForRoute, Poster } from "./forwarding.js";
|
|
8
|
+
import { ForwardHandler, MailboxPoller, mailboxTopicForRoute, Poster, } from "./forwarding.js";
|
|
9
9
|
import { MailboxDirector } from "./mailbox-director.js";
|
|
10
10
|
import { openMailboxerForHabery } from "./mailboxing.js";
|
|
11
11
|
import { Notifier, openNoterForHabery } from "./notifying.js";
|
|
@@ -13,6 +13,7 @@ import { isWellKnownOobiUrl, loadOobiHandlers, Oobiery, parseOobiUrl } from "./o
|
|
|
13
13
|
import { QueryCoordinator } from "./querying.js";
|
|
14
14
|
import { Reactor } from "./reactor.js";
|
|
15
15
|
import { Respondant } from "./respondant.js";
|
|
16
|
+
import { resolveRuntimeServices } from "./runtime-services.js";
|
|
16
17
|
import { runtimeTurn } from "./runtime-turn.js";
|
|
17
18
|
import { Signaler } from "./signaling.js";
|
|
18
19
|
/**
|
|
@@ -26,6 +27,7 @@ import { Signaler } from "./signaling.js";
|
|
|
26
27
|
*/
|
|
27
28
|
export function* createAgentRuntime(hby, options = {}) {
|
|
28
29
|
const mode = options.mode ?? "local";
|
|
30
|
+
const services = resolveRuntimeServices(options.services);
|
|
29
31
|
const enableMailboxStore = options.enableMailboxStore ?? mode === "indirect";
|
|
30
32
|
const mailboxer = options.mailboxer
|
|
31
33
|
?? (enableMailboxStore ? (yield* openMailboxerForHabery(hby)) : null);
|
|
@@ -47,7 +49,7 @@ export function* createAgentRuntime(hby, options = {}) {
|
|
|
47
49
|
loadDelegationHandlers(hby, reactor.exchanger, notifier);
|
|
48
50
|
loadOobiHandlers(hby, reactor.exchanger, notifier);
|
|
49
51
|
const mailboxDirector = new MailboxDirector(hby, mailboxer ? { mailboxer } : {});
|
|
50
|
-
const poster = new Poster(hby, { mailboxer });
|
|
52
|
+
const poster = new Poster(hby, { mailboxer, services });
|
|
51
53
|
const respondant = new Respondant(hby, { poster, mailboxDirector });
|
|
52
54
|
if (mailboxer) {
|
|
53
55
|
reactor.exchanger.addHandler(new ForwardHandler(mailboxDirector));
|
|
@@ -61,7 +63,10 @@ export function* createAgentRuntime(hby, options = {}) {
|
|
|
61
63
|
mailboxDirector.registerTopic(topic);
|
|
62
64
|
}
|
|
63
65
|
}
|
|
64
|
-
const mailboxPoller = new MailboxPoller(hby, mailboxDirector
|
|
66
|
+
const mailboxPoller = new MailboxPoller(hby, mailboxDirector, {
|
|
67
|
+
services,
|
|
68
|
+
pollTransport: options.mailboxPollTransport,
|
|
69
|
+
});
|
|
65
70
|
for (const topic of [
|
|
66
71
|
DELEGATE_MAILBOX_TOPIC,
|
|
67
72
|
RECEIPT_MAILBOX_TOPIC,
|
|
@@ -72,9 +77,9 @@ export function* createAgentRuntime(hby, options = {}) {
|
|
|
72
77
|
}
|
|
73
78
|
const querying = new QueryCoordinator(hby);
|
|
74
79
|
const delegating = new Anchorer(hby, { poster, querying });
|
|
75
|
-
const oobiery = new Oobiery(hby, reactor, { cues });
|
|
80
|
+
const oobiery = new Oobiery(hby, reactor, { cues, services });
|
|
76
81
|
oobiery.registerReplyRoutes(reactor.router);
|
|
77
|
-
const authenticator = new Authenticator(hby);
|
|
82
|
+
const authenticator = new Authenticator(hby, { services });
|
|
78
83
|
return {
|
|
79
84
|
hby,
|
|
80
85
|
mode,
|
|
@@ -92,6 +97,7 @@ export function* createAgentRuntime(hby, options = {}) {
|
|
|
92
97
|
poster,
|
|
93
98
|
delegating,
|
|
94
99
|
querying,
|
|
100
|
+
services,
|
|
95
101
|
*close() {
|
|
96
102
|
if (ownsNoter && noter?.opened) {
|
|
97
103
|
yield* noter.close();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { closeResponseBody, fetchResponseHandle } from "./httping.js";
|
|
2
2
|
import { isWellKnownOobiUrl, parseOobiUrl } from "./oobiery.js";
|
|
3
3
|
import { persistResolvedContact } from "./organizing.js";
|
|
4
|
+
import { defaultRuntimeServices } from "./runtime-services.js";
|
|
4
5
|
import { runtimeTurn } from "./runtime-turn.js";
|
|
5
6
|
/**
|
|
6
7
|
* Well-known OOBI authenticator for one `Habery`.
|
|
@@ -16,14 +17,22 @@ import { runtimeTurn } from "./runtime-turn.js";
|
|
|
16
17
|
* - `wkas.` records successful `(cid, url)` authorizations
|
|
17
18
|
*/
|
|
18
19
|
export class Authenticator {
|
|
19
|
-
constructor(hby) {
|
|
20
|
+
constructor(hby, options = {}) {
|
|
20
21
|
Object.defineProperty(this, "hby", {
|
|
21
22
|
enumerable: true,
|
|
22
23
|
configurable: true,
|
|
23
24
|
writable: true,
|
|
24
25
|
value: void 0
|
|
25
26
|
});
|
|
27
|
+
Object.defineProperty(this, "services", {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
configurable: true,
|
|
30
|
+
writable: true,
|
|
31
|
+
value: void 0
|
|
32
|
+
});
|
|
33
|
+
const { services = defaultRuntimeServices } = options;
|
|
26
34
|
this.hby = hby;
|
|
35
|
+
this.services = services;
|
|
27
36
|
}
|
|
28
37
|
/** Process one bounded auth step if queued well-known work exists. */
|
|
29
38
|
*processOnce() {
|
|
@@ -94,7 +103,7 @@ export class Authenticator {
|
|
|
94
103
|
const cid = record.cid
|
|
95
104
|
?? parseOobiUrl(url, record.oobialias ?? undefined).cid
|
|
96
105
|
?? null;
|
|
97
|
-
const response = yield* fetchAuthResponse(url);
|
|
106
|
+
const response = yield* fetchAuthResponse(url, this.services);
|
|
98
107
|
const date = new Date().toISOString();
|
|
99
108
|
const state = response.ok ? "resolved" : `http-${response.status}`;
|
|
100
109
|
yield* closeResponseBody(response);
|
|
@@ -114,7 +123,9 @@ export class Authenticator {
|
|
|
114
123
|
}
|
|
115
124
|
}
|
|
116
125
|
}
|
|
117
|
-
function* fetchAuthResponse(url) {
|
|
118
|
-
const { response } = yield* fetchResponseHandle(url
|
|
126
|
+
function* fetchAuthResponse(url, services = defaultRuntimeServices) {
|
|
127
|
+
const { response } = yield* fetchResponseHandle(url, {}, {
|
|
128
|
+
services,
|
|
129
|
+
});
|
|
119
130
|
return response;
|
|
120
131
|
}
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegator-side CLI approval for pending delegated events.
|
|
3
|
+
*
|
|
4
|
+
* KERIpy correspondence:
|
|
5
|
+
* - this is the bounded command analogue of KLI's delegation approval flow
|
|
6
|
+
* - pending work is discovered from durable `delegables.` escrow, not from
|
|
7
|
+
* controller notifications
|
|
8
|
+
*
|
|
9
|
+
* Maintainer rule:
|
|
10
|
+
* - `/delegate/request` notifications are UI hints only
|
|
11
|
+
* - approval ordering and event selection come from the delegated-event escrows
|
|
12
|
+
* and the delegator's own KEL state
|
|
13
|
+
*/
|
|
1
14
|
import { spawn } from "effection";
|
|
2
15
|
import { Diger } from "../../../../cesr/mod.js";
|
|
3
16
|
import { ValidationError } from "../../core/errors.js";
|
|
@@ -7,6 +20,7 @@ import { createAgentRuntime, processRuntimeTurn, processRuntimeUntil, } from "..
|
|
|
7
20
|
import { queryTransportSink } from "../query-transport.js";
|
|
8
21
|
import { WitnessReceiptor } from "../witnessing.js";
|
|
9
22
|
import { setupHby } from "./common/existing.js";
|
|
23
|
+
/** Build witness auth payloads from CLI `<witness>:<code>` inputs. */
|
|
10
24
|
function resolveWitnessAuths(witnesses, codes, codeTime, promptMissing = false) {
|
|
11
25
|
const timestamp = codeTime ?? makeNowIso8601();
|
|
12
26
|
const auths = {};
|
|
@@ -33,6 +47,7 @@ function resolveWitnessAuths(witnesses, codes, codeTime, promptMissing = false)
|
|
|
33
47
|
}
|
|
34
48
|
return auths;
|
|
35
49
|
}
|
|
50
|
+
/** Return pending delegated events for one local delegator, oldest first. */
|
|
36
51
|
function pendingDelegations(hby, delegatorPre) {
|
|
37
52
|
const pending = [];
|
|
38
53
|
for (const [keys, said] of hby.db.delegables.getTopItemIter()) {
|
|
@@ -52,6 +67,7 @@ function pendingDelegations(hby, delegatorPre) {
|
|
|
52
67
|
}
|
|
53
68
|
return pending.sort((left, right) => (left.sn ?? 0) - (right.sn ?? 0));
|
|
54
69
|
}
|
|
70
|
+
/** Determine the delegator prefix for `dip` or `drt` escrow material. */
|
|
55
71
|
function delegationSourcePrefix(hby, serder, pre) {
|
|
56
72
|
if (serder.delpre) {
|
|
57
73
|
return serder.delpre;
|
|
@@ -63,12 +79,14 @@ function delegationSourcePrefix(hby, serder, pre) {
|
|
|
63
79
|
return hby.db.getKever(delegatedPre)?.delpre
|
|
64
80
|
?? hby.db.getState(delegatedPre)?.di;
|
|
65
81
|
}
|
|
82
|
+
/** Project a delegated event into the seal embedded by the approving event. */
|
|
66
83
|
function anchorData(serder) {
|
|
67
84
|
if (!serder.pre || !serder.snh || !serder.said) {
|
|
68
85
|
throw new ValidationError("Delegated event is missing pre, sn, or said.");
|
|
69
86
|
}
|
|
70
87
|
return { i: serder.pre, s: serder.snh, d: serder.said };
|
|
71
88
|
}
|
|
89
|
+
/** Resolve delegate witnesses for either delegated inception or rotation. */
|
|
72
90
|
function delegateWitnesses(hby, serder) {
|
|
73
91
|
if ((serder.sn ?? 0) === 0) {
|
|
74
92
|
return [...serder.backs];
|
|
@@ -78,6 +96,7 @@ function delegateWitnesses(hby, serder) {
|
|
|
78
96
|
}
|
|
79
97
|
return [...(hby.db.getKever(serder.pre)?.wits ?? [])];
|
|
80
98
|
}
|
|
99
|
+
/** Return true once the delegated event has left escrow and reached local state. */
|
|
81
100
|
function delegateCommitted(hby, serder) {
|
|
82
101
|
if (!serder.pre) {
|
|
83
102
|
return false;
|
|
@@ -85,6 +104,7 @@ function delegateCommitted(hby, serder) {
|
|
|
85
104
|
const kever = hby.db.getKever(serder.pre);
|
|
86
105
|
return kever !== undefined && kever !== null && kever.sn >= (serder.sn ?? 0);
|
|
87
106
|
}
|
|
107
|
+
/** Build a witness log query used to pull delegate-side completion material. */
|
|
88
108
|
function delegateWitnessLogsQuery(hab, serder, witness) {
|
|
89
109
|
if (!serder.pre || !serder.snh) {
|
|
90
110
|
throw new ValidationError("Delegated event is missing pre or sn for query.");
|
|
@@ -103,6 +123,7 @@ function delegateWitnessLogsQuery(hab, serder, witness) {
|
|
|
103
123
|
msgs: [hab.query(serder.pre, witness, query, "logs")],
|
|
104
124
|
};
|
|
105
125
|
}
|
|
126
|
+
/** Route query cues through query transport and other cues through Respondant. */
|
|
106
127
|
function delegateConfirmSink(runtime, hby, hab) {
|
|
107
128
|
const querySink = queryTransportSink(runtime, hby, hab);
|
|
108
129
|
return {
|
|
@@ -115,6 +136,7 @@ function delegateConfirmSink(runtime, hby, hab) {
|
|
|
115
136
|
},
|
|
116
137
|
};
|
|
117
138
|
}
|
|
139
|
+
/** Approve pending delegated events for the selected local delegator habitat. */
|
|
118
140
|
export function* delegateConfirmCommand(args) {
|
|
119
141
|
const confirmArgs = {
|
|
120
142
|
name: args.name,
|
|
@@ -166,6 +188,9 @@ export function* delegateConfirmCommand(args) {
|
|
|
166
188
|
const selected = confirmArgs.auto ? pending : [pending[0]];
|
|
167
189
|
for (const serder of selected) {
|
|
168
190
|
const anchor = anchorData(serder);
|
|
191
|
+
// KERIpy permits either interaction or rotation approval. Keep this
|
|
192
|
+
// explicit because the chosen approving event type affects later
|
|
193
|
+
// replay, but the embedded anchor seal is the same.
|
|
169
194
|
if (interactionApproval) {
|
|
170
195
|
hab.interact({ data: [anchor] });
|
|
171
196
|
}
|
|
@@ -193,6 +218,9 @@ export function* delegateConfirmCommand(args) {
|
|
|
193
218
|
const witnesses = delegateWitnesses(hby, serder).sort();
|
|
194
219
|
const selectedWitness = witnesses[0];
|
|
195
220
|
if (selectedWitness) {
|
|
221
|
+
// Witnessed delegates must prove the delegated event is committed
|
|
222
|
+
// locally before we pin `aess.` and retry delegated unescrow. Doing
|
|
223
|
+
// it earlier can make local state look approved but incomplete.
|
|
196
224
|
yield* sink.send(delegateWitnessLogsQuery(hab, serder, selectedWitness));
|
|
197
225
|
yield* processRuntimeUntil(runtime, () => delegateCommitted(hby, serder), { hab, maxTurns: 128, pollMailbox: true, sink });
|
|
198
226
|
}
|
|
@@ -13,6 +13,7 @@ function requireRid(rid) {
|
|
|
13
13
|
}
|
|
14
14
|
return rid;
|
|
15
15
|
}
|
|
16
|
+
/** Open the signed notification facade for one CLI invocation. */
|
|
16
17
|
function* openNotifier(args) {
|
|
17
18
|
const hby = yield* setupHby(requireName(args.name), args.base ?? "", args.passcode, false, args.headDirPath, {
|
|
18
19
|
compat: args.compat ?? false,
|
|
@@ -26,6 +27,7 @@ function* openNotifier(args) {
|
|
|
26
27
|
notifier: new Notifier(hby, { noter }),
|
|
27
28
|
};
|
|
28
29
|
}
|
|
30
|
+
/** Print verified local controller notices as JSON for operator inspection. */
|
|
29
31
|
export function* notificationsListCommand(args) {
|
|
30
32
|
const commandArgs = {
|
|
31
33
|
name: args.name,
|
|
@@ -60,6 +62,7 @@ export function* notificationsListCommand(args) {
|
|
|
60
62
|
yield* hby.close();
|
|
61
63
|
}
|
|
62
64
|
}
|
|
65
|
+
/** Mark one verified notice as read and persist its new detached signature. */
|
|
63
66
|
export function* notificationsMarkReadCommand(args) {
|
|
64
67
|
const commandArgs = {
|
|
65
68
|
name: args.name,
|
|
@@ -82,6 +85,7 @@ export function* notificationsMarkReadCommand(args) {
|
|
|
82
85
|
yield* hby.close();
|
|
83
86
|
}
|
|
84
87
|
}
|
|
88
|
+
/** Remove one verified notice from the notification sidecar. */
|
|
85
89
|
export function* notificationsRemoveCommand(args) {
|
|
86
90
|
const commandArgs = {
|
|
87
91
|
name: args.name,
|
|
@@ -6,6 +6,7 @@ import { dgKey } from "../db/core/keys.js";
|
|
|
6
6
|
import { eventPayloadMessage, eventReplayMessage } from "./habbing.js";
|
|
7
7
|
import { sendWitnessMessage } from "./witnessing.js";
|
|
8
8
|
export const DELEGATE_REQUEST_ROUTE = "/delegate/request";
|
|
9
|
+
/** Runtime passes to wait between repeated delegator-witness anchor queries. */
|
|
9
10
|
const DELEGATION_ANCHOR_QUERY_RETRY_PASSES = 8;
|
|
10
11
|
function eventKey(serder) {
|
|
11
12
|
const pre = serder.pre;
|
|
@@ -15,12 +16,14 @@ function eventKey(serder) {
|
|
|
15
16
|
}
|
|
16
17
|
return [pre, snh];
|
|
17
18
|
}
|
|
19
|
+
/** Build the anchor seal shape a delegator must embed in its approving event. */
|
|
18
20
|
function eventAnchor(serder) {
|
|
19
21
|
if (!serder.pre || !serder.snh || !serder.said) {
|
|
20
22
|
throw new ValidationError("Delegated approval anchor requires pre, sn, and said.");
|
|
21
23
|
}
|
|
22
24
|
return { i: serder.pre, s: serder.snh, d: serder.said };
|
|
23
25
|
}
|
|
26
|
+
/** Resolve the local habitat that owns the delegated event being processed. */
|
|
24
27
|
function workflowHab(hby, serder) {
|
|
25
28
|
const pre = serder.pre;
|
|
26
29
|
if (!pre) {
|
|
@@ -61,6 +64,7 @@ function escrowContext(keys, serder) {
|
|
|
61
64
|
}
|
|
62
65
|
return [keys, serder, pre, said, snh];
|
|
63
66
|
}
|
|
67
|
+
/** Persist the delegator event seal that authorizes one delegated event. */
|
|
64
68
|
function pinAuthorizingSeal(hby, delegated, delegating) {
|
|
65
69
|
const pre = delegated.pre;
|
|
66
70
|
const said = delegated.said;
|
|
@@ -84,12 +88,14 @@ function witnessReceiptsComplete(hby, serder) {
|
|
|
84
88
|
}
|
|
85
89
|
return hby.db.wigs.get(dgKey(pre, said)).length >= kever.wits.length;
|
|
86
90
|
}
|
|
91
|
+
/** Resolve the delegator prefix from event material or accepted delegated state. */
|
|
87
92
|
function delegatedWorkflowDelpre(hby, serder, hab) {
|
|
88
93
|
if (serder.delpre) {
|
|
89
94
|
return serder.delpre;
|
|
90
95
|
}
|
|
91
96
|
return (hab ?? workflowHab(hby, serder)).kever?.delpre ?? null;
|
|
92
97
|
}
|
|
98
|
+
/** Return the local delegator event that contains the delegated event seal. */
|
|
93
99
|
function approvingEvent(hby, serder, hab) {
|
|
94
100
|
const delpre = delegatedWorkflowDelpre(hby, serder, hab);
|
|
95
101
|
return delpre
|
|
@@ -113,6 +119,7 @@ export function resolveDelegationCommunicationHab(hby, alias) {
|
|
|
113
119
|
}
|
|
114
120
|
return hab;
|
|
115
121
|
}
|
|
122
|
+
/** Install delegation-specific EXN handlers into one exchange router. */
|
|
116
123
|
export function loadDelegationHandlers(hby, exchanger, notifier = null) {
|
|
117
124
|
exchanger.addHandler(new DelegateRequestHandler(hby, notifier));
|
|
118
125
|
}
|
|
@@ -165,6 +172,7 @@ export class DelegateRequestHandler {
|
|
|
165
172
|
&& typeof embeds?.["evt"] === "object"
|
|
166
173
|
&& embeds?.["evt"] !== null;
|
|
167
174
|
}
|
|
175
|
+
/** Store a signed controller notification when this request targets a local delegator. */
|
|
168
176
|
handle(args) {
|
|
169
177
|
if (!this.notifier) {
|
|
170
178
|
return;
|
|
@@ -282,6 +290,7 @@ export class Anchorer {
|
|
|
282
290
|
this.communicationHabPins.delete(id);
|
|
283
291
|
}
|
|
284
292
|
}
|
|
293
|
+
/** Begin workflow processing from the currently accepted event for an AID. */
|
|
285
294
|
beginLatest(pre, sn, options = {}) {
|
|
286
295
|
const kever = this.hby.db.getKever(pre);
|
|
287
296
|
if (!kever) {
|
|
@@ -299,6 +308,7 @@ export class Anchorer {
|
|
|
299
308
|
this.begin(serder, options);
|
|
300
309
|
return serder;
|
|
301
310
|
}
|
|
311
|
+
/** Return the current durable workflow phase without mutating escrow state. */
|
|
302
312
|
workflowStatus(pre, snh) {
|
|
303
313
|
const key = [pre, snh];
|
|
304
314
|
const serder = this.hby.db.dpwe.get(key)
|
|
@@ -323,6 +333,7 @@ export class Anchorer {
|
|
|
323
333
|
complete: completed,
|
|
324
334
|
};
|
|
325
335
|
}
|
|
336
|
+
/** Return true after the delegated event has been durably completed. */
|
|
326
337
|
complete(pre, sn) {
|
|
327
338
|
const snNum = typeof sn === "number" ? sn : parseInt(sn, 16);
|
|
328
339
|
if (!Number.isInteger(snNum) || snNum < 0) {
|
|
@@ -340,6 +351,7 @@ export class Anchorer {
|
|
|
340
351
|
}
|
|
341
352
|
return false;
|
|
342
353
|
}
|
|
354
|
+
/** Process all delegation escrow families once in KERIpy-compatible order. */
|
|
343
355
|
*processAllOnce() {
|
|
344
356
|
const results = [];
|
|
345
357
|
for (const [keys, serder] of [...this.hby.db.dpwe.getTopItemIter()]) {
|
|
@@ -405,6 +417,9 @@ export class Anchorer {
|
|
|
405
417
|
reason: "Delegate witness receipts are not converged yet.",
|
|
406
418
|
};
|
|
407
419
|
}
|
|
420
|
+
// Do not ask the delegator to approve until the delegate's own witnesses
|
|
421
|
+
// have receipted the event. That preserves the KERIpy approval ordering
|
|
422
|
+
// and avoids anchoring an event the delegate cannot yet complete.
|
|
408
423
|
const message = eventPayloadMessage(this.hby, serder);
|
|
409
424
|
yield* this.poster.sendExchange(communicationHab, {
|
|
410
425
|
recipient: delpre,
|
|
@@ -475,6 +490,9 @@ export class Anchorer {
|
|
|
475
490
|
reason: this.retryDelegatorWitnessQuery(serder, communicationHab),
|
|
476
491
|
};
|
|
477
492
|
}
|
|
493
|
+
// The approving event is authoritative only after the delegator's sealing
|
|
494
|
+
// event is learned locally; pinning `aess.` is what lets delegated unescrow
|
|
495
|
+
// and later reopen paths prove the authorization.
|
|
478
496
|
pinAuthorizingSeal(this.hby, serder, delegating);
|
|
479
497
|
this.hby.db.dune.rem(keys);
|
|
480
498
|
if ((hab.kever?.wits.length ?? 0) === 0) {
|
|
@@ -548,6 +566,7 @@ export class Anchorer {
|
|
|
548
566
|
// immediately enqueueing the same query again.
|
|
549
567
|
this.anchorQueryRetryPasses.set(id, -1);
|
|
550
568
|
}
|
|
569
|
+
/** Retry bounded delegator-witness queries while waiting for the anchor. */
|
|
551
570
|
retryDelegatorWitnessQuery(serder, communicationHab) {
|
|
552
571
|
const id = workflowId(serder);
|
|
553
572
|
const delpre = delegatedWorkflowDelpre(this.hby, serder);
|
|
@@ -605,6 +624,8 @@ export class Anchorer {
|
|
|
605
624
|
if (!kever) {
|
|
606
625
|
throw new ValidationError(`Delegation witness publication: missing accepted key state for ${pre}.`);
|
|
607
626
|
}
|
|
627
|
+
// Publish the delegator chain first, then replay the approving event. This
|
|
628
|
+
// matches the witness-visible material KERIpy sends for delegated approval.
|
|
608
629
|
for (const msg of this.hby.db.cloneDelegation(kever)) {
|
|
609
630
|
for (const witness of kever.wits) {
|
|
610
631
|
yield* sendWitnessMessage(hab, witness, msg);
|