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.
Files changed (79) hide show
  1. package/esm/cesr/mod.js +1 -0
  2. package/esm/cesr/src/core/parser-frame-parser.js +3 -0
  3. package/esm/cesr/src/primitives/matter.js +7 -0
  4. package/esm/cesr/src/tables/counter.tables.generated.js +1 -5
  5. package/esm/cesr/src/tables/hard-code-tables.js +39 -0
  6. package/esm/cesr/src/tables/indexer.tables.generated.js +1 -9
  7. package/esm/cesr/src/tables/matter.tables.generated.js +1 -14
  8. package/esm/cesr/src/version.js +7 -4
  9. package/esm/keri/src/app/agent-runtime.js +11 -5
  10. package/esm/keri/src/app/authenticating.js +15 -4
  11. package/esm/keri/src/app/cli/delegate.js +28 -0
  12. package/esm/keri/src/app/cli/notifications.js +4 -0
  13. package/esm/keri/src/app/delegating.js +21 -0
  14. package/esm/keri/src/app/forwarding.js +59 -13
  15. package/esm/keri/src/app/habbing.js +1 -0
  16. package/esm/keri/src/app/httping.js +12 -7
  17. package/esm/keri/src/app/keeping.js +3 -3
  18. package/esm/keri/src/app/mailbox-sse.js +11 -9
  19. package/esm/keri/src/app/notifying.js +11 -0
  20. package/esm/keri/src/app/oobiery.js +15 -4
  21. package/esm/keri/src/app/query-transport.js +3 -0
  22. package/esm/keri/src/app/runtime-services.js +22 -0
  23. package/esm/keri/src/app/version.js +7 -4
  24. package/esm/keri/src/core/eventing.js +40 -0
  25. package/esm/keri/src/core/kever.js +9 -0
  26. package/esm/keri/src/core/protocol-eventing.js +15 -0
  27. package/esm/keri/src/db/noting.js +4 -0
  28. package/esm/keri/src/runtime/index.js +1 -0
  29. package/package.json +2 -2
  30. package/types/cesr/mod.d.ts +1 -0
  31. package/types/cesr/mod.d.ts.map +1 -1
  32. package/types/cesr/src/core/parser-frame-parser.d.ts.map +1 -1
  33. package/types/cesr/src/primitives/matter.d.ts.map +1 -1
  34. package/types/cesr/src/tables/counter.tables.generated.d.ts +1 -1
  35. package/types/cesr/src/tables/counter.tables.generated.d.ts.map +1 -1
  36. package/types/cesr/src/tables/hard-code-tables.d.ts +15 -0
  37. package/types/cesr/src/tables/hard-code-tables.d.ts.map +1 -0
  38. package/types/cesr/src/tables/indexer.tables.generated.d.ts +1 -1
  39. package/types/cesr/src/tables/indexer.tables.generated.d.ts.map +1 -1
  40. package/types/cesr/src/tables/matter.tables.generated.d.ts +1 -1
  41. package/types/cesr/src/tables/matter.tables.generated.d.ts.map +1 -1
  42. package/types/cesr/src/version.d.ts +7 -4
  43. package/types/cesr/src/version.d.ts.map +1 -1
  44. package/types/keri/src/app/agent-runtime.d.ts +5 -1
  45. package/types/keri/src/app/agent-runtime.d.ts.map +1 -1
  46. package/types/keri/src/app/authenticating.d.ts +7 -1
  47. package/types/keri/src/app/authenticating.d.ts.map +1 -1
  48. package/types/keri/src/app/cli/delegate.d.ts +14 -0
  49. package/types/keri/src/app/cli/delegate.d.ts.map +1 -1
  50. package/types/keri/src/app/cli/notifications.d.ts +10 -0
  51. package/types/keri/src/app/cli/notifications.d.ts.map +1 -1
  52. package/types/keri/src/app/delegating.d.ts +23 -0
  53. package/types/keri/src/app/delegating.d.ts.map +1 -1
  54. package/types/keri/src/app/forwarding.d.ts +39 -9
  55. package/types/keri/src/app/forwarding.d.ts.map +1 -1
  56. package/types/keri/src/app/habbing.d.ts.map +1 -1
  57. package/types/keri/src/app/httping.d.ts +10 -4
  58. package/types/keri/src/app/httping.d.ts.map +1 -1
  59. package/types/keri/src/app/keeping.d.ts +2 -2
  60. package/types/keri/src/app/mailbox-sse.d.ts +8 -4
  61. package/types/keri/src/app/mailbox-sse.d.ts.map +1 -1
  62. package/types/keri/src/app/notifying.d.ts +23 -0
  63. package/types/keri/src/app/notifying.d.ts.map +1 -1
  64. package/types/keri/src/app/oobiery.d.ts +7 -3
  65. package/types/keri/src/app/oobiery.d.ts.map +1 -1
  66. package/types/keri/src/app/query-transport.d.ts.map +1 -1
  67. package/types/keri/src/app/runtime-services.d.ts +26 -0
  68. package/types/keri/src/app/runtime-services.d.ts.map +1 -0
  69. package/types/keri/src/app/version.d.ts +7 -4
  70. package/types/keri/src/app/version.d.ts.map +1 -1
  71. package/types/keri/src/core/eventing.d.ts +30 -0
  72. package/types/keri/src/core/eventing.d.ts.map +1 -1
  73. package/types/keri/src/core/kever.d.ts.map +1 -1
  74. package/types/keri/src/core/protocol-eventing.d.ts +8 -0
  75. package/types/keri/src/core/protocol-eventing.d.ts.map +1 -1
  76. package/types/keri/src/db/noting.d.ts +2 -0
  77. package/types/keri/src/db/noting.d.ts.map +1 -1
  78. package/types/keri/src/runtime/index.d.ts +1 -0
  79. package/types/keri/src/runtime/index.d.ts.map +1 -1
package/esm/cesr/mod.js CHANGED
@@ -1,2 +1,3 @@
1
+ /** cesr-ts npm package root entrypoint. */
1
2
  export * from "./src/index.js";
2
3
  export * from "./src/version.js";
@@ -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
- ]);
@@ -1,11 +1,14 @@
1
1
  /**
2
- * Generated by scripts/generate_versions.ts.
3
- * Do not edit by hand.
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.6.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.9.11f27f1a6176caac7b15d7fba862023af598592f";
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);