keri-ts 2.1.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -2
- package/esm/keri/npm/src/acdc/authoring.js +195 -0
- package/esm/keri/npm/src/acdc/custody.js +187 -0
- package/esm/keri/npm/src/acdc/dhking.js +244 -32
- package/esm/keri/npm/src/acdc/regbasing.js +10 -0
- package/esm/keri/npm/src/acdc/salting.js +16 -1
- package/esm/keri/npm/src/acdc/scheming.js +93 -54
- package/esm/keri/npm/src/acdc/unblinding.js +118 -95
- package/esm/keri/npm/src/app/bootstrap/authenticating.js +4 -6
- package/esm/keri/npm/src/app/bootstrap/oobi-resolving.js +41 -0
- package/esm/keri/npm/src/app/bootstrap/oobiery.js +4 -6
- package/esm/keri/npm/src/app/credentials/credential-revoking.js +1 -0
- package/esm/keri/npm/src/app/credentials/credential-workflows.js +2 -0
- package/esm/keri/npm/src/app/credentials/registry-settling.js +44 -0
- package/esm/keri/npm/src/app/credentials/root-replicating.js +68 -60
- package/esm/keri/npm/src/app/credentials/root-replicator.js +198 -0
- package/esm/keri/npm/src/app/credentials/tel-completion.js +36 -0
- package/esm/keri/npm/src/app/delivery/forwarding.js +16 -3
- package/esm/keri/npm/src/app/exchanges/exchanging.js +14 -4
- package/esm/keri/npm/src/app/identity/challenging.js +50 -0
- package/esm/keri/npm/src/app/identity/delegating.js +77 -77
- package/esm/keri/npm/src/app/identity/delegation-approval.js +333 -0
- package/esm/keri/npm/src/app/identity/event-completion.js +154 -0
- package/esm/keri/npm/src/app/identity/habbing.js +129 -6
- package/esm/keri/npm/src/app/identity/keeping.js +77 -4
- package/esm/keri/npm/src/app/ipex/group-ipex.js +341 -0
- package/esm/keri/npm/src/app/ipex/group-issuance.js +905 -0
- package/esm/keri/npm/src/app/ipex/ipex-admitting.js +120 -0
- package/esm/keri/npm/src/app/ipex/ipex-conversation.js +197 -0
- package/esm/keri/npm/src/app/ipex/ipex-discloser.js +591 -0
- package/esm/keri/npm/src/app/ipex/ipex-granting.js +93 -0
- package/esm/keri/npm/src/app/ipex/ipex-grouping.js +50 -19
- package/esm/keri/npm/src/app/ipex/ipex-node-authentication.js +42 -18
- package/esm/keri/npm/src/app/ipex/issuance.js +896 -0
- package/esm/keri/npm/src/app/ipex/pending-presentations.js +46 -0
- package/esm/keri/npm/src/app/ipex/presentation-files.js +200 -0
- package/esm/keri/npm/src/app/ipex/presenting.js +408 -0
- package/esm/keri/npm/src/app/ipex/receive-issuance.js +86 -0
- package/esm/keri/npm/src/app/ipex/unblinding-workflow.js +667 -0
- package/esm/keri/npm/src/app/mailbox/ipex-arrival.js +103 -0
- package/esm/keri/npm/src/app/mailbox/kel-publisher.js +322 -0
- package/esm/keri/npm/src/app/mailbox/kel-publishing.js +65 -0
- package/esm/keri/npm/src/app/mailbox/kel-submission.js +24 -0
- package/esm/keri/npm/src/app/mailbox/mailbox-admin.js +208 -0
- package/esm/keri/npm/src/app/mailbox/mailbox-poller.js +212 -47
- package/esm/keri/npm/src/app/mailbox/mailboxing.js +10 -5
- package/esm/keri/npm/src/app/multisig/counseling.js +488 -0
- package/esm/keri/npm/src/app/multisig/group-members.js +18 -0
- package/esm/keri/npm/src/app/multisig/multisig-messaging.js +33 -6
- package/esm/keri/npm/src/app/multisig/multisig-workflows.js +98 -147
- package/esm/keri/npm/src/app/multisig/proposals.js +281 -0
- package/esm/keri/npm/src/app/multisig/proposing.js +122 -0
- package/esm/keri/npm/src/app/notifications/signaling.js +5 -5
- package/esm/keri/npm/src/app/protocol/parsering.js +26 -1
- package/esm/keri/npm/src/app/protocol/protocol-processing.js +9 -3
- package/esm/keri/npm/src/app/queries/query-workflows.js +98 -0
- package/esm/keri/npm/src/app/runtime/agent-runtime.js +106 -55
- package/esm/keri/npm/src/app/runtime/cue-runtime.js +3 -6
- package/esm/keri/npm/src/app/runtime/delivery-outbox.js +87 -0
- package/esm/keri/npm/src/app/runtime/doing.js +17 -0
- package/esm/keri/npm/src/app/runtime/ipex-auxiliaries.js +207 -0
- package/esm/keri/npm/src/app/runtime/operation-owners.js +151 -0
- package/esm/keri/npm/src/app/runtime/retry-backoff.js +93 -0
- package/esm/keri/npm/src/app/runtime/workflow-contract.js +80 -0
- package/esm/keri/npm/src/app/transport/http-client.js +25 -6
- package/esm/keri/npm/src/app/witness/http-endpoints.js +4 -4
- package/esm/keri/npm/src/cli/common/event-completion.js +49 -0
- package/esm/keri/npm/src/cli/common/runtime-workers.js +23 -0
- package/esm/keri/npm/src/cli/credentials/ipex.js +164 -191
- package/esm/keri/npm/src/cli/credentials/vc.js +53 -72
- package/esm/keri/npm/src/cli/endpoints/did.js +12 -3
- package/esm/keri/npm/src/cli/endpoints/oobi.js +10 -13
- package/esm/keri/npm/src/cli/identity/challenge.js +8 -34
- package/esm/keri/npm/src/cli/identity/delegate.js +81 -258
- package/esm/keri/npm/src/cli/identity/incept.js +15 -32
- package/esm/keri/npm/src/cli/identity/interact.js +5 -17
- package/esm/keri/npm/src/cli/identity/rotate.js +8 -36
- package/esm/keri/npm/src/cli/index.js +3 -1
- package/esm/keri/npm/src/cli/messaging/group-join.js +83 -0
- package/esm/keri/npm/src/cli/messaging/group-wait.js +88 -0
- package/esm/keri/npm/src/cli/messaging/multisig.js +190 -285
- package/esm/keri/npm/src/cli/messaging/root-copy-lines.js +31 -0
- package/esm/keri/npm/src/core/kel/eventing.js +66 -10
- package/esm/keri/npm/src/core/mailbox/kram-policy.js +39 -6
- package/esm/keri/npm/src/core/mailbox/kraming.js +2 -0
- package/esm/keri/npm/src/core/records.js +23 -0
- package/esm/keri/npm/src/core/routing.js +13 -0
- package/esm/keri/npm/src/db/basing.js +34 -2
- package/esm/keri/npm/src/db/core/indexeddb-persistence.js +221 -0
- package/esm/keri/npm/src/db/indexeddb.js +98 -0
- package/esm/keri/npm/src/db/keeping.js +11 -2
- package/esm/keri/npm/src/db/store-lock.js +150 -0
- package/esm/keri/npm/src/npm/db-indexeddb.browser.js +2 -0
- package/esm/keri/npm/src/npm/db-indexeddb.js +3 -0
- package/esm/keri/npm/src/npm/db.browser.js +2 -0
- package/esm/keri/npm/src/npm/index.browser.js +9 -0
- package/esm/keri/npm/src/npm/runtime-web.browser.js +2 -0
- package/esm/keri/npm/src/npm/runtime-web.js +3 -0
- package/esm/keri/npm/src/npm/runtime.browser.js +2 -0
- package/esm/keri/npm/src/runtime/index.js +51 -4
- package/esm/keri/npm/src/runtime/web/output-barrier.js +47 -0
- package/esm/keri/npm/src/runtime/web/persistent-storage.js +37 -0
- package/esm/keri/npm/src/runtime/web.js +10 -0
- package/esm/keri/npm/src/vdr/tel-publication.js +16 -0
- package/esm/keri/npm/src/version.js +2 -2
- package/package.json +15 -2
- package/types/acdc/authoring.d.ts +54 -0
- package/types/acdc/authoring.d.ts.map +1 -0
- package/types/acdc/custody.d.ts +84 -0
- package/types/acdc/custody.d.ts.map +1 -0
- package/types/acdc/dhking.d.ts +94 -3
- package/types/acdc/dhking.d.ts.map +1 -1
- package/types/acdc/regbasing.d.ts +4 -0
- package/types/acdc/regbasing.d.ts.map +1 -1
- package/types/acdc/salting.d.ts +6 -1
- package/types/acdc/salting.d.ts.map +1 -1
- package/types/acdc/scheming.d.ts +2 -0
- package/types/acdc/scheming.d.ts.map +1 -1
- package/types/acdc/unblinding.d.ts +58 -19
- package/types/acdc/unblinding.d.ts.map +1 -1
- package/types/app/bootstrap/authenticating.d.ts +3 -1
- package/types/app/bootstrap/authenticating.d.ts.map +1 -1
- package/types/app/bootstrap/oobi-resolving.d.ts +92 -0
- package/types/app/bootstrap/oobi-resolving.d.ts.map +1 -0
- package/types/app/bootstrap/oobiery.d.ts +3 -1
- package/types/app/bootstrap/oobiery.d.ts.map +1 -1
- package/types/app/credentials/credential-revoking.d.ts +3 -0
- package/types/app/credentials/credential-revoking.d.ts.map +1 -1
- package/types/app/credentials/credential-workflows.d.ts +5 -0
- package/types/app/credentials/credential-workflows.d.ts.map +1 -1
- package/types/app/credentials/registry-settling.d.ts +85 -0
- package/types/app/credentials/registry-settling.d.ts.map +1 -0
- package/types/app/credentials/root-replicating.d.ts +56 -44
- package/types/app/credentials/root-replicating.d.ts.map +1 -1
- package/types/app/credentials/root-replicator.d.ts +105 -0
- package/types/app/credentials/root-replicator.d.ts.map +1 -0
- package/types/app/credentials/tel-completion.d.ts +55 -0
- package/types/app/credentials/tel-completion.d.ts.map +1 -0
- package/types/app/delivery/forwarding.d.ts +6 -0
- package/types/app/delivery/forwarding.d.ts.map +1 -1
- package/types/app/exchanges/exchanging.d.ts.map +1 -1
- package/types/app/identity/challenging.d.ts +54 -0
- package/types/app/identity/challenging.d.ts.map +1 -1
- package/types/app/identity/delegating.d.ts +21 -4
- package/types/app/identity/delegating.d.ts.map +1 -1
- package/types/app/identity/delegation-approval.d.ts +228 -0
- package/types/app/identity/delegation-approval.d.ts.map +1 -0
- package/types/app/identity/event-completion.d.ts +151 -0
- package/types/app/identity/event-completion.d.ts.map +1 -0
- package/types/app/identity/habbing.d.ts +67 -2
- package/types/app/identity/habbing.d.ts.map +1 -1
- package/types/app/identity/keeping.d.ts +49 -3
- package/types/app/identity/keeping.d.ts.map +1 -1
- package/types/app/ipex/group-ipex.d.ts +254 -0
- package/types/app/ipex/group-ipex.d.ts.map +1 -0
- package/types/app/ipex/group-issuance.d.ts +281 -0
- package/types/app/ipex/group-issuance.d.ts.map +1 -0
- package/types/app/ipex/ipex-admitting.d.ts +47 -0
- package/types/app/ipex/ipex-admitting.d.ts.map +1 -0
- package/types/app/ipex/ipex-conversation.d.ts +195 -0
- package/types/app/ipex/ipex-conversation.d.ts.map +1 -0
- package/types/app/ipex/ipex-discloser.d.ts +156 -0
- package/types/app/ipex/ipex-discloser.d.ts.map +1 -0
- package/types/app/ipex/ipex-granting.d.ts +145 -0
- package/types/app/ipex/ipex-granting.d.ts.map +1 -0
- package/types/app/ipex/ipex-grouping.d.ts +18 -0
- package/types/app/ipex/ipex-grouping.d.ts.map +1 -1
- package/types/app/ipex/ipex-node-authentication.d.ts +9 -1
- package/types/app/ipex/ipex-node-authentication.d.ts.map +1 -1
- package/types/app/ipex/issuance.d.ts +445 -0
- package/types/app/ipex/issuance.d.ts.map +1 -0
- package/types/app/ipex/pending-presentations.d.ts +25 -0
- package/types/app/ipex/pending-presentations.d.ts.map +1 -0
- package/types/app/ipex/presentation-files.d.ts +47 -0
- package/types/app/ipex/presentation-files.d.ts.map +1 -0
- package/types/app/ipex/presenting.d.ts +300 -0
- package/types/app/ipex/presenting.d.ts.map +1 -0
- package/types/app/ipex/receive-issuance.d.ts +99 -0
- package/types/app/ipex/receive-issuance.d.ts.map +1 -0
- package/types/app/ipex/unblinding-workflow.d.ts +257 -0
- package/types/app/ipex/unblinding-workflow.d.ts.map +1 -0
- package/types/app/mailbox/ipex-arrival.d.ts +104 -0
- package/types/app/mailbox/ipex-arrival.d.ts.map +1 -0
- package/types/app/mailbox/kel-publisher.d.ts +141 -0
- package/types/app/mailbox/kel-publisher.d.ts.map +1 -0
- package/types/app/mailbox/kel-publishing.d.ts +70 -0
- package/types/app/mailbox/kel-publishing.d.ts.map +1 -0
- package/types/app/mailbox/kel-submission.d.ts +18 -0
- package/types/app/mailbox/kel-submission.d.ts.map +1 -0
- package/types/app/mailbox/mailbox-admin.d.ts +113 -0
- package/types/app/mailbox/mailbox-admin.d.ts.map +1 -0
- package/types/app/mailbox/mailbox-poller.d.ts +92 -3
- package/types/app/mailbox/mailbox-poller.d.ts.map +1 -1
- package/types/app/mailbox/mailboxing.d.ts +3 -0
- package/types/app/mailbox/mailboxing.d.ts.map +1 -1
- package/types/app/multisig/counseling.d.ts +196 -0
- package/types/app/multisig/counseling.d.ts.map +1 -0
- package/types/app/multisig/group-members.d.ts +11 -0
- package/types/app/multisig/group-members.d.ts.map +1 -1
- package/types/app/multisig/grouping.d.ts +39 -20
- package/types/app/multisig/grouping.d.ts.map +1 -1
- package/types/app/multisig/multisig-messaging.d.ts +23 -6
- package/types/app/multisig/multisig-messaging.d.ts.map +1 -1
- package/types/app/multisig/multisig-workflows.d.ts +91 -22
- package/types/app/multisig/multisig-workflows.d.ts.map +1 -1
- package/types/app/multisig/proposals.d.ts +129 -0
- package/types/app/multisig/proposals.d.ts.map +1 -0
- package/types/app/multisig/proposing.d.ts +125 -0
- package/types/app/multisig/proposing.d.ts.map +1 -0
- package/types/app/notifications/signaling.d.ts +3 -1
- package/types/app/notifications/signaling.d.ts.map +1 -1
- package/types/app/protocol/parsering.d.ts +13 -0
- package/types/app/protocol/parsering.d.ts.map +1 -1
- package/types/app/protocol/protocol-processing.d.ts +7 -1
- package/types/app/protocol/protocol-processing.d.ts.map +1 -1
- package/types/app/queries/query-workflows.d.ts +98 -0
- package/types/app/queries/query-workflows.d.ts.map +1 -0
- package/types/app/runtime/agent-runtime.d.ts +72 -25
- package/types/app/runtime/agent-runtime.d.ts.map +1 -1
- package/types/app/runtime/cue-runtime.d.ts +2 -1
- package/types/app/runtime/cue-runtime.d.ts.map +1 -1
- package/types/app/runtime/delivery-outbox.d.ts +68 -0
- package/types/app/runtime/delivery-outbox.d.ts.map +1 -0
- package/types/app/runtime/doing.d.ts +27 -0
- package/types/app/runtime/doing.d.ts.map +1 -0
- package/types/app/runtime/ipex-auxiliaries.d.ts +74 -0
- package/types/app/runtime/ipex-auxiliaries.d.ts.map +1 -0
- package/types/app/runtime/operation-owners.d.ts +137 -0
- package/types/app/runtime/operation-owners.d.ts.map +1 -0
- package/types/app/runtime/retry-backoff.d.ts +49 -0
- package/types/app/runtime/retry-backoff.d.ts.map +1 -0
- package/types/app/runtime/workflow-contract.d.ts +79 -0
- package/types/app/runtime/workflow-contract.d.ts.map +1 -0
- package/types/app/transport/http-client.d.ts.map +1 -1
- package/types/cli/common/event-completion.d.ts +26 -0
- package/types/cli/common/event-completion.d.ts.map +1 -0
- package/types/cli/common/runtime-workers.d.ts +23 -0
- package/types/cli/common/runtime-workers.d.ts.map +1 -0
- package/types/cli/credentials/ipex.d.ts.map +1 -1
- package/types/cli/credentials/vc.d.ts +1 -1
- package/types/cli/credentials/vc.d.ts.map +1 -1
- package/types/cli/endpoints/did.d.ts.map +1 -1
- package/types/cli/endpoints/oobi.d.ts +3 -1
- package/types/cli/endpoints/oobi.d.ts.map +1 -1
- package/types/cli/identity/challenge.d.ts +1 -1
- package/types/cli/identity/challenge.d.ts.map +1 -1
- package/types/cli/identity/delegate.d.ts +14 -1
- package/types/cli/identity/delegate.d.ts.map +1 -1
- package/types/cli/identity/incept.d.ts.map +1 -1
- package/types/cli/identity/interact.d.ts.map +1 -1
- package/types/cli/identity/rotate.d.ts.map +1 -1
- package/types/cli/index.d.ts +3 -1
- package/types/cli/index.d.ts.map +1 -1
- package/types/cli/messaging/group-join.d.ts +56 -0
- package/types/cli/messaging/group-join.d.ts.map +1 -0
- package/types/cli/messaging/group-wait.d.ts +34 -0
- package/types/cli/messaging/group-wait.d.ts.map +1 -0
- package/types/cli/messaging/multisig.d.ts +29 -5
- package/types/cli/messaging/multisig.d.ts.map +1 -1
- package/types/cli/messaging/root-copy-lines.d.ts +39 -0
- package/types/cli/messaging/root-copy-lines.d.ts.map +1 -0
- package/types/core/cues.d.ts +11 -0
- package/types/core/cues.d.ts.map +1 -1
- package/types/core/kel/eventing.d.ts.map +1 -1
- package/types/core/mailbox/kram-policy.d.ts +14 -0
- package/types/core/mailbox/kram-policy.d.ts.map +1 -1
- package/types/core/mailbox/kraming.d.ts +1 -1
- package/types/core/mailbox/kraming.d.ts.map +1 -1
- package/types/core/records.d.ts +61 -0
- package/types/core/records.d.ts.map +1 -1
- package/types/core/routing.d.ts +6 -0
- package/types/core/routing.d.ts.map +1 -1
- package/types/db/basing.d.ts +8 -2
- package/types/db/basing.d.ts.map +1 -1
- package/types/db/core/indexeddb-persistence.d.ts +59 -0
- package/types/db/core/indexeddb-persistence.d.ts.map +1 -0
- package/types/db/indexeddb.d.ts +37 -0
- package/types/db/indexeddb.d.ts.map +1 -0
- package/types/db/keeping.d.ts +5 -2
- package/types/db/keeping.d.ts.map +1 -1
- package/types/db/store-lock.d.ts +72 -0
- package/types/db/store-lock.d.ts.map +1 -0
- package/types/npm/db-indexeddb.d.ts +4 -0
- package/types/npm/db-indexeddb.d.ts.map +1 -0
- package/types/npm/runtime-web.d.ts +4 -0
- package/types/npm/runtime-web.d.ts.map +1 -0
- package/types/runtime/index.d.ts +42 -7
- package/types/runtime/index.d.ts.map +1 -1
- package/types/runtime/web/output-barrier.d.ts +30 -0
- package/types/runtime/web/output-barrier.d.ts.map +1 -0
- package/types/runtime/web/persistent-storage.d.ts +36 -0
- package/types/runtime/web/persistent-storage.d.ts.map +1 -0
- package/types/runtime/web.d.ts +11 -0
- package/types/runtime/web.d.ts.map +1 -0
- package/types/vdr/tel-publication.d.ts +6 -0
- package/types/vdr/tel-publication.d.ts.map +1 -1
- package/types/version.d.ts +2 -2
- package/esm/keri/npm/src/cli/common/tel-completion.js +0 -24
- package/types/cli/common/tel-completion.d.ts +0 -8
- package/types/cli/common/tel-completion.d.ts.map +0 -1
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-signature event completion: the steps that follow authoring a local
|
|
3
|
+
* event, owned by the library so that every host (CLI, wallet, service) runs
|
|
4
|
+
* one implementation.
|
|
5
|
+
*
|
|
6
|
+
* Completion is two independent steps. `receiptEvent` obtains witness receipts
|
|
7
|
+
* for the accepted event. For delegated events, `beginDelegation` places the
|
|
8
|
+
* event in the durable delegating workflow and `waitForDelegation` drives the
|
|
9
|
+
* host's runtime has learned the delegator's anchor. Begin is separate from
|
|
10
|
+
* wait so that a host without a blocking caller can begin, return to its user
|
|
11
|
+
* interface and read `delegationStatus` later. `completeEvent` is the
|
|
12
|
+
* convenience that runs both steps in order. A completed rotation (`rot` or `drt`) is then announced with a
|
|
13
|
+
* {@link RotatedCue} to the host's `KelPublisher`, which tells the identifier's mailboxes (a mailbox
|
|
14
|
+
* authenticates the identifier's polls against the key state it holds). The announcement is a prompt:
|
|
15
|
+
* the publisher derives what is owed from state, so a host without one loses nothing durable. An interaction
|
|
16
|
+
* event changes no keys, so it announces nothing.
|
|
17
|
+
*
|
|
18
|
+
* Boundaries:
|
|
19
|
+
* - Dependencies are narrow collaborators, not an AgentRuntime (ADR-0013). The
|
|
20
|
+
* host owns the runtime and its lifetime; `withDelegation` lends the
|
|
21
|
+
* collaborator for one scope and, for a one-shot host, runs workers in it.
|
|
22
|
+
* - Waits only observe. They never start runtime workers, and an expired wait is
|
|
23
|
+
* a returned `timed-out` value, not an exception.
|
|
24
|
+
* - Witness authorization codes arrive resolved. Prompting is a host concern.
|
|
25
|
+
* - Delegation state is the Anchorer's durable escrow membership; this module
|
|
26
|
+
* adds none.
|
|
27
|
+
*/
|
|
28
|
+
import { Ilks } from "cesr-ts";
|
|
29
|
+
import { dgKey } from "../../db/core/keys.js";
|
|
30
|
+
import { observeUntil } from "../runtime/workflow-contract.js";
|
|
31
|
+
import { Receiptor, WitnessReceiptor } from "../witness/receipting.js";
|
|
32
|
+
/** How long the CLI-compatible wait for a delegator's anchor lasts. */
|
|
33
|
+
export const DELEGATION_WAIT_TIMEOUT_MS = 120_000;
|
|
34
|
+
/**
|
|
35
|
+
* Obtain witness receipts for an accepted local event. No-op when the
|
|
36
|
+
* identifier has no accepted key state yet (a delegated inception awaiting
|
|
37
|
+
* approval) or its current key state has no witnesses.
|
|
38
|
+
*
|
|
39
|
+
* @throws Receipt failures from the witness receiptor propagate.
|
|
40
|
+
*/
|
|
41
|
+
export function* receiptEvent(deps, pre, { sn, auths, endpoint = false, force = false } = {}) {
|
|
42
|
+
const kever = deps.hby.habs.get(pre)?.kever;
|
|
43
|
+
if (!kever?.wits.length)
|
|
44
|
+
return;
|
|
45
|
+
if (endpoint) {
|
|
46
|
+
yield* new Receiptor(deps.hby, deps.protocol, deps.http, deps.clock).receipt(pre, { sn, auths });
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
yield* new WitnessReceiptor(deps.hby, deps.protocol, deps.http, deps.clock, { force })
|
|
50
|
+
.submit(pre, { sn, auths });
|
|
51
|
+
}
|
|
52
|
+
deps.changes?.push({ kind: "event", id: `${pre}:${sn ?? kever.sn}` });
|
|
53
|
+
}
|
|
54
|
+
/** Hex sequence key the delegating workflow uses. */
|
|
55
|
+
function snKey(sn) {
|
|
56
|
+
return sn.toString(16);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Put one delegated event into the durable delegating workflow. Returns at once;
|
|
60
|
+
* progress needs the host's runtime workers, and `delegationStatus` reports it.
|
|
61
|
+
*
|
|
62
|
+
* @param communicationHab Optional local proxy that signs delegation traffic.
|
|
63
|
+
*/
|
|
64
|
+
export function beginDelegation(delegation, pre, sn, communicationHab) {
|
|
65
|
+
delegation.anchorer.beginLatest(pre, sn, { communicationHab });
|
|
66
|
+
delegation.changes?.push({ kind: "delegation", id: `${pre}:${sn}` });
|
|
67
|
+
}
|
|
68
|
+
/** Read the durable workflow state for one delegated event; mutates nothing. */
|
|
69
|
+
export function delegationStatus(delegation, pre, sn) {
|
|
70
|
+
return delegation.anchorer.workflowStatus(pre, snKey(sn));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Observe the delegated event until the delegator's anchor is learned or the
|
|
74
|
+
* deadline passes. Starts no worker.
|
|
75
|
+
*/
|
|
76
|
+
export function* waitForDelegation(delegation, hab, sn, { timeoutMs = DELEGATION_WAIT_TIMEOUT_MS } = {}) {
|
|
77
|
+
const done = yield* observeUntil(() => delegation.anchorer.complete(hab.pre, sn), { timeoutMs });
|
|
78
|
+
const status = delegationStatus(delegation, hab.pre, sn);
|
|
79
|
+
if (!done)
|
|
80
|
+
return { outcome: "timed-out", status, timeoutMs };
|
|
81
|
+
delegation.changes?.push({ kind: "delegation", id: `${hab.pre}:${sn}` });
|
|
82
|
+
return { outcome: "settled", status };
|
|
83
|
+
}
|
|
84
|
+
/** Announce a completed rotation so its mailboxes are told; any other event announces nothing. */
|
|
85
|
+
function announceRotation(deps, pre, sn, status) {
|
|
86
|
+
if (status.state !== "complete" || !deps.rotated)
|
|
87
|
+
return;
|
|
88
|
+
const said = deps.hby.db.kels.getLast(pre, sn);
|
|
89
|
+
const ilk = said ? deps.hby.db.getEvtSerder(pre, said)?.ilk : null;
|
|
90
|
+
if (said && (ilk === Ilks.rot || ilk === Ilks.drt))
|
|
91
|
+
deps.rotated.push({ kin: "rotated", pre, sn, said });
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Complete a freshly authored event: witness receipts, then, for delegated
|
|
95
|
+
* events, delegation begin and wait.
|
|
96
|
+
*
|
|
97
|
+
* @param sn Sequence number of the event just authored.
|
|
98
|
+
*/
|
|
99
|
+
export function* completeEvent(deps, hab, sn, { delegation, ...receipt } = {}) {
|
|
100
|
+
yield* receiptEvent(deps, hab.pre, { ...receipt, sn });
|
|
101
|
+
if (!delegation) {
|
|
102
|
+
const status = eventStatus(deps.hby, hab.pre, sn);
|
|
103
|
+
announceRotation(deps, hab.pre, sn, status);
|
|
104
|
+
return { outcome: "settled", status, delegationPhase: null };
|
|
105
|
+
}
|
|
106
|
+
const communicationHab = delegation.communicationHab?.();
|
|
107
|
+
return yield* deps.withDelegation(hab, function* (collaborator) {
|
|
108
|
+
beginDelegation(collaborator, hab.pre, sn, communicationHab);
|
|
109
|
+
const result = yield* waitForDelegation(collaborator, hab, sn, { timeoutMs: delegation.timeoutMs });
|
|
110
|
+
const status = eventStatus({ db: deps.hby.db, anchorer: collaborator.anchorer }, hab.pre, sn);
|
|
111
|
+
if (result.outcome === "timed-out") {
|
|
112
|
+
return {
|
|
113
|
+
outcome: "timed-out",
|
|
114
|
+
status,
|
|
115
|
+
timeoutMs: result.timeoutMs,
|
|
116
|
+
delegationPhase: result.status.phase,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
announceRotation(deps, hab.pre, sn, status);
|
|
120
|
+
return { outcome: "settled", status, delegationPhase: result.status.phase };
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Pure synchronous status of the event `pre` at `sn`, derived from durable state.
|
|
125
|
+
*
|
|
126
|
+
* Receipts are judged against the witness set of THAT event (not the current
|
|
127
|
+
* key state) via stored `wigs`. A delegating-workflow escrow phase takes
|
|
128
|
+
* precedence; a delegated event with no escrow and no anchor yet reads as
|
|
129
|
+
* waiting for the delegator's anchor. Group events are not covered.
|
|
130
|
+
*/
|
|
131
|
+
export function eventStatus(deps, pre, sn) {
|
|
132
|
+
const workflow = deps.anchorer?.workflowStatus(pre, snKey(sn));
|
|
133
|
+
if (workflow?.phase)
|
|
134
|
+
return { state: "active", phase: workflow.phase };
|
|
135
|
+
const said = deps.db.kels.getLast(pre, sn);
|
|
136
|
+
const serder = said ? deps.db.getEvtSerder(pre, said) : null;
|
|
137
|
+
if (!said || !serder)
|
|
138
|
+
return { state: "unknown", reason: "no-accepted-event" };
|
|
139
|
+
if (!deps.db.fullyWitnessed(serder)) {
|
|
140
|
+
return {
|
|
141
|
+
state: "active",
|
|
142
|
+
phase: "waitingWitnessReceipts",
|
|
143
|
+
blocked: {
|
|
144
|
+
missing: "witnessReceipts",
|
|
145
|
+
have: deps.db.wigs.get(dgKey(pre, said)).length,
|
|
146
|
+
of: deps.db.acceptedEventWitnesses(serder)?.length ?? 0,
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (deps.anchorer && deps.db.getKever(pre)?.delegated && !deps.anchorer.complete(pre, sn)) {
|
|
151
|
+
return { state: "active", phase: "waitingDelegatorAnchor" };
|
|
152
|
+
}
|
|
153
|
+
return { state: "complete" };
|
|
154
|
+
}
|
|
@@ -17,6 +17,7 @@ import { Deck } from "../../core/deck.js";
|
|
|
17
17
|
import { TransIdxSigGroup } from "../../core/dispatch.js";
|
|
18
18
|
import { ValidationError } from "../../core/errors.js";
|
|
19
19
|
import { Kevery } from "../../core/kel/eventing.js";
|
|
20
|
+
import { Kever } from "../../core/kel/kever.js";
|
|
20
21
|
import { incept as inceptEvent, interact as interactEvent, query as queryEvent, receipt as receiptEvent, reply as replyEvent, rotate as rotateEvent, } from "../../core/protocol-eventing.js";
|
|
21
22
|
import { messagize } from "../../core/protocol-serialization.js";
|
|
22
23
|
import { HabitatRecord } from "../../core/records.js";
|
|
@@ -275,6 +276,23 @@ export class Hab {
|
|
|
275
276
|
get accepted() {
|
|
276
277
|
return !!this.pre && this.db.getKever(this.pre) !== null;
|
|
277
278
|
}
|
|
279
|
+
/**
|
|
280
|
+
* Whether the held or stored signing keys currently allow this habitat to sign.
|
|
281
|
+
* False for a keyless habitat (`makeSignedHab`) until the host holds its signer.
|
|
282
|
+
*/
|
|
283
|
+
canSign() {
|
|
284
|
+
try {
|
|
285
|
+
const probe = new Uint8Array(1);
|
|
286
|
+
if (this.kever?.transferable === false)
|
|
287
|
+
this.sign(probe, false);
|
|
288
|
+
else
|
|
289
|
+
this.sign(probe, true);
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
278
296
|
/** Return the live accepted-state `Kever` for this habitat when available. */
|
|
279
297
|
get kever() {
|
|
280
298
|
return this.pre ? this.db.getKever(this.pre) : null;
|
|
@@ -436,8 +454,24 @@ export class Hab {
|
|
|
436
454
|
if (!pre || !serder.said) {
|
|
437
455
|
throw new Error("Expected inception serder to provide string pre and said.");
|
|
438
456
|
}
|
|
439
|
-
const
|
|
440
|
-
this.mgr.move(
|
|
457
|
+
const sigs = this.mgr.sign(serder.raw, keys, true);
|
|
458
|
+
this.mgr.move(verfers[0].qb64, pre);
|
|
459
|
+
this.admitInception(serder, sigs, hidden);
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Admit one signed inception as this habitat's first event: bind `pre`,
|
|
463
|
+
* register the name and habitat records unless `hidden`, and accept the event
|
|
464
|
+
* into the local KEL.
|
|
465
|
+
*
|
|
466
|
+
* Shared tail of `make()` and `makeSigned()`. It writes no keeper state and
|
|
467
|
+
* never signs. On rejection the `prefixes` entry is withdrawn and the error
|
|
468
|
+
* propagates; callers decide what else to undo.
|
|
469
|
+
*/
|
|
470
|
+
admitInception(serder, sigers, hidden) {
|
|
471
|
+
const pre = serder.pre;
|
|
472
|
+
if (!pre || !serder.said) {
|
|
473
|
+
throw new Error("Expected inception serder to provide string pre and said.");
|
|
474
|
+
}
|
|
441
475
|
this.pre = pre;
|
|
442
476
|
if (!hidden) {
|
|
443
477
|
const habord = new HabitatRecord({
|
|
@@ -449,9 +483,8 @@ export class Hab {
|
|
|
449
483
|
this.db.pinName(this.ns ?? "", this.name, pre);
|
|
450
484
|
this.db.prefixes.add(pre);
|
|
451
485
|
}
|
|
452
|
-
const sigs = this.mgr.sign(serder.raw, keys, true);
|
|
453
486
|
try {
|
|
454
|
-
this.acceptLocally(serder,
|
|
487
|
+
this.acceptLocally(serder, sigers);
|
|
455
488
|
}
|
|
456
489
|
catch (error) {
|
|
457
490
|
if (!hidden) {
|
|
@@ -460,6 +493,50 @@ export class Hab {
|
|
|
460
493
|
throw error;
|
|
461
494
|
}
|
|
462
495
|
}
|
|
496
|
+
/**
|
|
497
|
+
* Adopt a pre-signed inception this `Habery` did not generate, with no
|
|
498
|
+
* keeper key state for it (KERIpy `SignifyHab.incept` / `makeSignifyHab`).
|
|
499
|
+
*
|
|
500
|
+
* The inception is evaluated first, without mutation, by the same `Kever`
|
|
501
|
+
* decision local acceptance uses: SAID, prefix derivation, key and threshold
|
|
502
|
+
* material, and the signatures against the event's own keys. Anything but an
|
|
503
|
+
* accept (including an escrow for missing signatures) is refused before any
|
|
504
|
+
* record is written. A name or prefix already in use is refused too.
|
|
505
|
+
*
|
|
506
|
+
* Differences from KERIpy: verification precedes persistence instead of
|
|
507
|
+
* following it, a taken name is refused before anything is written (KERIpy
|
|
508
|
+
* pins the habitat record first), and `sign` is not disabled; it succeeds
|
|
509
|
+
* once the host holds the matching signer (`Manager.hold`).
|
|
510
|
+
*/
|
|
511
|
+
makeSigned(args) {
|
|
512
|
+
const { serder, sigers, hidden = false } = args;
|
|
513
|
+
const pre = serder.pre;
|
|
514
|
+
if (!pre || !serder.said) {
|
|
515
|
+
throw new ValidationError("Pre-signed inception must provide a prefix and SAID.");
|
|
516
|
+
}
|
|
517
|
+
if (this.db.getHab(pre) || this.db.getKever(pre) || this.db.prefixes.has(pre)) {
|
|
518
|
+
throw new ValidationError(`Habitat prefix ${pre} already exists.`);
|
|
519
|
+
}
|
|
520
|
+
if (!hidden && this.db.getName(this.ns ?? "", this.name) !== null) {
|
|
521
|
+
throw new ValidationError(`Habitat name ${this.name} already exists.`);
|
|
522
|
+
}
|
|
523
|
+
const decision = Kever.evaluateInception({ db: this.db, serder, sigers, local: true });
|
|
524
|
+
if (decision.kind !== "accept") {
|
|
525
|
+
const detail = decision.kind === "duplicate" ? decision.duplicate : decision.message;
|
|
526
|
+
throw new ValidationError(`Pre-signed inception ${serder.said} refused: ${detail}`);
|
|
527
|
+
}
|
|
528
|
+
try {
|
|
529
|
+
this.admitInception(serder, sigers, hidden);
|
|
530
|
+
}
|
|
531
|
+
catch (error) {
|
|
532
|
+
if (!hidden) {
|
|
533
|
+
this.db.habs.rem(pre);
|
|
534
|
+
this.db.names.rem([this.ns ?? "", this.name]);
|
|
535
|
+
}
|
|
536
|
+
this.pre = "";
|
|
537
|
+
throw error;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
463
540
|
/**
|
|
464
541
|
* Rotate this habitat through the shared accepted-state path.
|
|
465
542
|
*
|
|
@@ -1190,6 +1267,17 @@ export class Habery {
|
|
|
1190
1267
|
writable: true,
|
|
1191
1268
|
value: void 0
|
|
1192
1269
|
});
|
|
1270
|
+
/**
|
|
1271
|
+
* Prefixes of habitats whose alias config was not applied at open because they
|
|
1272
|
+
* could not sign yet (a keyless habitat before the host holds its signer). The
|
|
1273
|
+
* host calls `hab.reconfigure()` after holding; applying config is retried then.
|
|
1274
|
+
*/
|
|
1275
|
+
Object.defineProperty(this, "deferredReconfigure", {
|
|
1276
|
+
enumerable: true,
|
|
1277
|
+
configurable: true,
|
|
1278
|
+
writable: true,
|
|
1279
|
+
value: []
|
|
1280
|
+
});
|
|
1193
1281
|
this.storeOpener = opener;
|
|
1194
1282
|
this.borrowsStores = borrowsStores;
|
|
1195
1283
|
this.name = name;
|
|
@@ -1237,8 +1325,10 @@ export class Habery {
|
|
|
1237
1325
|
/**
|
|
1238
1326
|
* Populate the in-memory habitat cache from durable `habs.` + `states.` data.
|
|
1239
1327
|
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1328
|
+
* Like KERIpy `loadHabs`, a local group record is held even while its
|
|
1329
|
+
* inception is unaccepted: the `Hab` reads accepted state on demand, so it
|
|
1330
|
+
* becomes usable the moment the event is accepted. A non-group record without
|
|
1331
|
+
* accepted state is an orphan; `Baser.reloadKevers` already dropped it.
|
|
1242
1332
|
*/
|
|
1243
1333
|
loadHabs() {
|
|
1244
1334
|
this.reconfigure();
|
|
@@ -1251,13 +1341,20 @@ export class Habery {
|
|
|
1251
1341
|
const hab = new Hab(habord.name, this.db, this.ks, this.mgr, this.cf, this.rtr, this.rvy, this.kevery, habord.domain, hid);
|
|
1252
1342
|
if (!hab.accepted) {
|
|
1253
1343
|
if (habord.mid) {
|
|
1344
|
+
this.habs.set(hab.pre, hab);
|
|
1254
1345
|
continue;
|
|
1255
1346
|
}
|
|
1256
1347
|
throw new ValidationError(`Problem loading Hab pre=${hid} name=${habord.name} from db.`);
|
|
1257
1348
|
}
|
|
1258
1349
|
this.habs.set(hab.pre, hab);
|
|
1259
1350
|
}
|
|
1351
|
+
this.deferredReconfigure.length = 0;
|
|
1260
1352
|
for (const hab of this.habs.values()) {
|
|
1353
|
+
// Config replies are signed. A habitat that cannot sign yet applies them once its signer is held.
|
|
1354
|
+
if (hab.accepted && hab.configuredSection() && !hab.canSign()) {
|
|
1355
|
+
this.deferredReconfigure.push(hab.pre);
|
|
1356
|
+
continue;
|
|
1357
|
+
}
|
|
1261
1358
|
hab.reconfigure();
|
|
1262
1359
|
}
|
|
1263
1360
|
// Restart recovery: commit members of an accepted establishment event
|
|
@@ -1327,6 +1424,32 @@ export class Habery {
|
|
|
1327
1424
|
}
|
|
1328
1425
|
}
|
|
1329
1426
|
}
|
|
1427
|
+
/**
|
|
1428
|
+
* Adopt an inception the caller built and signed, creating a habitat with no
|
|
1429
|
+
* keeper key state (KERIpy `makeSignifyHab`).
|
|
1430
|
+
*
|
|
1431
|
+
* Contract:
|
|
1432
|
+
* - the inception and its signatures are verified before anything is
|
|
1433
|
+
* persisted; a bad, under-signed or duplicate inception is refused and
|
|
1434
|
+
* leaves no record behind
|
|
1435
|
+
* - nothing is written to the keeper, so the hab cannot sign until the host
|
|
1436
|
+
* calls `mgr.hold()` with the matching signer(s), cannot rotate, and after
|
|
1437
|
+
* reopen is present again with signing unavailable until re-held
|
|
1438
|
+
* - hold signers with the encoding the inception's keys use (`D...` for
|
|
1439
|
+
* transferable, `B...` for non-transferable)
|
|
1440
|
+
* - unlike `makeHab`, bootstrap config replies are not applied, since they
|
|
1441
|
+
* need a signing key; the host reconfigures after holding
|
|
1442
|
+
*/
|
|
1443
|
+
makeSignedHab(name, ns, args) {
|
|
1444
|
+
const pre = args.serder.pre;
|
|
1445
|
+
if (pre && this.habs.has(pre)) {
|
|
1446
|
+
throw new ValidationError(`Habitat prefix ${pre} already exists.`);
|
|
1447
|
+
}
|
|
1448
|
+
const hab = new Hab(name, this.db, this.ks, this.mgr, this.cf, this.rtr, this.rvy, this.kevery, ns, "");
|
|
1449
|
+
hab.makeSigned(args);
|
|
1450
|
+
this.habs.set(hab.pre, hab);
|
|
1451
|
+
return hab;
|
|
1452
|
+
}
|
|
1330
1453
|
/** Creates and caches a new habitat under this habery. */
|
|
1331
1454
|
makeHab(name, ns, args = {}) {
|
|
1332
1455
|
const hab = new Hab(name, this.db, this.ks, this.mgr, this.cf, this.rtr, this.rvy, this.kevery, ns, "");
|
|
@@ -241,6 +241,16 @@ export class Manager {
|
|
|
241
241
|
writable: true,
|
|
242
242
|
value: null
|
|
243
243
|
});
|
|
244
|
+
/**
|
|
245
|
+
* Borrowed, volatile signers keyed by qualified public key (`hold()`).
|
|
246
|
+
* Never written to the Keeper and never consulted by `Keeper` rows.
|
|
247
|
+
*/
|
|
248
|
+
Object.defineProperty(this, "held", {
|
|
249
|
+
enumerable: true,
|
|
250
|
+
configurable: true,
|
|
251
|
+
writable: true,
|
|
252
|
+
value: new Map()
|
|
253
|
+
});
|
|
244
254
|
const { ks, seed = "", aeid = "", pidx = 0, algo = Algos.salty, salt = randomSaltQb64(), tier = Tiers.low, } = args;
|
|
245
255
|
this._ks = ks;
|
|
246
256
|
this._seed = seed;
|
|
@@ -428,13 +438,21 @@ export class Manager {
|
|
|
428
438
|
}
|
|
429
439
|
return root;
|
|
430
440
|
}
|
|
431
|
-
/**
|
|
432
|
-
|
|
441
|
+
/**
|
|
442
|
+
* Retain once, returning false for the identical root without replacing ciphertext. `overwrite` replaces a
|
|
443
|
+
* different held root; only a caller that has shown that root was never used (no update staged or accepted
|
|
444
|
+
* for its registry) may set it.
|
|
445
|
+
*/
|
|
446
|
+
putRegistryRoot(aid, regid, root, overwrite = false) {
|
|
433
447
|
const keys = this.registryRootKeys(aid, regid);
|
|
434
448
|
if (!(root instanceof Salter) || root.code !== MtrDex.Salt_128)
|
|
435
449
|
throw new Error("Registry root must be Salt128");
|
|
436
450
|
const { aeid, encrypter, decrypter } = this.registryRootCrypto();
|
|
437
|
-
return this.ks.retainRegistryRoot(keys, root, aeid, encrypter, decrypter);
|
|
451
|
+
return this.ks.retainRegistryRoot(keys, root, aeid, encrypter, decrypter, overwrite);
|
|
452
|
+
}
|
|
453
|
+
/** Whether a root is retained for `aid` and `regid`; reads no ciphertext and needs no unlocked Keeper. */
|
|
454
|
+
hasRegistryRoot(aid, regid) {
|
|
455
|
+
return !!this.ks.rroots.get(this.registryRootKeys(aid, regid));
|
|
438
456
|
}
|
|
439
457
|
signerDecrypter() {
|
|
440
458
|
if (this.aeid && !this.decrypter) {
|
|
@@ -442,8 +460,63 @@ export class Manager {
|
|
|
442
460
|
}
|
|
443
461
|
return this.decrypter ?? undefined;
|
|
444
462
|
}
|
|
445
|
-
/**
|
|
463
|
+
/**
|
|
464
|
+
* Borrow live signers for signing, decryption and ESSR opening without
|
|
465
|
+
* persisting them.
|
|
466
|
+
*
|
|
467
|
+
* Held signers are consulted before stored keys by the one private lookup
|
|
468
|
+
* every `sign`, `decrypt`, `open`, group-member and endpoint-role path
|
|
469
|
+
* resolves through. They live only in this `Manager` instance's memory:
|
|
470
|
+
* nothing is written to any Keeper table, re-encryption by `updateAeid()`
|
|
471
|
+
* neither reads nor changes them, and a new `Manager` over the same Keeper
|
|
472
|
+
* starts with none.
|
|
473
|
+
*
|
|
474
|
+
* Contract:
|
|
475
|
+
* - The table is keyed by `signer.verfer.qb64`. The same raw key encodes
|
|
476
|
+
* differently when transferable (`D...`) and non-transferable (`B...`), so
|
|
477
|
+
* build each `Signer` with the transferability the key list or prefix uses,
|
|
478
|
+
* and hold that encoding. A request for the other encoding does not match.
|
|
479
|
+
* - The host owns each `Signer` and its seed bytes, including zeroing them.
|
|
480
|
+
* This keeps the reference only; it never copies seed bytes and never
|
|
481
|
+
* erases them. Dropping a reference with `release()` does not zero memory.
|
|
482
|
+
* - Holding a pub that is already held replaces the earlier signer. A held
|
|
483
|
+
* signer shadows a stored key with the same public key.
|
|
484
|
+
* - The `pre/path` branch of `sign()` re-derives salty keys from the stored
|
|
485
|
+
* prefix salt and never consults held signers.
|
|
486
|
+
*
|
|
487
|
+
* @param signers Signers to borrow; all are validated before any is held.
|
|
488
|
+
*/
|
|
489
|
+
hold(signers) {
|
|
490
|
+
const batch = new Map();
|
|
491
|
+
for (const signer of signers) {
|
|
492
|
+
if (!(signer instanceof Signer)) {
|
|
493
|
+
throw new ValidationError("Held signers must be Signer instances");
|
|
494
|
+
}
|
|
495
|
+
batch.set(signer.verfer.qb64, signer);
|
|
496
|
+
}
|
|
497
|
+
for (const [pub, signer] of batch)
|
|
498
|
+
this.held.set(pub, signer);
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Drop held signer references: all of them, or only those for `pubs`.
|
|
502
|
+
*
|
|
503
|
+
* Unheld pubs are ignored. Afterwards a request for a released key resolves
|
|
504
|
+
* from stored keys only and fails as any missing key does. This drops
|
|
505
|
+
* references; zeroing a signer's seed stays the host's job.
|
|
506
|
+
*/
|
|
507
|
+
release(pubs) {
|
|
508
|
+
if (pubs === undefined) {
|
|
509
|
+
this.held.clear();
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
for (const pub of pubs)
|
|
513
|
+
this.held.delete(pub);
|
|
514
|
+
}
|
|
515
|
+
/** Resolve one signer by qualified public key: held first, then the Keeper's `pris.`. */
|
|
446
516
|
getSignerByPub(pub) {
|
|
517
|
+
const held = this.held.get(pub);
|
|
518
|
+
if (held)
|
|
519
|
+
return held;
|
|
447
520
|
const signer = this.ks.pris.get(pub, this.signerDecrypter());
|
|
448
521
|
if (!signer) {
|
|
449
522
|
throw new Error(`Missing prikey in db for pubkey=${pub}`);
|