keri-ts 2.0.1 → 2.1.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/keri/npm/src/acdc/chaining.js +223 -89
- package/esm/keri/npm/src/acdc/observing.js +2 -2
- package/esm/keri/npm/src/acdc/regbasing.js +20 -29
- package/esm/keri/npm/src/acdc/regengine.js +4 -6
- package/esm/keri/npm/src/acdc/registering.js +13 -10
- package/esm/keri/npm/src/acdc/registraring.js +4 -9
- package/esm/keri/npm/src/acdc/salting.js +127 -25
- package/esm/keri/npm/src/acdc/unblinding.js +2 -4
- package/esm/keri/npm/src/app/bootstrap/oobiery.js +1 -1
- package/esm/keri/npm/src/app/credentials/root-replicating.js +123 -0
- package/esm/keri/npm/src/app/credentials/verifying.js +12 -3
- package/esm/keri/npm/src/app/delivery/forwarding.js +49 -7
- package/esm/keri/npm/src/app/exchanges/exchanging.js +11 -12
- package/esm/keri/npm/src/app/identity/configing.js +17 -43
- package/esm/keri/npm/src/app/identity/habbing.js +54 -35
- package/esm/keri/npm/src/app/identity/keeping.js +1 -1
- package/esm/keri/npm/src/app/identity/lmdb-habery.js +12 -0
- package/esm/keri/npm/src/app/ipex/ipex-graph.js +7 -70
- package/esm/keri/npm/src/app/ipex/ipex-grouping.js +8 -5
- package/esm/keri/npm/src/app/ipex/ipex-v2.js +21 -5
- package/esm/keri/npm/src/app/ipex/ipexing.js +1 -1
- package/esm/keri/npm/src/app/mailbox/mailboxing.js +5 -9
- package/esm/keri/npm/src/app/multisig/group-members.js +14 -0
- package/esm/keri/npm/src/app/multisig/grouping.js +4 -3
- package/esm/keri/npm/src/app/multisig/multisig-workflows.js +7 -2
- package/esm/keri/npm/src/app/notifications/notifying.js +5 -9
- package/esm/keri/npm/src/app/protocol/protocol-processing.js +35 -3
- package/esm/keri/npm/src/app/queries/witness-inquisitor.js +2 -2
- package/esm/keri/npm/src/app/runtime/agent-runtime.js +7 -10
- package/esm/keri/npm/src/app/transport/byte-source.js +6 -42
- package/esm/keri/npm/src/app/transport/cesr-egress.js +77 -13
- package/esm/keri/npm/src/app/transport/file-bytes.js +41 -0
- package/esm/keri/npm/src/app/transport/http-messenger.js +14 -9
- package/esm/keri/npm/src/app/transport/message-source.js +1 -1
- package/esm/keri/npm/src/app/transport/messengering.js +3 -4
- package/esm/keri/npm/src/app/transport/node-http-client.js +21 -0
- package/esm/keri/npm/src/app/transport/tcp-dialer.js +14 -0
- package/esm/keri/npm/src/app/witness/receipt-client.js +2 -2
- package/esm/keri/npm/src/cli/common/context.js +2 -2
- package/esm/keri/npm/src/cli/common/existing.js +3 -5
- package/esm/keri/npm/src/cli/credentials/ipex.js +2 -1
- package/esm/keri/npm/src/cli/endpoints/oobi-clean.js +4 -3
- package/esm/keri/npm/src/cli/endpoints/oobi.js +2 -2
- package/esm/keri/npm/src/cli/identity/challenge.js +2 -2
- package/esm/keri/npm/src/cli/identity/incept.js +2 -2
- package/esm/keri/npm/src/cli/identity/init.js +4 -3
- package/esm/keri/npm/src/cli/identity/interact.js +2 -2
- package/esm/keri/npm/src/cli/identity/rotate.js +2 -2
- package/esm/keri/npm/src/cli/messaging/exchange.js +2 -2
- package/esm/keri/npm/src/cli/messaging/multisig.js +61 -3
- package/esm/keri/npm/src/cli/tools/annotate.js +2 -1
- package/esm/keri/npm/src/cli/tools/benchmark.js +2 -1
- package/esm/keri/npm/src/cli/tools/db-dump.js +1 -4
- package/esm/keri/npm/src/core/bytes.js +9 -0
- package/esm/keri/npm/src/core/kel/delegation-ancestry.js +92 -0
- package/esm/keri/npm/src/core/kel/eventing.js +1 -2
- package/esm/keri/npm/src/core/kel/kever.js +11 -9
- package/esm/keri/npm/src/core/mailbox/kram-policy.js +2 -3
- package/esm/keri/npm/src/core/mailbox/kram-pruning.js +15 -22
- package/esm/keri/npm/src/core/mailbox/kram-staging.js +2 -2
- package/esm/keri/npm/src/core/routing.js +2 -2
- package/esm/keri/npm/src/db/basing.js +149 -203
- package/esm/keri/npm/src/db/core/dber.js +1062 -0
- package/esm/keri/npm/src/db/core/index.js +4 -2
- package/esm/keri/npm/src/db/core/lmdb-opener.js +30 -0
- package/esm/keri/npm/src/db/core/lmdber.js +199 -1067
- package/esm/keri/npm/src/db/core/memstore.js +532 -0
- package/esm/keri/npm/src/db/core/path-manager.js +109 -223
- package/esm/keri/npm/src/db/core/store-owner.js +104 -0
- package/esm/keri/npm/src/db/core/webdber.js +252 -0
- package/esm/keri/npm/src/db/escrowing.js +2 -2
- package/esm/keri/npm/src/db/exchange/exchange-nests.js +3 -2
- package/esm/keri/npm/src/db/keeping.js +27 -121
- package/esm/keri/npm/src/db/koming.js +1 -1
- package/esm/keri/npm/src/db/lmdb-stores.js +68 -0
- package/esm/keri/npm/src/db/lmdb.js +6 -0
- package/esm/keri/npm/src/db/mailbox/mailboxing.js +12 -65
- package/esm/keri/npm/src/db/noting.js +11 -55
- package/esm/keri/npm/src/db/reger.js +43 -105
- package/esm/keri/npm/src/db/replay/witness-replay.js +2 -20
- package/esm/keri/npm/src/db/subing.js +1 -1
- package/esm/keri/npm/src/npm/db-lmdb.js +3 -0
- package/esm/keri/npm/src/npm/runtime-node.js +3 -0
- package/esm/keri/npm/src/runtime/index.js +9 -10
- package/esm/keri/npm/src/runtime/node.js +14 -0
- package/esm/keri/npm/src/vdr/eventing.js +1 -1
- package/esm/keri/npm/src/vdr/tel-publication.js +3 -3
- package/esm/keri/npm/src/version.js +2 -2
- package/package.json +11 -4
- package/types/acdc/chaining.d.ts +56 -6
- package/types/acdc/chaining.d.ts.map +1 -1
- package/types/acdc/regbasing.d.ts +7 -6
- package/types/acdc/regbasing.d.ts.map +1 -1
- package/types/acdc/regengine.d.ts.map +1 -1
- package/types/acdc/registering.d.ts +8 -4
- package/types/acdc/registering.d.ts.map +1 -1
- package/types/acdc/registraring.d.ts.map +1 -1
- package/types/acdc/salting.d.ts +53 -6
- package/types/acdc/salting.d.ts.map +1 -1
- package/types/acdc/unblinding.d.ts.map +1 -1
- package/types/app/credentials/root-replicating.d.ts +85 -0
- package/types/app/credentials/root-replicating.d.ts.map +1 -0
- package/types/app/credentials/verifying.d.ts +2 -1
- package/types/app/credentials/verifying.d.ts.map +1 -1
- package/types/app/delivery/forwarding.d.ts +10 -0
- package/types/app/delivery/forwarding.d.ts.map +1 -1
- package/types/app/exchanges/exchanging.d.ts +2 -0
- package/types/app/exchanges/exchanging.d.ts.map +1 -1
- package/types/app/identity/configing.d.ts +7 -5
- package/types/app/identity/configing.d.ts.map +1 -1
- package/types/app/identity/habbing.d.ts +23 -5
- package/types/app/identity/habbing.d.ts.map +1 -1
- package/types/app/identity/keeping.d.ts +1 -1
- package/types/app/identity/lmdb-habery.d.ts +6 -0
- package/types/app/identity/lmdb-habery.d.ts.map +1 -0
- package/types/app/ipex/ipex-graph.d.ts +4 -4
- package/types/app/ipex/ipex-graph.d.ts.map +1 -1
- package/types/app/ipex/ipex-grouping.d.ts.map +1 -1
- package/types/app/ipex/ipex-v2.d.ts +11 -2
- package/types/app/ipex/ipex-v2.d.ts.map +1 -1
- package/types/app/ipex/ipexing.d.ts +3 -0
- package/types/app/ipex/ipexing.d.ts.map +1 -1
- package/types/app/mailbox/mailboxing.d.ts +1 -1
- package/types/app/mailbox/mailboxing.d.ts.map +1 -1
- package/types/app/multisig/group-members.d.ts +9 -0
- package/types/app/multisig/group-members.d.ts.map +1 -1
- package/types/app/multisig/grouping.d.ts.map +1 -1
- package/types/app/multisig/multisig-workflows.d.ts +2 -1
- package/types/app/multisig/multisig-workflows.d.ts.map +1 -1
- package/types/app/notifications/notifying.d.ts +1 -1
- package/types/app/notifications/notifying.d.ts.map +1 -1
- package/types/app/protocol/parsering.d.ts +3 -1
- package/types/app/protocol/parsering.d.ts.map +1 -1
- package/types/app/protocol/protocol-processing.d.ts +2 -0
- package/types/app/protocol/protocol-processing.d.ts.map +1 -1
- package/types/app/runtime/agent-runtime.d.ts +7 -0
- package/types/app/runtime/agent-runtime.d.ts.map +1 -1
- package/types/app/transport/byte-source.d.ts +13 -10
- package/types/app/transport/byte-source.d.ts.map +1 -1
- package/types/app/transport/cesr-egress.d.ts +21 -7
- package/types/app/transport/cesr-egress.d.ts.map +1 -1
- package/types/app/transport/file-bytes.d.ts +11 -0
- package/types/app/transport/file-bytes.d.ts.map +1 -0
- package/types/app/transport/http-client.d.ts +3 -0
- package/types/app/transport/http-client.d.ts.map +1 -1
- package/types/app/transport/http-messenger.d.ts +15 -10
- package/types/app/transport/http-messenger.d.ts.map +1 -1
- package/types/app/transport/message-source.d.ts +1 -1
- package/types/app/transport/messengering.d.ts +2 -2
- package/types/app/transport/messengering.d.ts.map +1 -1
- package/types/app/transport/node-http-client.d.ts +10 -0
- package/types/app/transport/node-http-client.d.ts.map +1 -0
- package/types/app/transport/tcp-dialer.d.ts +21 -0
- package/types/app/transport/tcp-dialer.d.ts.map +1 -0
- package/types/cli/common/existing.d.ts.map +1 -1
- package/types/cli/credentials/ipex.d.ts.map +1 -1
- package/types/cli/endpoints/oobi-clean.d.ts.map +1 -1
- package/types/cli/identity/init.d.ts.map +1 -1
- package/types/cli/index.d.ts +1 -1
- package/types/cli/index.d.ts.map +1 -1
- package/types/cli/messaging/multisig.d.ts +10 -1
- package/types/cli/messaging/multisig.d.ts.map +1 -1
- package/types/cli/tools/annotate.d.ts.map +1 -1
- package/types/cli/tools/benchmark.d.ts.map +1 -1
- package/types/cli/tools/db-dump.d.ts.map +1 -1
- package/types/core/bytes.d.ts +2 -0
- package/types/core/bytes.d.ts.map +1 -1
- package/types/core/kel/delegation-ancestry.d.ts +41 -0
- package/types/core/kel/delegation-ancestry.d.ts.map +1 -0
- package/types/core/kel/eventing.d.ts.map +1 -1
- package/types/core/kel/kever.d.ts +5 -4
- package/types/core/kel/kever.d.ts.map +1 -1
- package/types/core/mailbox/kram-policy.d.ts.map +1 -1
- package/types/core/mailbox/kram-pruning.d.ts +1 -3
- package/types/core/mailbox/kram-pruning.d.ts.map +1 -1
- package/types/db/basing.d.ts +14 -23
- package/types/db/basing.d.ts.map +1 -1
- package/types/db/core/dber.d.ts +505 -0
- package/types/db/core/dber.d.ts.map +1 -0
- package/types/db/core/index.d.ts +4 -2
- package/types/db/core/index.d.ts.map +1 -1
- package/types/db/core/lmdb-opener.d.ts +17 -0
- package/types/db/core/lmdb-opener.d.ts.map +1 -0
- package/types/db/core/lmdber.d.ts +60 -383
- package/types/db/core/lmdber.d.ts.map +1 -1
- package/types/db/core/memstore.d.ts +129 -0
- package/types/db/core/memstore.d.ts.map +1 -0
- package/types/db/core/path-manager.d.ts +22 -45
- package/types/db/core/path-manager.d.ts.map +1 -1
- package/types/db/core/store-owner.d.ts +59 -0
- package/types/db/core/store-owner.d.ts.map +1 -0
- package/types/db/core/webdber.d.ts +127 -0
- package/types/db/core/webdber.d.ts.map +1 -0
- package/types/db/escrowing.d.ts +3 -3
- package/types/db/escrowing.d.ts.map +1 -1
- package/types/db/exchange/exchange-nests.d.ts.map +1 -1
- package/types/db/keeping.d.ts +9 -23
- package/types/db/keeping.d.ts.map +1 -1
- package/types/db/koming.d.ts +7 -8
- package/types/db/koming.d.ts.map +1 -1
- package/types/db/lmdb-stores.d.ts +45 -0
- package/types/db/lmdb-stores.d.ts.map +1 -0
- package/types/db/lmdb.d.ts +7 -0
- package/types/db/lmdb.d.ts.map +1 -0
- package/types/db/mailbox/mailboxing.d.ts +7 -21
- package/types/db/mailbox/mailboxing.d.ts.map +1 -1
- package/types/db/noting.d.ts +7 -12
- package/types/db/noting.d.ts.map +1 -1
- package/types/db/reger.d.ts +7 -11
- package/types/db/reger.d.ts.map +1 -1
- package/types/db/replay/witness-replay.d.ts +0 -2
- package/types/db/replay/witness-replay.d.ts.map +1 -1
- package/types/db/subing.d.ts +24 -25
- package/types/db/subing.d.ts.map +1 -1
- package/types/npm/db-lmdb.d.ts +4 -0
- package/types/npm/db-lmdb.d.ts.map +1 -0
- package/types/npm/runtime-node.d.ts +4 -0
- package/types/npm/runtime-node.d.ts.map +1 -0
- package/types/runtime/index.d.ts +9 -10
- package/types/runtime/index.d.ts.map +1 -1
- package/types/runtime/node.d.ts +15 -0
- package/types/runtime/node.d.ts.map +1 -0
- package/types/version.d.ts +2 -2
- package/esm/keri/npm/src/acdc/relating.js +0 -59
- package/esm/keri/npm/src/db/baser-defaults.js +0 -11
- package/types/acdc/relating.d.ts +0 -21
- package/types/acdc/relating.d.ts.map +0 -1
- package/types/db/baser-defaults.d.ts +0 -5
- package/types/db/baser-defaults.d.ts.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
-
import { basename, dirname, join } from "../../deps/jsr.io/@std/path/1.1.6/mod.js";
|
|
2
|
+
import { basename, dirname, extname, join } from "../../deps/jsr.io/@std/path/1.1.6/mod.js";
|
|
3
3
|
import { ValidationError } from "../../core/errors.js";
|
|
4
4
|
import { PathManager } from "../../db/core/path-manager.js";
|
|
5
5
|
const CONFIGER_DEFAULTS = {
|
|
@@ -23,7 +23,7 @@ const CONFIGER_DEFAULTS = {
|
|
|
23
23
|
* - currently supports JSON only
|
|
24
24
|
*/
|
|
25
25
|
export class Configer {
|
|
26
|
-
/** Create a config manager bound to a PathManager-
|
|
26
|
+
/** Create a config manager bound to a PathManager-resolved file. */
|
|
27
27
|
constructor(options = {}) {
|
|
28
28
|
Object.defineProperty(this, "name", {
|
|
29
29
|
enumerable: true,
|
|
@@ -62,7 +62,7 @@ export class Configer {
|
|
|
62
62
|
value: null
|
|
63
63
|
});
|
|
64
64
|
this.name = options.name || "conf";
|
|
65
|
-
this.base = options.base
|
|
65
|
+
this.base = options.base ?? "main";
|
|
66
66
|
this.temp = options.temp || false;
|
|
67
67
|
this.fext = options.fext || CONFIGER_DEFAULTS.fext;
|
|
68
68
|
this.pathManager = new PathManager({
|
|
@@ -70,27 +70,24 @@ export class Configer {
|
|
|
70
70
|
name: this.name,
|
|
71
71
|
base: this.base,
|
|
72
72
|
temp: this.temp,
|
|
73
|
+
filed: true,
|
|
74
|
+
fext: this.fext,
|
|
73
75
|
}, {
|
|
74
76
|
tailDirPath: CONFIGER_DEFAULTS.tailDirPath,
|
|
75
77
|
cleanTailDirPath: CONFIGER_DEFAULTS.cleanTailDirPath,
|
|
76
|
-
altTailDirPath: CONFIGER_DEFAULTS.altTailDirPath,
|
|
77
|
-
altCleanTailDirPath: CONFIGER_DEFAULTS.altCleanTailDirPath,
|
|
78
|
+
altTailDirPath: options.compat ? ".keri/cf" : CONFIGER_DEFAULTS.altTailDirPath,
|
|
79
|
+
altCleanTailDirPath: options.compat ? ".keri/clean/cf" : CONFIGER_DEFAULTS.altCleanTailDirPath,
|
|
78
80
|
tempPrefix: CONFIGER_DEFAULTS.tempPrefix,
|
|
79
81
|
});
|
|
80
82
|
}
|
|
81
83
|
get opened() {
|
|
82
84
|
return this.path !== null;
|
|
83
85
|
}
|
|
84
|
-
/**
|
|
85
|
-
|
|
86
|
-
if (this.name.endsWith(`.${this.fext}`)) {
|
|
87
|
-
return this.name;
|
|
88
|
-
}
|
|
89
|
-
const hasExt = this.name.includes(".");
|
|
90
|
-
if (hasExt) {
|
|
86
|
+
/** Refuse a config name carrying an extension this manager cannot read. */
|
|
87
|
+
assertSupportedExtension() {
|
|
88
|
+
if (extname(this.name) && !this.name.endsWith(`.${this.fext}`)) {
|
|
91
89
|
throw new ValidationError(`Unsupported config extension for '${this.name}'. Only .${this.fext} is supported.`);
|
|
92
90
|
}
|
|
93
|
-
return `${this.name}.${this.fext}`;
|
|
94
91
|
}
|
|
95
92
|
ensureOpenPath() {
|
|
96
93
|
if (!this.path) {
|
|
@@ -194,44 +191,21 @@ export class Configer {
|
|
|
194
191
|
throw pendingError;
|
|
195
192
|
}
|
|
196
193
|
}
|
|
197
|
-
/** Open
|
|
194
|
+
/** Open the config file at KERIpy's `{head}/keri/cf/{base}/{name}.{fext}`, creating it when absent. */
|
|
198
195
|
*reopen(options = {}) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
name: this.name,
|
|
202
|
-
base: this.base,
|
|
203
|
-
temp: this.temp,
|
|
204
|
-
});
|
|
196
|
+
this.assertSupportedExtension();
|
|
197
|
+
const opened = yield* this.pathManager.reopen(options);
|
|
205
198
|
if (!opened || !this.pathManager.path) {
|
|
206
199
|
return false;
|
|
207
200
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
dntShim.Deno.statSync(this.path);
|
|
212
|
-
}
|
|
213
|
-
catch (error) {
|
|
214
|
-
if (error instanceof dntShim.Deno.errors.NotFound) {
|
|
215
|
-
this.writeAtomic(this.path, "{}\n");
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
throw error;
|
|
219
|
-
}
|
|
201
|
+
this.path = this.pathManager.path;
|
|
202
|
+
if (dntShim.Deno.statSync(this.path).size === 0) {
|
|
203
|
+
this.writeAtomic(this.path, "{}\n");
|
|
220
204
|
}
|
|
221
205
|
return true;
|
|
222
206
|
}
|
|
223
|
-
/** Close the config manager and optionally remove
|
|
207
|
+
/** Close the config manager and optionally remove the file. */
|
|
224
208
|
*close(clear = false) {
|
|
225
|
-
if (clear && this.path) {
|
|
226
|
-
try {
|
|
227
|
-
dntShim.Deno.removeSync(this.path);
|
|
228
|
-
}
|
|
229
|
-
catch (error) {
|
|
230
|
-
if (!(error instanceof dntShim.Deno.errors.NotFound)) {
|
|
231
|
-
throw error;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
209
|
this.path = null;
|
|
236
210
|
yield* this.pathManager.close(clear);
|
|
237
211
|
return true;
|
|
@@ -23,13 +23,13 @@ import { HabitatRecord } from "../../core/records.js";
|
|
|
23
23
|
import { Roles } from "../../core/roles.js";
|
|
24
24
|
import { BasicReplyRouteHandler, Revery, Router } from "../../core/routing.js";
|
|
25
25
|
import { Schemes } from "../../core/schemes.js";
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
26
|
+
import { Baser } from "../../db/basing.js";
|
|
27
|
+
import { openOwner } from "../../db/core/store-owner.js";
|
|
28
|
+
import { Keeper, PreSit } from "../../db/keeping.js";
|
|
28
29
|
import { makeNowIso8601 } from "../../time/mod.js";
|
|
29
30
|
import { oobiReplyMessages } from "../bootstrap/oobi-replies.js";
|
|
30
31
|
import { loadStoredReply } from "../delivery/stored-replies.js";
|
|
31
32
|
import { acceptedGroupMembers, latestGroupContribution } from "../multisig/group-members.js";
|
|
32
|
-
import { createConfiger } from "./configing.js";
|
|
33
33
|
import { branToSaltQb64, encodeHugeNumber, ensureKeeperCryptoReady, Manager, normalizeSaltQb64, saltySigner, } from "./keeping.js";
|
|
34
34
|
/** Reserved alias for the local signatory habitat record. */
|
|
35
35
|
export const SIGNER = "__signatory__";
|
|
@@ -43,13 +43,16 @@ const KERI_V1 = Object.freeze({ major: 1, minor: 0 });
|
|
|
43
43
|
/**
|
|
44
44
|
* Select the KERI version for a new event on an existing identifier.
|
|
45
45
|
*
|
|
46
|
-
* An identifier
|
|
47
|
-
*
|
|
48
|
-
*
|
|
46
|
+
* An identifier follows the KERI version of its latest accepted event. An explicit
|
|
47
|
+
* selection that conflicts with it is refused rather than silently ignored, except
|
|
48
|
+
* for a deliberate upgrade rotation, which is how a v1 identifier moves up to v2.
|
|
49
|
+
* Stricter than KERIpy, whose per-event default can mix versions without being asked.
|
|
49
50
|
*/
|
|
50
|
-
function acceptedKelVersion(kever, requested) {
|
|
51
|
+
function acceptedKelVersion(kever, requested, { allowUpgrade = false } = {}) {
|
|
51
52
|
const accepted = kever.serder.pvrsn.major === 1 ? Vrsn_1_0 : Vrsn_2_0;
|
|
52
53
|
if (requested && (requested.major !== accepted.major || requested.minor !== accepted.minor)) {
|
|
54
|
+
if (allowUpgrade && requested.major > accepted.major)
|
|
55
|
+
return requested;
|
|
53
56
|
throw new ValidationError(`KEL of ${kever.prefixer.qb64} is KERI ${accepted.major}.${accepted.minor}; `
|
|
54
57
|
+ `refusing a KERI ${requested.major}.${requested.minor} event.`);
|
|
55
58
|
}
|
|
@@ -473,7 +476,7 @@ export class Hab {
|
|
|
473
476
|
if (!kever) {
|
|
474
477
|
throw new ValidationError(`Missing accepted key state for ${this.pre}.`);
|
|
475
478
|
}
|
|
476
|
-
const version = acceptedKelVersion(kever, args.version);
|
|
479
|
+
const version = acceptedKelVersion(kever, args.version, { allowUpgrade: true });
|
|
477
480
|
const priorSit = this.ks.getSits(this.pre);
|
|
478
481
|
if (!priorSit) {
|
|
479
482
|
throw new ValidationError(`Missing keeper state for ${this.pre}.`);
|
|
@@ -1077,7 +1080,7 @@ export class Signator {
|
|
|
1077
1080
|
*/
|
|
1078
1081
|
export class Habery {
|
|
1079
1082
|
/** Compose one habery from already-opened storage, manager, and config surfaces. */
|
|
1080
|
-
constructor(name, base, temp, headDirPath, compat, readonly, db, ks, mgr, cf, skipSignator = false) {
|
|
1083
|
+
constructor(name, base, temp, headDirPath, compat, readonly, db, ks, mgr, cf, skipSignator = false, opener, borrowsStores = false) {
|
|
1081
1084
|
Object.defineProperty(this, "name", {
|
|
1082
1085
|
enumerable: true,
|
|
1083
1086
|
configurable: true,
|
|
@@ -1114,6 +1117,19 @@ export class Habery {
|
|
|
1114
1117
|
writable: true,
|
|
1115
1118
|
value: void 0
|
|
1116
1119
|
});
|
|
1120
|
+
Object.defineProperty(this, "storeOpener", {
|
|
1121
|
+
enumerable: true,
|
|
1122
|
+
configurable: true,
|
|
1123
|
+
writable: true,
|
|
1124
|
+
value: void 0
|
|
1125
|
+
});
|
|
1126
|
+
/** True when `db` and `ks` were borrowed; their owner closes them. */
|
|
1127
|
+
Object.defineProperty(this, "borrowsStores", {
|
|
1128
|
+
enumerable: true,
|
|
1129
|
+
configurable: true,
|
|
1130
|
+
writable: true,
|
|
1131
|
+
value: void 0
|
|
1132
|
+
});
|
|
1117
1133
|
Object.defineProperty(this, "db", {
|
|
1118
1134
|
enumerable: true,
|
|
1119
1135
|
configurable: true,
|
|
@@ -1174,6 +1190,8 @@ export class Habery {
|
|
|
1174
1190
|
writable: true,
|
|
1175
1191
|
value: void 0
|
|
1176
1192
|
});
|
|
1193
|
+
this.storeOpener = opener;
|
|
1194
|
+
this.borrowsStores = borrowsStores;
|
|
1177
1195
|
this.name = name;
|
|
1178
1196
|
this.base = base;
|
|
1179
1197
|
this.temp = temp;
|
|
@@ -1688,10 +1706,20 @@ export class Habery {
|
|
|
1688
1706
|
this.habs.set(pre, hab);
|
|
1689
1707
|
return hab;
|
|
1690
1708
|
}
|
|
1691
|
-
/**
|
|
1709
|
+
/** Creates this Habery's sidecar stores. */
|
|
1710
|
+
get opener() {
|
|
1711
|
+
if (!this.storeOpener)
|
|
1712
|
+
throw new ValidationError("This Habery was given stores without an opener for sidecars.");
|
|
1713
|
+
return this.storeOpener;
|
|
1714
|
+
}
|
|
1715
|
+
/** Identity shared by this Habery's stores and sidecars. */
|
|
1716
|
+
storeIdentity() {
|
|
1717
|
+
return { name: this.name, base: this.base, temp: this.temp, reopen: true, readonly: this.readonly };
|
|
1718
|
+
}
|
|
1719
|
+
/** Closes owned backing databases and optionally clears temp storage. */
|
|
1692
1720
|
*close(clear = false) {
|
|
1693
1721
|
const failures = [];
|
|
1694
|
-
const closing = [this.db.close(clear), this.ks.close(clear)];
|
|
1722
|
+
const closing = this.borrowsStores ? [] : [this.db.close(clear), this.ks.close(clear)];
|
|
1695
1723
|
if (this.cf)
|
|
1696
1724
|
closing.push(this.cf.close(clear && this.temp));
|
|
1697
1725
|
for (const operation of closing) {
|
|
@@ -1726,38 +1754,29 @@ export function branToSeedAeid(bran) {
|
|
|
1726
1754
|
* The returned `Habery` immediately reconstructs its local habitat cache from
|
|
1727
1755
|
* durable DB state rather than depending on process-local creation history.
|
|
1728
1756
|
*/
|
|
1729
|
-
export function*
|
|
1730
|
-
const { name, base = "", temp = false, headDirPath, compat = false, readonly = false, cf: providedCf, skipConfig = false, skipSignator = false, bran, seed, aeid, salt, algo, } = args;
|
|
1757
|
+
export function* openHabery(args) {
|
|
1758
|
+
const { name, base = "", temp = false, headDirPath, compat = false, readonly = false, cf: providedCf, createConfig, skipConfig = false, skipSignator = false, opener, stores, bran, seed, aeid, salt, algo, } = args;
|
|
1731
1759
|
let db;
|
|
1732
1760
|
let ks;
|
|
1733
1761
|
let cf;
|
|
1734
1762
|
let delivered = false;
|
|
1735
1763
|
let failure;
|
|
1736
1764
|
try {
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
});
|
|
1746
|
-
ks = yield* createKeeper({
|
|
1747
|
-
name,
|
|
1748
|
-
base,
|
|
1749
|
-
temp,
|
|
1750
|
-
headDirPath,
|
|
1751
|
-
compat,
|
|
1752
|
-
reopen: true,
|
|
1753
|
-
readonly,
|
|
1754
|
-
});
|
|
1765
|
+
if (!opener && !stores)
|
|
1766
|
+
throw new ValidationError("A Habery needs a store opener or borrowed stores.");
|
|
1767
|
+
if (!providedCf && !skipConfig && !createConfig) {
|
|
1768
|
+
throw new ValidationError("A Habery needs a Configer, a Configer factory or skipConfig.");
|
|
1769
|
+
}
|
|
1770
|
+
const identity = { name, base, temp, reopen: true, readonly };
|
|
1771
|
+
db = stores?.db ?? (yield* openOwner(new Baser(opener.create(Baser.Family, identity)), "Baser", identity));
|
|
1772
|
+
ks = stores?.ks ?? (yield* openOwner(new Keeper(opener.create(Keeper.Family, identity)), "Keeper", identity));
|
|
1755
1773
|
cf = providedCf
|
|
1756
|
-
?? (skipConfig ? undefined : (yield*
|
|
1774
|
+
?? (skipConfig ? undefined : (yield* createConfig({
|
|
1757
1775
|
name,
|
|
1758
1776
|
base,
|
|
1759
1777
|
temp,
|
|
1760
1778
|
headDirPath,
|
|
1779
|
+
compat,
|
|
1761
1780
|
reopen: true,
|
|
1762
1781
|
clear: false,
|
|
1763
1782
|
})));
|
|
@@ -1779,7 +1798,7 @@ export function* createHabery(args) {
|
|
|
1779
1798
|
algo,
|
|
1780
1799
|
salt: normalizeSaltQb64(salt),
|
|
1781
1800
|
});
|
|
1782
|
-
const hby = new Habery(name, base, temp, headDirPath, compat, readonly, db, ks, mgr, cf, skipSignator);
|
|
1801
|
+
const hby = new Habery(name, base, temp, headDirPath, compat, readonly, db, ks, mgr, cf, skipSignator, opener, !!stores);
|
|
1783
1802
|
delivered = true;
|
|
1784
1803
|
return hby;
|
|
1785
1804
|
}
|
|
@@ -1796,9 +1815,9 @@ export function* createHabery(args) {
|
|
|
1796
1815
|
const closing = [];
|
|
1797
1816
|
if (cf && cf !== providedCf)
|
|
1798
1817
|
closing.push(cf.close());
|
|
1799
|
-
if (ks)
|
|
1818
|
+
if (ks && !stores)
|
|
1800
1819
|
closing.push(ks.close());
|
|
1801
|
-
if (db)
|
|
1820
|
+
if (db && !stores)
|
|
1802
1821
|
closing.push(db.close());
|
|
1803
1822
|
for (const operation of closing) {
|
|
1804
1823
|
try {
|
|
@@ -1195,7 +1195,7 @@ export function b64DecodeUrl(text) {
|
|
|
1195
1195
|
/**
|
|
1196
1196
|
* Backward-compatibility no-op for older app-layer startup seams.
|
|
1197
1197
|
*
|
|
1198
|
-
* CESR primitives now own
|
|
1198
|
+
* CESR primitives now own crypto backend readiness through their own module
|
|
1199
1199
|
* initialization, so higher layers no longer need an explicit keeper-crypto
|
|
1200
1200
|
* readiness step.
|
|
1201
1201
|
*/
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Default LMDB-backed `Habery` construction, kept apart so `openHabery` stays backend-neutral. */
|
|
2
|
+
import { LmdbStoreOpener } from "../../db/core/lmdb-opener.js";
|
|
3
|
+
import { createConfiger } from "./configing.js";
|
|
4
|
+
import { openHabery } from "./habbing.js";
|
|
5
|
+
/** Open a `Habery` on LMDB at its established paths, unless the caller supplies stores or an opener. */
|
|
6
|
+
export function* createHabery(args) {
|
|
7
|
+
return yield* openHabery({
|
|
8
|
+
opener: new LmdbStoreOpener({ headDirPath: args.headDirPath, compat: args.compat }),
|
|
9
|
+
createConfig: createConfiger,
|
|
10
|
+
...args,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Borrowed IPEX frame DAGs, negotiated disclosure paths and traversal policy. */
|
|
2
2
|
import { Compactor, makePather, SerderACDC } from "cesr-ts";
|
|
3
|
-
import {
|
|
3
|
+
import { walkAcdcGraph } from "../../acdc/chaining.js";
|
|
4
4
|
const nodeIlks = new Set([null, "acm", "ace", "act", "acg"]);
|
|
5
5
|
/** Empty UUID marks field-map metadata; fixed-field public credentials keep that slot empty too. */
|
|
6
6
|
export function isIpexMetadata(node) {
|
|
@@ -58,15 +58,15 @@ export function singleDagDisclosurePlan(value) {
|
|
|
58
58
|
return Array.isArray(value) && value.length === 1 && validDisclosurePlan(value[0]) ? value[0] : null;
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
-
* Index unique disclosed credential
|
|
62
|
-
* Offers
|
|
61
|
+
* Index unique disclosed credential frames, then delegate the graph walk to `walkAcdcGraph`.
|
|
62
|
+
* Offers always walk open; Grants use the caller's walk policy. Nested ownership
|
|
63
63
|
* does not make these nodes independently accepted runtime messages.
|
|
64
64
|
*/
|
|
65
|
-
export function walkIpexGraph(origin, nests,
|
|
65
|
+
export function walkIpexGraph(origin, nests, walk) {
|
|
66
66
|
const nodes = new Map();
|
|
67
67
|
for (const [index, frame] of nests.entries()) {
|
|
68
68
|
const body = frame.body;
|
|
69
|
-
if (!(body instanceof SerderACDC) || !
|
|
69
|
+
if (!(body instanceof SerderACDC) || !nodeIlks.has(body.ilk)
|
|
70
70
|
|| !body.said || (index === 0 && body.said !== origin) || nodes.has(body.said))
|
|
71
71
|
return null;
|
|
72
72
|
// Descendants are not additional implicit evidence for this disclosed node.
|
|
@@ -74,71 +74,8 @@ export function walkIpexGraph(origin, nests, closed) {
|
|
|
74
74
|
return null;
|
|
75
75
|
nodes.set(body.said, frame);
|
|
76
76
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const seen = new Set();
|
|
80
|
-
const order = [];
|
|
81
|
-
const dependencies = new Map();
|
|
82
|
-
const queue = [origin];
|
|
83
|
-
for (let index = 0; index < queue.length; index++) {
|
|
84
|
-
const said = queue[index];
|
|
85
|
-
if (seen.has(said))
|
|
86
|
-
continue;
|
|
87
|
-
seen.add(said);
|
|
88
|
-
order.push(said);
|
|
89
|
-
const farNodes = new Set();
|
|
90
|
-
dependencies.set(said, farNodes);
|
|
91
|
-
const edges = blocks(nodes.get(said).body.sad.e);
|
|
92
|
-
if (!edges)
|
|
93
|
-
return null;
|
|
94
|
-
const groups = [...edges];
|
|
95
|
-
for (let g = 0; g < groups.length; g++) {
|
|
96
|
-
const edge = groups[g];
|
|
97
|
-
const target = acdcEdgeTarget(edge);
|
|
98
|
-
if (target === false)
|
|
99
|
-
return null;
|
|
100
|
-
if (typeof target === "string") {
|
|
101
|
-
if (!nodes.has(target)) {
|
|
102
|
-
if (closed)
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
farNodes.add(target);
|
|
107
|
-
if (!seen.has(target))
|
|
108
|
-
queue.push(target);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
if (!record(edge))
|
|
113
|
-
return null;
|
|
114
|
-
for (const [key, value] of Object.entries(edge)) {
|
|
115
|
-
if (acdcGroupLabels.has(key) || typeof value === "string")
|
|
116
|
-
continue;
|
|
117
|
-
groups.push(value);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
if (seen.size !== nodes.size)
|
|
123
|
-
return null;
|
|
124
|
-
const parents = new Map();
|
|
125
|
-
for (const [near, children] of dependencies) {
|
|
126
|
-
for (const far of children) {
|
|
127
|
-
if (!parents.has(far))
|
|
128
|
-
parents.set(far, new Set());
|
|
129
|
-
parents.get(far).add(near);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
const dependencyOrder = order.filter((said) => dependencies.get(said).size === 0);
|
|
133
|
-
for (let i = 0; i < dependencyOrder.length; i++) {
|
|
134
|
-
for (const near of parents.get(dependencyOrder[i]) ?? []) {
|
|
135
|
-
const children = dependencies.get(near);
|
|
136
|
-
children.delete(dependencyOrder[i]);
|
|
137
|
-
if (!children.size)
|
|
138
|
-
dependencyOrder.push(near);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return dependencyOrder.length === nodes.size ? { nodes, order } : null;
|
|
77
|
+
const order = walkAcdcGraph(origin, nodes, walk);
|
|
78
|
+
return order ? { nodes, order, walk } : null;
|
|
142
79
|
}
|
|
143
80
|
/** Compare SAD values structurally while retaining list order; map insertion order is not semantic here. */
|
|
144
81
|
function equal(a, b) {
|
|
@@ -29,10 +29,11 @@ import { collectBytes } from "../transport/byte-source.js";
|
|
|
29
29
|
import { credentialGrantReady, credentialPresentationSupportMessages, credentialSaidFromGrant, validateAdmitGrant, } from "./ipex-credentialing.js";
|
|
30
30
|
import { walkIpexGraph } from "./ipex-graph.js";
|
|
31
31
|
import { authenticateIpexNode, issuedNodeVerdict } from "./ipex-node-authentication.js";
|
|
32
|
+
import { ipexGrantWalk } from "./ipex-v2.js";
|
|
32
33
|
import { IPEX_ADMIT_ROUTE, IPEX_GRANT_ROUTE, ipexConversationReady, ipexRecipient } from "./ipexing.js";
|
|
33
34
|
/** Authenticate the exact disclosed graph; only the existing evaluator's explicit true authorizes new use. */
|
|
34
|
-
function acdcV2GraphUse(hby, registry, origin, nests) {
|
|
35
|
-
const graph = walkIpexGraph(origin, nests,
|
|
35
|
+
function acdcV2GraphUse(hby, registry, origin, nests, walk) {
|
|
36
|
+
const graph = walkIpexGraph(origin, nests, walk);
|
|
36
37
|
if (!graph)
|
|
37
38
|
throw new ValidationError("ACDC v2 group graph is malformed or incomplete.");
|
|
38
39
|
const verdicts = new Map();
|
|
@@ -55,7 +56,7 @@ function acdcV2GrantUse(hby, exchanger, registry, said) {
|
|
|
55
56
|
if (!Array.isArray(origins) || origins.length !== 1 || typeof origins[0] !== "string") {
|
|
56
57
|
throw new ValidationError("ACDC v2 group Grant requires one origin.");
|
|
57
58
|
}
|
|
58
|
-
return acdcV2GraphUse(hby, registry, origins[0], loadNests(hby.db, said));
|
|
59
|
+
return acdcV2GraphUse(hby, registry, origins[0], loadNests(hby.db, said), ipexGrantWalk(exchanger));
|
|
59
60
|
}
|
|
60
61
|
/** Recheck current graph authorization at an accepted group's new delivery, output or consent action. */
|
|
61
62
|
export function requireAcdcV2GroupUse(hby, protocol, embedded) {
|
|
@@ -110,8 +111,10 @@ export function* prepareAcdcV2GroupIpex(hby, protocol, group, raw) {
|
|
|
110
111
|
if (!Array.isArray(origins) || origins.length !== 1 || typeof origins[0] !== "string") {
|
|
111
112
|
throw new ValidationError("ACDC v2 group Grant requires one origin.");
|
|
112
113
|
}
|
|
113
|
-
|
|
114
|
+
const walk = ipexGrantWalk(protocol.exc);
|
|
115
|
+
if (acdcV2GraphUse(hby, protocol.registry?.store ?? null, origins[0], frame.nests ?? [], walk) !== true) {
|
|
114
116
|
return null;
|
|
117
|
+
}
|
|
115
118
|
}
|
|
116
119
|
else if (embedded.route === IPEX_ADMIT_ROUTE) {
|
|
117
120
|
if (typeof embedded.sad.p !== "string"
|
|
@@ -353,7 +356,7 @@ function* prepareGroupIpexMessages(hby, protocol, groupHab, embedded, childGvrsn
|
|
|
353
356
|
if (child.route === IPEX_GRANT_ROUTE) {
|
|
354
357
|
const origins = child.sad.a.o;
|
|
355
358
|
if (!Array.isArray(origins) || origins.length !== 1 || typeof origins[0] !== "string"
|
|
356
|
-
|| acdcV2GraphUse(hby, protocol.registry?.store ?? null, origins[0], childFrame.nests ?? []) !== true) {
|
|
359
|
+
|| acdcV2GraphUse(hby, protocol.registry?.store ?? null, origins[0], childFrame.nests ?? [], ipexGrantWalk(protocol.exc)) !== true) {
|
|
357
360
|
throw new ValidationError("ACDC v2 group graph is unavailable before proposal publication.");
|
|
358
361
|
}
|
|
359
362
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IPEX_V2_PREDECESSORS, isIpexVerb, nestedIpexRoute, } from "../../core/exchange/protocol-exchanging.js";
|
|
2
2
|
/** V2 IPEX route policy; v1 routing remains independently registered. */
|
|
3
3
|
import { Diger, ParserError, Prefixer, } from "cesr-ts";
|
|
4
|
-
import { evaluateChain } from "../../acdc/chaining.js";
|
|
4
|
+
import { DEFAULT_GRANT_WALK, evaluateChain } from "../../acdc/chaining.js";
|
|
5
5
|
import { validateUpdate, verifyRegistryAnchor, vet, vetBinds, vetBlind, vetBound, } from "../../acdc/regeventing.js";
|
|
6
6
|
import { validateSchema } from "../../acdc/scheming.js";
|
|
7
7
|
import { DatabaseOperationError } from "../../core/errors.js";
|
|
@@ -31,9 +31,11 @@ function missing(reason) {
|
|
|
31
31
|
* Authenticate each disclosed node independently before Exchanger persists an EXN.
|
|
32
32
|
* Registry evidence is caller-owned; notifier delivery follows durable acceptance.
|
|
33
33
|
* Presentation registries require the retained receiver receipt and node-local proofs.
|
|
34
|
+
* `grantWalk` selects how a Grant treats an undisclosed far node (`AcdcWalkPolicy`);
|
|
35
|
+
* a far node the disclosure plan selects but the Grant does not nest always refuses.
|
|
34
36
|
*/
|
|
35
37
|
export class IpexV2Handler {
|
|
36
|
-
constructor(resource, hby, notifier = null, registry = null) {
|
|
38
|
+
constructor(resource, hby, notifier = null, registry = null, grantWalk = DEFAULT_GRANT_WALK) {
|
|
37
39
|
Object.defineProperty(this, "resource", {
|
|
38
40
|
enumerable: true,
|
|
39
41
|
configurable: true,
|
|
@@ -58,6 +60,12 @@ export class IpexV2Handler {
|
|
|
58
60
|
writable: true,
|
|
59
61
|
value: registry
|
|
60
62
|
});
|
|
63
|
+
Object.defineProperty(this, "grantWalk", {
|
|
64
|
+
enumerable: true,
|
|
65
|
+
configurable: true,
|
|
66
|
+
writable: true,
|
|
67
|
+
value: grantWalk
|
|
68
|
+
});
|
|
61
69
|
Object.defineProperty(this, "protocolMajor", {
|
|
62
70
|
enumerable: true,
|
|
63
71
|
configurable: true,
|
|
@@ -266,7 +274,7 @@ export class IpexV2Handler {
|
|
|
266
274
|
if (verb === "offer" && nests.length) {
|
|
267
275
|
if (nests.some(hasIpexNodeAttachments))
|
|
268
276
|
return false;
|
|
269
|
-
const graph = walkIpexGraph(attrs.o[0], nests,
|
|
277
|
+
const graph = walkIpexGraph(attrs.o[0], nests, "open");
|
|
270
278
|
return graph ? this.nodeSchemas(graph) : false;
|
|
271
279
|
}
|
|
272
280
|
if (verb !== "grant")
|
|
@@ -287,7 +295,7 @@ export class IpexV2Handler {
|
|
|
287
295
|
if (!single(attrs.o, "string") || !this.validOrigin(attrs.o[0]) || !nests.length)
|
|
288
296
|
return false;
|
|
289
297
|
const origin = attrs.o[0];
|
|
290
|
-
const graph = walkIpexGraph(origin, nests,
|
|
298
|
+
const graph = walkIpexGraph(origin, nests, this.grantWalk);
|
|
291
299
|
if (!graph || [...graph.nodes.values()].some((node) => isIpexMetadata(node.body)))
|
|
292
300
|
return false;
|
|
293
301
|
if (!verifyIpexDisclosure(plan, origin, graph))
|
|
@@ -492,7 +500,7 @@ export class IpexV2Handler {
|
|
|
492
500
|
const nests = loadNests(this.hby.db, offerSaid);
|
|
493
501
|
if (!nests.length)
|
|
494
502
|
return missing(`Missing metadata ACDC for accepted Offer ${offerSaid}.`);
|
|
495
|
-
const offered = walkIpexGraph(offeredOrigin, nests,
|
|
503
|
+
const offered = walkIpexGraph(offeredOrigin, nests, "open");
|
|
496
504
|
if (!offered)
|
|
497
505
|
return false;
|
|
498
506
|
const metadata = offered.nodes.get(offeredOrigin).body;
|
|
@@ -690,3 +698,11 @@ export class IpexV2Handler {
|
|
|
690
698
|
return [[issuee, regid]];
|
|
691
699
|
}
|
|
692
700
|
}
|
|
701
|
+
/**
|
|
702
|
+
* The Grant walk policy of the exchanger's v2 Grant owner. Later use of an
|
|
703
|
+
* accepted Grant re-walks it under this policy so reuse agrees with admission.
|
|
704
|
+
*/
|
|
705
|
+
export function ipexGrantWalk(exchanger) {
|
|
706
|
+
const handler = exchanger.routeHandler("/ipex/grant", 2);
|
|
707
|
+
return handler instanceof IpexV2Handler ? handler.grantWalk : DEFAULT_GRANT_WALK;
|
|
708
|
+
}
|
|
@@ -111,7 +111,7 @@ export class IpexHandler {
|
|
|
111
111
|
export function loadIpexHandlers(hby, exchanger, options = {}) {
|
|
112
112
|
for (const route of IPEX_ROUTES) {
|
|
113
113
|
exchanger.addHandler(new IpexHandler(route, hby, options.notifier ?? null));
|
|
114
|
-
exchanger.addHandler(new IpexV2Handler(route, hby, options.notifier ?? null, options.registry ?? null));
|
|
114
|
+
exchanger.addHandler(new IpexV2Handler(route, hby, options.notifier ?? null, options.registry ?? null, options.grantWalk));
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
/** Apply for an ACDC. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TopicsRecord } from "../../core/records.js";
|
|
2
2
|
import { Roles } from "../../core/roles.js";
|
|
3
|
-
import {
|
|
3
|
+
import { openOwner } from "../../db/core/store-owner.js";
|
|
4
|
+
import { Mailboxer } from "../../db/mailbox/mailboxing.js";
|
|
4
5
|
/**
|
|
5
6
|
* Derive mailbox open options from one existing habery.
|
|
6
7
|
*
|
|
@@ -13,13 +14,7 @@ import { createMailboxer } from "../../db/mailbox/mailboxing.js";
|
|
|
13
14
|
*/
|
|
14
15
|
export function mailboxerOptionsForHabery(hby, options = {}) {
|
|
15
16
|
return {
|
|
16
|
-
|
|
17
|
-
base: hby.base,
|
|
18
|
-
temp: hby.temp,
|
|
19
|
-
headDirPath: hby.headDirPath,
|
|
20
|
-
compat: hby.compat,
|
|
21
|
-
readonly: hby.readonly,
|
|
22
|
-
reopen: true,
|
|
17
|
+
...hby.storeIdentity(),
|
|
23
18
|
...options,
|
|
24
19
|
};
|
|
25
20
|
}
|
|
@@ -35,7 +30,8 @@ export function mailboxerOptionsForHabery(hby, options = {}) {
|
|
|
35
30
|
* @returns Provider sidecar whose acquisition/lifetime belongs to the caller scope.
|
|
36
31
|
*/
|
|
37
32
|
export function* openMailboxerForHabery(hby, options = {}) {
|
|
38
|
-
|
|
33
|
+
const identity = mailboxerOptionsForHabery(hby, options);
|
|
34
|
+
return yield* openOwner(new Mailboxer(hby.opener.create(Mailboxer.Family, identity)), "Mailboxer", identity);
|
|
39
35
|
}
|
|
40
36
|
/**
|
|
41
37
|
* Build the stored mailbox topic key used by KERIpy-style mailbox storage.
|
|
@@ -64,6 +64,20 @@ export function groupWitnesserSelection(db, group, { sn, said }) {
|
|
|
64
64
|
}
|
|
65
65
|
return null;
|
|
66
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Return the current signing member elected by `coordinator`, as KERIpy
|
|
69
|
+
* `GroupHab.elected`: the member whose latest contribution to the coordinator's
|
|
70
|
+
* establishment keys holds the lowest verified signing index. Null when the
|
|
71
|
+
* event has no election or that contributor is no longer a current signing
|
|
72
|
+
* member. The result depends on locally stored signatures, so it suits
|
|
73
|
+
* idempotent duties only; frozen operations recheck their earlier choice instead.
|
|
74
|
+
*/
|
|
75
|
+
export function groupElectedMember(hby, group, coordinator) {
|
|
76
|
+
const selection = groupWitnesserSelection(hby.db, group, coordinator);
|
|
77
|
+
if (!selection)
|
|
78
|
+
return null;
|
|
79
|
+
return groupSigningMembers(hby, group).find(member => latestGroupContribution(hby.db, member, selection.establishment.verfers)?.index === selection.index) ?? null;
|
|
80
|
+
}
|
|
67
81
|
/** Return current group signing member AIDs in signing-index order. */
|
|
68
82
|
export function groupSigningMembers(hby, groupPre) {
|
|
69
83
|
const stored = hby.ks.getSmids(groupPre).map((tuple) => tuple[0].qb64);
|
|
@@ -304,8 +304,9 @@ export function* prepareMultisigEventExn(sender, proposal, wire, options = {}) {
|
|
|
304
304
|
// Keep the route selection stable through parser suspension; attribute values remain immutable borrows.
|
|
305
305
|
const captured = { ...proposal };
|
|
306
306
|
const { route, attrs } = captured;
|
|
307
|
-
// KERIpy `kli multisig incept|interact
|
|
308
|
-
//
|
|
307
|
+
// KERIpy `kli multisig incept|interact` and `ends add` send these routes as v1 `e`-embed
|
|
308
|
+
// wrappers whatever the group KEL version. `kli multisig rotate --version 2.0` sends a v2
|
|
309
|
+
// nested wrapper, and `kli multisig join` replies in its proposal's form, as approvals here do.
|
|
309
310
|
const keripyEmbedRoute = KERIPY_EMBED_PROPOSAL_ROUTES.includes(route);
|
|
310
311
|
const version = options.pvrsn ?? options.version ?? (keripyEmbedRoute ? Vrsn_1_0 : Vrsn_2_0);
|
|
311
312
|
const field = route.slice(route.lastIndexOf("/") + 1);
|
|
@@ -547,7 +548,7 @@ export class Multiplexor {
|
|
|
547
548
|
if (this.isLocalHab(sender))
|
|
548
549
|
yield* this.processApproved(nests);
|
|
549
550
|
}
|
|
550
|
-
const { existing, submitters } = this.hby.db.
|
|
551
|
+
const { existing, submitters } = this.hby.db.transaction(() => {
|
|
551
552
|
const indexed = this.hby.db.meids.get([embeddedSaid]);
|
|
552
553
|
const existing = isV2RegistryRoute(route) || v2Ipex
|
|
553
554
|
? indexed.filter(diger => {
|
|
@@ -152,9 +152,10 @@ export function* publishAcdcV2Registry(hby, postman, group, approval) {
|
|
|
152
152
|
* @param proposal Route-correlated group proposal with its named business fields.
|
|
153
153
|
* @param embeddedMessage Signed child wire to include under the route-derived label.
|
|
154
154
|
* @param childGvrsn Optional explicit attachment genus for the child.
|
|
155
|
+
* @param wrapperVersion Optional wrapper protocol version; an approval mirrors its proposal's.
|
|
155
156
|
* @returns Stable proposal/wrapper identities and completed deliveries, independent of group acceptance.
|
|
156
157
|
*/
|
|
157
|
-
export function* publishProposal(hby, protocol, postman, member, recipients, proposal, embeddedMessage, childGvrsn) {
|
|
158
|
+
export function* publishProposal(hby, protocol, postman, member, recipients, proposal, embeddedMessage, childGvrsn, wrapperVersion) {
|
|
158
159
|
const input = new Reactor(protocol);
|
|
159
160
|
const outcomes = [];
|
|
160
161
|
for (const recipient of remoteGroupMembers(hby, member, recipients)) {
|
|
@@ -162,6 +163,7 @@ export function* publishProposal(hby, protocol, postman, member, recipients, pro
|
|
|
162
163
|
const prepared = yield* prepareMultisigEventExn(member.pre, proposal, embeddedMessage, {
|
|
163
164
|
recipient: destination,
|
|
164
165
|
childGvrsn,
|
|
166
|
+
...(wrapperVersion ? { pvrsn: wrapperVersion } : {}),
|
|
165
167
|
});
|
|
166
168
|
const signed = yield* prepareGroupMessage(protocol.exc, member, destination, prepared);
|
|
167
169
|
outcomes.push(yield* admitAndSendGroupMessage(input, postman, signed));
|
|
@@ -444,7 +446,10 @@ function* approveKelProposal(hby, runtime, exn, route, options) {
|
|
|
444
446
|
yield* runtime.reactor.processBytes(concatBytes(Counter.makeGVC(approval.genus), localMessage), { local: true });
|
|
445
447
|
yield* runtime.reactor.processBytes(concatBytes(Counter.makeGVC(approval.genus), serder.raw, approval.attachment), { local: true });
|
|
446
448
|
yield* runtime.protocol.processEscrowsOnce();
|
|
447
|
-
const publication = yield* publishProposal(hby, runtime.protocol, runtime.postman, member, members, proposal, localMessage, approval.genus
|
|
449
|
+
const publication = yield* publishProposal(hby, runtime.protocol, runtime.postman, member, members, proposal, localMessage, approval.genus,
|
|
450
|
+
// KERIpy indexes contributions by wrapper form (v1 `e` SAID, v2 child SAID), so an
|
|
451
|
+
// approval must reuse its proposal's wrapper version for the proposer to merge it.
|
|
452
|
+
exn.pvrsn);
|
|
448
453
|
const accepted = eventAccepted(hby, serder);
|
|
449
454
|
if (proposal.route !== MULTISIG_IXN_ROUTE) {
|
|
450
455
|
commitAcceptedGroupMembers(hby, serder, smids, proposal.attrs.rmids);
|