keri-ts 2.0.1 → 2.2.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/README.md +30 -2
- package/esm/keri/npm/src/acdc/authoring.js +195 -0
- package/esm/keri/npm/src/acdc/chaining.js +223 -89
- package/esm/keri/npm/src/acdc/custody.js +164 -0
- package/esm/keri/npm/src/acdc/dhking.js +244 -32
- package/esm/keri/npm/src/acdc/observing.js +2 -2
- package/esm/keri/npm/src/acdc/regbasing.js +30 -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 +143 -26
- package/esm/keri/npm/src/acdc/scheming.js +93 -54
- package/esm/keri/npm/src/acdc/unblinding.js +120 -99
- 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 +5 -7
- 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 +131 -0
- 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/credentials/verifying.js +12 -3
- package/esm/keri/npm/src/app/delivery/forwarding.js +64 -9
- package/esm/keri/npm/src/app/exchanges/exchanging.js +24 -15
- package/esm/keri/npm/src/app/identity/challenging.js +50 -0
- package/esm/keri/npm/src/app/identity/configing.js +17 -43
- 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 +183 -41
- package/esm/keri/npm/src/app/identity/keeping.js +78 -5
- package/esm/keri/npm/src/app/identity/lmdb-habery.js +12 -0
- package/esm/keri/npm/src/app/ipex/group-ipex.js +327 -0
- package/esm/keri/npm/src/app/ipex/group-issuance.js +902 -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-graph.js +7 -70
- package/esm/keri/npm/src/app/ipex/ipex-grouping.js +42 -16
- 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/ipex/issuance.js +888 -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 +401 -0
- package/esm/keri/npm/src/app/ipex/receive-issuance.js +86 -0
- package/esm/keri/npm/src/app/ipex/unblinding-workflow.js +660 -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 +15 -14
- package/esm/keri/npm/src/app/multisig/counseling.js +482 -0
- package/esm/keri/npm/src/app/multisig/group-members.js +32 -0
- package/esm/keri/npm/src/app/multisig/grouping.js +4 -3
- package/esm/keri/npm/src/app/multisig/multisig-workflows.js +101 -141
- 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/notifying.js +5 -9
- 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 +44 -6
- package/esm/keri/npm/src/app/queries/query-workflows.js +98 -0
- package/esm/keri/npm/src/app/queries/witness-inquisitor.js +2 -2
- package/esm/keri/npm/src/app/runtime/agent-runtime.js +113 -65
- 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/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-client.js +25 -6
- 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/http-endpoints.js +4 -4
- 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/event-completion.js +49 -0
- package/esm/keri/npm/src/cli/common/existing.js +3 -5
- package/esm/keri/npm/src/cli/common/runtime-workers.js +23 -0
- package/esm/keri/npm/src/cli/credentials/ipex.js +159 -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-clean.js +4 -3
- package/esm/keri/npm/src/cli/endpoints/oobi.js +12 -15
- package/esm/keri/npm/src/cli/identity/challenge.js +9 -35
- package/esm/keri/npm/src/cli/identity/delegate.js +81 -258
- package/esm/keri/npm/src/cli/identity/incept.js +17 -34
- package/esm/keri/npm/src/cli/identity/init.js +4 -3
- package/esm/keri/npm/src/cli/identity/interact.js +7 -19
- package/esm/keri/npm/src/cli/identity/rotate.js +10 -38
- package/esm/keri/npm/src/cli/index.js +3 -1
- package/esm/keri/npm/src/cli/messaging/exchange.js +2 -2
- package/esm/keri/npm/src/cli/messaging/group-join.js +79 -0
- package/esm/keri/npm/src/cli/messaging/group-wait.js +88 -0
- package/esm/keri/npm/src/cli/messaging/multisig.js +187 -250
- package/esm/keri/npm/src/cli/messaging/root-copy-lines.js +31 -0
- 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 +67 -12
- package/esm/keri/npm/src/core/kel/kever.js +11 -9
- package/esm/keri/npm/src/core/mailbox/kram-policy.js +41 -9
- 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/mailbox/kraming.js +2 -0
- package/esm/keri/npm/src/core/records.js +23 -0
- package/esm/keri/npm/src/core/routing.js +15 -2
- package/esm/keri/npm/src/db/basing.js +183 -205
- 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/indexeddb-persistence.js +221 -0
- 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/indexeddb.js +98 -0
- package/esm/keri/npm/src/db/keeping.js +38 -123
- 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/store-lock.js +150 -0
- package/esm/keri/npm/src/db/subing.js +1 -1
- 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-lmdb.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-node.js +3 -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 +58 -12
- package/esm/keri/npm/src/runtime/node.js +14 -0
- 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/eventing.js +1 -1
- package/esm/keri/npm/src/vdr/tel-publication.js +19 -3
- package/esm/keri/npm/src/version.js +2 -2
- package/package.json +24 -4
- package/types/acdc/authoring.d.ts +54 -0
- package/types/acdc/authoring.d.ts.map +1 -0
- package/types/acdc/chaining.d.ts +56 -6
- package/types/acdc/chaining.d.ts.map +1 -1
- package/types/acdc/custody.d.ts +77 -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 +11 -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 +59 -7
- 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 +97 -0
- package/types/app/credentials/root-replicating.d.ts.map +1 -0
- 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/credentials/verifying.d.ts +2 -1
- package/types/app/credentials/verifying.d.ts.map +1 -1
- package/types/app/delivery/forwarding.d.ts +16 -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/challenging.d.ts +54 -0
- package/types/app/identity/challenging.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/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 +90 -7
- package/types/app/identity/habbing.d.ts.map +1 -1
- package/types/app/identity/keeping.d.ts +50 -4
- package/types/app/identity/keeping.d.ts.map +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/group-ipex.d.ts +247 -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-graph.d.ts +4 -4
- package/types/app/ipex/ipex-graph.d.ts.map +1 -1
- 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-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/ipex/issuance.d.ts +443 -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 +298 -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 +255 -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 +4 -1
- 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 +20 -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-workflows.d.ts +93 -23
- 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/notifying.d.ts +1 -1
- package/types/app/notifications/notifying.d.ts.map +1 -1
- 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 +16 -1
- package/types/app/protocol/parsering.d.ts.map +1 -1
- package/types/app/protocol/protocol-processing.d.ts +9 -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 +79 -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/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/event-completion.d.ts +26 -0
- package/types/cli/common/event-completion.d.ts.map +1 -0
- package/types/cli/common/existing.d.ts.map +1 -1
- 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-clean.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/init.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 +4 -2
- package/types/cli/index.d.ts.map +1 -1
- package/types/cli/messaging/group-join.d.ts +53 -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 +36 -4
- 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/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/cues.d.ts +11 -0
- package/types/core/cues.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 +14 -0
- 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/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 +22 -25
- 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/indexeddb-persistence.d.ts +59 -0
- package/types/db/core/indexeddb-persistence.d.ts.map +1 -0
- 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/indexeddb.d.ts +37 -0
- package/types/db/indexeddb.d.ts.map +1 -0
- package/types/db/keeping.d.ts +14 -25
- 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/store-lock.d.ts +72 -0
- package/types/db/store-lock.d.ts.map +1 -0
- package/types/db/subing.d.ts +24 -25
- package/types/db/subing.d.ts.map +1 -1
- package/types/npm/db-indexeddb.d.ts +4 -0
- package/types/npm/db-indexeddb.d.ts.map +1 -0
- 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/npm/runtime-web.d.ts +4 -0
- package/types/npm/runtime-web.d.ts.map +1 -0
- package/types/runtime/index.d.ts +48 -14
- 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/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/acdc/relating.js +0 -59
- package/esm/keri/npm/src/cli/common/tel-completion.js +0 -24
- 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/cli/common/tel-completion.d.ts +0 -8
- package/types/cli/common/tel-completion.d.ts.map +0 -1
- package/types/db/baser-defaults.d.ts +0 -5
- package/types/db/baser-defaults.d.ts.map +0 -1
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry blind derivation over the Keeper's registry root.
|
|
3
|
+
*
|
|
4
|
+
* Issuing a blinded (BUP) registry update needs a deterministic opening. The
|
|
5
|
+
* root salt stays in the Keeper; this core derives openings from it and keeps
|
|
6
|
+
* only the public, event-specific coordinates in a `DerivedUpdateStore`. A
|
|
7
|
+
* runtime defaults to {@link BaserDerivedUpdateStore}; a wallet backs the port
|
|
8
|
+
* with its own table. The core opens no database of its own.
|
|
9
|
+
*/
|
|
10
|
+
import { bytesEqual, makeBlindState, makeBoundState, MtrDex, Salter } from "cesr-ts";
|
|
11
|
+
import { ValidationError } from "../core/errors.js";
|
|
12
|
+
import { DerivedUpdateRecord } from "../core/records.js";
|
|
13
|
+
import { vetBlind } from "./regeventing.js";
|
|
14
|
+
/** Process-local store for a CLI or tests; a wallet backs the port with its own durable table. */
|
|
15
|
+
export class MemoryDerivedUpdateStore {
|
|
16
|
+
constructor() {
|
|
17
|
+
Object.defineProperty(this, "rows", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
configurable: true,
|
|
20
|
+
writable: true,
|
|
21
|
+
value: new Map()
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
get(event) {
|
|
25
|
+
return this.rows.get(event) ?? null;
|
|
26
|
+
}
|
|
27
|
+
pin(event, value) {
|
|
28
|
+
this.rows.set(event, structuredClone(value));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Derivation coordinates kept in a registry environment's own database (`RegBaser.dvus`). The default of a
|
|
33
|
+
* runtime that supplies no store, so a server agent keeps them durably beside the registry events they
|
|
34
|
+
* describe. A wallet with its own table still passes that instead.
|
|
35
|
+
*/
|
|
36
|
+
export class BaserDerivedUpdateStore {
|
|
37
|
+
constructor(baser) {
|
|
38
|
+
Object.defineProperty(this, "baser", {
|
|
39
|
+
enumerable: true,
|
|
40
|
+
configurable: true,
|
|
41
|
+
writable: true,
|
|
42
|
+
value: baser
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
get(event) {
|
|
46
|
+
const row = this.baser.dvus.get([event]);
|
|
47
|
+
return row ? { credential: row.credential, state: row.state, bound: row.bound } : null;
|
|
48
|
+
}
|
|
49
|
+
pin(event, value) {
|
|
50
|
+
this.baser.dvus.pin([event], new DerivedUpdateRecord(structuredClone(value)));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Explicit capability over a local habitat's Keeper root and accepted public registry evidence. */
|
|
54
|
+
export class RegistryCustody {
|
|
55
|
+
/** Borrow owners only; construction loads no encrypted row. */
|
|
56
|
+
constructor(options) {
|
|
57
|
+
Object.defineProperty(this, "options", {
|
|
58
|
+
enumerable: true,
|
|
59
|
+
configurable: true,
|
|
60
|
+
writable: true,
|
|
61
|
+
value: options
|
|
62
|
+
});
|
|
63
|
+
this.owner();
|
|
64
|
+
}
|
|
65
|
+
/** Bind the actual local habitat and its key owners, never an AID label alone. */
|
|
66
|
+
owner() {
|
|
67
|
+
const { hby, hab } = this.options;
|
|
68
|
+
if (hby.habs.get(hab.pre) !== hab || hab.ks !== hby.ks || hab.mgr !== hby.mgr || hab.db !== hby.db) {
|
|
69
|
+
throw new ValidationError("Custody requires the actual local habitat and Keeper owners");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Load only this habitat's Keeper root; possession confers no protocol authority. */
|
|
73
|
+
load(registry) {
|
|
74
|
+
this.owner();
|
|
75
|
+
const root = this.options.hby.mgr.getRegistryRoot(this.options.hab.pre, registry);
|
|
76
|
+
if (!root)
|
|
77
|
+
throw new ValidationError("Registry custody is not provisioned");
|
|
78
|
+
return root;
|
|
79
|
+
}
|
|
80
|
+
/** Provision an issuer-selected root once, refusing replacement behind opaque accepted history. */
|
|
81
|
+
createCustody(registry) {
|
|
82
|
+
this.owner();
|
|
83
|
+
const { hby, hab } = this.options;
|
|
84
|
+
if (!hby.mgr.aeid || !hby.mgr.seed) {
|
|
85
|
+
throw new ValidationError("Private credential custody requires an authenticated encrypted Keeper");
|
|
86
|
+
}
|
|
87
|
+
if (hby.mgr.getRegistryRoot(hab.pre, registry))
|
|
88
|
+
return { registry };
|
|
89
|
+
const rip = this.options.registry.seqEvent(registry, 0);
|
|
90
|
+
if (!rip || rip.issuer !== hab.pre) {
|
|
91
|
+
throw new ValidationError("New custody requires the accepted registry issuer's actual local habitat");
|
|
92
|
+
}
|
|
93
|
+
// Existing clone validation authenticates public openings without another parser or proof algorithm.
|
|
94
|
+
for (const _ of this.options.registry.cloneTelIter(registry)) { /* consume the accepted public prefix */ }
|
|
95
|
+
const head = this.options.registry.headEvent(registry);
|
|
96
|
+
const last = head ? Number(BigInt(`0x${head.sad.n}`)) : 0;
|
|
97
|
+
if (!Number.isSafeInteger(last))
|
|
98
|
+
throw new ValidationError("Accepted registry ordinal is not representable");
|
|
99
|
+
for (let ordinal = 1; ordinal <= last; ordinal++) {
|
|
100
|
+
const event = this.options.registry.seqEvent(registry, ordinal);
|
|
101
|
+
if (!event)
|
|
102
|
+
throw new ValidationError("Accepted registry history is incomplete");
|
|
103
|
+
if (event.ilk === "bup" && !this.options.registry.opening(event.said)) {
|
|
104
|
+
throw new ValidationError("Local custody is missing for blinded registry history; salt cannot be recreated");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
hby.mgr.putRegistryRoot(hab.pre, registry, new Salter({ code: MtrDex.Salt_128, raw: crypto.getRandomValues(new Uint8Array(16)) }));
|
|
108
|
+
return { registry };
|
|
109
|
+
}
|
|
110
|
+
/** Derive a candidate only; consumers still authenticate its exact accepted event and bound KEL reference. */
|
|
111
|
+
derive(registry, ordinal, credential, state, options = {}) {
|
|
112
|
+
if ((typeof ordinal !== "bigint" && (typeof ordinal !== "number" || !Number.isSafeInteger(ordinal))) || ordinal < 1) {
|
|
113
|
+
throw new ValidationError("Update ordinal must be a positive integer");
|
|
114
|
+
}
|
|
115
|
+
const root = this.load(registry);
|
|
116
|
+
const values = { salt: root.qb64, sn: ordinal, tier: "low", acdc: credential, state };
|
|
117
|
+
return options.bound
|
|
118
|
+
? makeBoundState({ ...values, bsn: options.bsn ?? 0, bd: options.bd ?? "" })
|
|
119
|
+
: makeBlindState(values);
|
|
120
|
+
}
|
|
121
|
+
/** Persist exact nonsecret coordinates before processing/anchoring a newly derived BUP. */
|
|
122
|
+
retainDerivedUpdate(event, opening) {
|
|
123
|
+
if (event.ilk !== "bup" || !event.verify() || !vetBlind(opening, event.sad.b)) {
|
|
124
|
+
throw new ValidationError("Derived update requires its exact authenticated BUP opening");
|
|
125
|
+
}
|
|
126
|
+
const value = {
|
|
127
|
+
credential: opening.td.nonce,
|
|
128
|
+
state: opening.ts.label,
|
|
129
|
+
bound: "bn" in opening ? { bn: opening.bn.num.toString(16), bd: opening.bd.nonce } : null,
|
|
130
|
+
};
|
|
131
|
+
const old = this.options.store.get(event.said);
|
|
132
|
+
if (old && JSON.stringify(canonical(old)) !== JSON.stringify(value)) {
|
|
133
|
+
throw new ValidationError("Different derivation coordinates are already retained for this event");
|
|
134
|
+
}
|
|
135
|
+
this.options.store.pin(event.said, value);
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
/** Reproduce only the exact accepted event, never today's head or a later credential's coordinates. */
|
|
139
|
+
derivedOpening(event) {
|
|
140
|
+
if (event.ilk !== "bup" || !event.verify())
|
|
141
|
+
throw new ValidationError("Exact accepted blinded update is required");
|
|
142
|
+
const ordinal = BigInt(`0x${event.sad.n}`);
|
|
143
|
+
if (!Number.isSafeInteger(Number(ordinal))) {
|
|
144
|
+
throw new ValidationError("Accepted registry ordinal is not representable");
|
|
145
|
+
}
|
|
146
|
+
const stored = event.regid ? this.options.registry.seqEvent(event.regid, Number(ordinal)) : null;
|
|
147
|
+
if (!stored || !bytesEqual(stored.raw, event.raw)) {
|
|
148
|
+
throw new ValidationError("Exact accepted registry event is required");
|
|
149
|
+
}
|
|
150
|
+
const value = this.options.store.get(event.said);
|
|
151
|
+
if (!value)
|
|
152
|
+
throw new ValidationError("Exact derived update coordinates are unavailable");
|
|
153
|
+
const opening = this.derive(event.regid, ordinal, value.credential, value.state, value.bound ? { bound: true, bsn: BigInt(`0x${value.bound.bn}`), bd: value.bound.bd } : {});
|
|
154
|
+
if (!vetBlind(opening, event.sad.b)) {
|
|
155
|
+
throw new ValidationError("Derived opening does not match the exact accepted event");
|
|
156
|
+
}
|
|
157
|
+
return opening;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** Fix field order so equality does not depend on how a store hydrated the record. */
|
|
161
|
+
function canonical(value) {
|
|
162
|
+
const { credential, state, bound } = value;
|
|
163
|
+
return { credential, state, bound: bound ? { bn: bound.bn, bd: bound.bd } : null };
|
|
164
|
+
}
|
|
@@ -8,7 +8,7 @@ import { hkdf } from "@noble/hashes/hkdf";
|
|
|
8
8
|
import { sha256 } from "@noble/hashes/sha2";
|
|
9
9
|
import { Hab } from "../app/identity/habbing.js";
|
|
10
10
|
import { groupWitnesserSelection, isLocalGroupHab, latestGroupContribution, localGroupMember, } from "../app/multisig/group-members.js";
|
|
11
|
-
import { copyAuxiliaryQuery, envelopeFromFrame, } from "../app/protocol/parsering.js";
|
|
11
|
+
import { auxiliaryQueryWire, copyAuxiliaryQuery, envelopeFromFrame, restoreAuxiliaryQuery, } from "../app/protocol/parsering.js";
|
|
12
12
|
import { Deck } from "../core/deck.js";
|
|
13
13
|
import { ValidationError } from "../core/errors.js";
|
|
14
14
|
import { verifyQueryAttachments } from "../core/exchange/exchange-proofing.js";
|
|
@@ -85,6 +85,72 @@ export function deriveRoot(privateKey, context) {
|
|
|
85
85
|
shared.fill(0);
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* The DH transaction id of a Grant: its own SAID when it opens the exchange (`xip`), and otherwise the exchange it
|
|
90
|
+
* continues (`x`). The one definition, so the owner and any workflow that names the transaction agree.
|
|
91
|
+
*/
|
|
92
|
+
export function grantTransactionId(grant) {
|
|
93
|
+
return grant.ilk === "xip" ? grant.said : grant.sad.x;
|
|
94
|
+
}
|
|
95
|
+
/** The parties and transaction of a Grant `hab` takes part in, or null when it is not a DH party of it. */
|
|
96
|
+
function grantParties(hab, input) {
|
|
97
|
+
const message = input.serder, issuer = message.pre, issuee = message.sad.ri;
|
|
98
|
+
const xid = grantTransactionId(message);
|
|
99
|
+
return typeof xid === "string" && typeof issuee === "string" && issuer !== issuee
|
|
100
|
+
&& [issuer, issuee].includes(hab.pre)
|
|
101
|
+
? { issuer, issuee, xid }
|
|
102
|
+
: null;
|
|
103
|
+
}
|
|
104
|
+
/** Resolve the pending Grant `hab` may start DH for, or the reason it cannot. Reads only; creates no approval. */
|
|
105
|
+
function freshScope(hab, exc, grant) {
|
|
106
|
+
const input = exc.retainedInput(grant, { pending: true });
|
|
107
|
+
if (!input)
|
|
108
|
+
return "DH requires an authenticated pending Grant";
|
|
109
|
+
const parties = grantParties(hab, input);
|
|
110
|
+
if (!parties)
|
|
111
|
+
return "Local habitat is not a DH party";
|
|
112
|
+
const context = exc.pendingGrant(grant, { ...parties, sender: parties.issuer, recipient: parties.issuee });
|
|
113
|
+
if (!context)
|
|
114
|
+
return "DH requires authenticated fresh registry scope";
|
|
115
|
+
return { input, ...parties, registries: [...context.registries] };
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The scope of a completed exchange that can finish without new key exchange: the Grant is still pending
|
|
119
|
+
* inside its original deadline and `hab` holds a root for the registries it discloses. The scope is those
|
|
120
|
+
* registries; a registry that is still fresh must hold one. No fresh registry is required, because the
|
|
121
|
+
* issuer's update may already be accepted: {@link Dhke.finish} proves the held root against that update, so
|
|
122
|
+
* a root from any other exchange is rejected there. Pure read of stores. Null when nothing can resume.
|
|
123
|
+
*/
|
|
124
|
+
export function resumableExchange({ hab, exc }, grant) {
|
|
125
|
+
const input = exc.retainedInput(grant, { pending: true });
|
|
126
|
+
const parties = input && grantParties(hab, input);
|
|
127
|
+
if (!input || !parties)
|
|
128
|
+
return null;
|
|
129
|
+
const disclosed = (input.nests ?? []).map((nest) => nest.body.ked?.rd);
|
|
130
|
+
const held = [...new Set(disclosed)].filter((registry) => typeof registry === "string" && hab.mgr.hasRegistryRoot(hab.pre, registry));
|
|
131
|
+
const fresh = exc.pendingGrant(grant, { ...parties, sender: parties.issuer, recipient: parties.issuee });
|
|
132
|
+
if (!held.length || fresh?.registries.some((registry) => !held.includes(registry)))
|
|
133
|
+
return null;
|
|
134
|
+
return { input, ...parties, registries: held };
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Whether `registry` has no committed state: its head is still the inception and no update is escrowed.
|
|
138
|
+
* A staged update waits in the missing-anchor or out-of-order escrow under its registry until the issuer's
|
|
139
|
+
* anchor is accepted, and an accepted one moves the head, so two keyed reads bounded by this registry
|
|
140
|
+
* decide it. Only then can a retained root be unused, because every derivation from a root, and every copy
|
|
141
|
+
* of it to another member (which `RegistryRoot` authorizes only for an accepted, issuer-anchored update),
|
|
142
|
+
* starts from a staged or accepted update. A remote update escrowed for this registry also counts, which
|
|
143
|
+
* is the conservative side.
|
|
144
|
+
*/
|
|
145
|
+
export function registryUncommitted(registryStore, registry) {
|
|
146
|
+
if (registryStore.headEvent(registry)?.ilk !== "rip")
|
|
147
|
+
return false;
|
|
148
|
+
for (const table of [registryStore.baser.maes, registryStore.baser.ooes]) {
|
|
149
|
+
for (const _ of table.getTopItemIter(registry))
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
88
154
|
/**
|
|
89
155
|
* Issuer/issuee DH for an explicitly approved pending Grant. Wire
|
|
90
156
|
* intake cannot approve work. Inject as ProtocolProcessor.qvy and register on
|
|
@@ -95,7 +161,7 @@ export function deriveRoot(privateKey, context) {
|
|
|
95
161
|
*/
|
|
96
162
|
export class Dhke {
|
|
97
163
|
/** Bind concrete local owners; construction grants no consent and writes nothing. */
|
|
98
|
-
constructor({ hab, exc, registryStore, rvy = hab.rvy, now = Date.now }) {
|
|
164
|
+
constructor({ hab, exc, registryStore, rvy = hab.rvy, now = Date.now, kram = true }) {
|
|
99
165
|
Object.defineProperty(this, "resource", {
|
|
100
166
|
enumerable: true,
|
|
101
167
|
configurable: true,
|
|
@@ -108,6 +174,13 @@ export class Dhke {
|
|
|
108
174
|
writable: true,
|
|
109
175
|
value: new Deck()
|
|
110
176
|
});
|
|
177
|
+
/** Completion cues for roots just retained by this group's custodian; feed `RootReplicator.replicate`. */
|
|
178
|
+
Object.defineProperty(this, "replicated", {
|
|
179
|
+
enumerable: true,
|
|
180
|
+
configurable: true,
|
|
181
|
+
writable: true,
|
|
182
|
+
value: new Deck()
|
|
183
|
+
});
|
|
111
184
|
Object.defineProperty(this, "pendingQueries", {
|
|
112
185
|
enumerable: true,
|
|
113
186
|
configurable: true,
|
|
@@ -156,6 +229,13 @@ export class Dhke {
|
|
|
156
229
|
writable: true,
|
|
157
230
|
value: void 0
|
|
158
231
|
});
|
|
232
|
+
Object.defineProperty(this, "kram", {
|
|
233
|
+
enumerable: true,
|
|
234
|
+
configurable: true,
|
|
235
|
+
writable: true,
|
|
236
|
+
value: void 0
|
|
237
|
+
});
|
|
238
|
+
this.kram = kram;
|
|
159
239
|
if (!(hab instanceof Hab) || hab.db !== exc.hby.db || rvy.db !== hab.db
|
|
160
240
|
|| exc.hby.habs.get(hab.pre) !== hab)
|
|
161
241
|
throw new ValidationError("DH requires a local signing habitat");
|
|
@@ -169,8 +249,20 @@ export class Dhke {
|
|
|
169
249
|
throw new ValidationError("DH requires a local signing member");
|
|
170
250
|
}
|
|
171
251
|
}
|
|
172
|
-
/**
|
|
252
|
+
/**
|
|
253
|
+
* Select one live fresh issuance and freeze its exact bodies, parties and registry order.
|
|
254
|
+
*
|
|
255
|
+
* A registry that already holds a root refuses (`Registry root conflicts with this live DH operation`)
|
|
256
|
+
* unless it has no committed state ({@link registryUncommitted}): then the held root was never used and
|
|
257
|
+
* this exchange, whose Grant is from the registry's issuer, overwrites it when it retains its own root,
|
|
258
|
+
* never at approval, so an interruption before retention leaves the old root. Once any update is staged
|
|
259
|
+
* or accepted the refusal is unchanged. A KERIpy peer keeps the old rule and refuses such a second
|
|
260
|
+
* exchange: with a KERIpy holder the issuer needs a fresh registry. One process also refuses a second
|
|
261
|
+
* live operation on a registry, so two pending Grants cannot clobber each other's root.
|
|
262
|
+
*/
|
|
173
263
|
approve(grant, { coordinator, custodian } = {}) {
|
|
264
|
+
if (!this.kram)
|
|
265
|
+
throw new ValidationError("DH requires KRAM: enable it with the runtime's kram option");
|
|
174
266
|
this.pruneQueries();
|
|
175
267
|
this.hab.mgr.requireRegistryRootAccess();
|
|
176
268
|
for (const op of this.operations.values()) {
|
|
@@ -184,27 +276,68 @@ export class Dhke {
|
|
|
184
276
|
return op.xid;
|
|
185
277
|
}
|
|
186
278
|
}
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
189
|
-
throw new ValidationError(
|
|
190
|
-
const
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
279
|
+
const scope = freshScope(this.hab, this.exc, grant);
|
|
280
|
+
if (typeof scope === "string")
|
|
281
|
+
throw new ValidationError(scope);
|
|
282
|
+
const op = this.frozen(scope, grant, { coordinator, custodian }, false);
|
|
283
|
+
for (const other of this.operations.values()) {
|
|
284
|
+
if (!other.abandoned && other.registries.some((registry) => op.registries.includes(registry))) {
|
|
285
|
+
throw new ValidationError("Another live DH operation uses this registry");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
for (const registry of op.registries) {
|
|
289
|
+
if (this.hab.mgr.hasRegistryRoot(this.hab.pre, registry) && registryUncommitted(this.registryStore, registry)) {
|
|
290
|
+
op.replaces.add(registry);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
this.roots(op);
|
|
294
|
+
this.operations.set(op.xid, op);
|
|
295
|
+
this.replayQuery(op.xid);
|
|
296
|
+
return op.xid;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Resume a completed exchange after a process restart, without new key exchange: rebuild the operation as
|
|
300
|
+
* completed from the roots held for the Grant's registries ({@link resumableExchange}). It holds no
|
|
301
|
+
* ephemeral key, so it cannot start, answer or renew a query; it can only {@link complete} and
|
|
302
|
+
* {@link finish}, which signs nothing and verifies the issuer's update against the held root. Needs an
|
|
303
|
+
* unlocked Keeper; wire intake never calls it. Repeating it returns the same transaction.
|
|
304
|
+
*
|
|
305
|
+
* @throws ValidationError unless the Grant is pending and holds a root for each registry in its scope.
|
|
306
|
+
*/
|
|
307
|
+
resume(grant, { coordinator, custodian } = {}) {
|
|
308
|
+
this.pruneQueries();
|
|
309
|
+
this.hab.mgr.requireRegistryRootAccess();
|
|
310
|
+
for (const op of this.operations.values()) {
|
|
311
|
+
if (op.grant !== grant)
|
|
312
|
+
continue;
|
|
313
|
+
if (!op.completed)
|
|
314
|
+
throw new ValidationError("DH is still exchanging keys for this Grant; nothing to resume");
|
|
315
|
+
this.pending(op);
|
|
316
|
+
return op.xid;
|
|
317
|
+
}
|
|
318
|
+
const scope = resumableExchange(this, grant);
|
|
319
|
+
if (!scope)
|
|
320
|
+
throw new ValidationError("No root is held for this pending Grant's registries");
|
|
321
|
+
const op = this.frozen(scope, grant, { coordinator, custodian }, true);
|
|
322
|
+
this.roots(op);
|
|
323
|
+
this.operations.set(op.xid, op);
|
|
324
|
+
this.pendingQueries.delete(op.xid);
|
|
325
|
+
this.dropHeld(op.xid);
|
|
326
|
+
return op.xid;
|
|
327
|
+
}
|
|
328
|
+
/** Freeze the exact pending Grant, parties and registry order into an operation; registers nothing. */
|
|
329
|
+
frozen(scope, grant, { coordinator, custodian }, completed) {
|
|
330
|
+
const { input, issuer, issuee, xid, registries } = scope;
|
|
195
331
|
if (this.operations.has(xid))
|
|
196
332
|
throw new ValidationError("Another Grant is selected for this transaction");
|
|
197
|
-
const context = this.exc.pendingGrant(grant, { xid, sender: issuer, recipient: issuee });
|
|
198
|
-
if (!context)
|
|
199
|
-
throw new ValidationError("DH requires authenticated fresh registry scope");
|
|
200
333
|
const op = {
|
|
201
334
|
xid,
|
|
202
335
|
grant,
|
|
203
336
|
issuer,
|
|
204
337
|
issuee,
|
|
205
|
-
raw:
|
|
338
|
+
raw: input.serder.raw.slice(),
|
|
206
339
|
bodies: (input.nests ?? []).map((nest) => nest.body.raw.slice()),
|
|
207
|
-
registries
|
|
340
|
+
registries,
|
|
208
341
|
privateKeys: new Map(),
|
|
209
342
|
publicKeys: {},
|
|
210
343
|
peer: null,
|
|
@@ -213,7 +346,8 @@ export class Dhke {
|
|
|
213
346
|
proposal: null,
|
|
214
347
|
contribution: null,
|
|
215
348
|
custody: null,
|
|
216
|
-
|
|
349
|
+
replaces: new Set(),
|
|
350
|
+
completed,
|
|
217
351
|
abandoned: false,
|
|
218
352
|
};
|
|
219
353
|
if (this.group) {
|
|
@@ -235,10 +369,17 @@ export class Dhke {
|
|
|
235
369
|
else if (coordinator !== undefined || custodian !== undefined) {
|
|
236
370
|
throw new ValidationError("Individual DH has no group coordinator");
|
|
237
371
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
372
|
+
return op;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Whether this owner already holds a live operation for `grant`. Two operation tables over one runtime
|
|
376
|
+
* (the host's and a command's own) use it so only the first to reach a Grant drives it.
|
|
377
|
+
*/
|
|
378
|
+
holds(grant) {
|
|
379
|
+
for (const op of this.operations.values())
|
|
380
|
+
if (op.grant === grant && !op.abandoned)
|
|
381
|
+
return true;
|
|
382
|
+
return false;
|
|
242
383
|
}
|
|
243
384
|
/** Return the stable issuer proposal until own threshold intake supplies the complete query. */
|
|
244
385
|
start(grant) {
|
|
@@ -506,12 +647,34 @@ export class Dhke {
|
|
|
506
647
|
/** Drop local ephemeral key references and permanently refuse this operation. */
|
|
507
648
|
abandon(xid) {
|
|
508
649
|
const retained = this.pendingQueries.delete(xid);
|
|
650
|
+
this.dropHeld(xid);
|
|
509
651
|
if (retained && !this.operations.has(xid))
|
|
510
652
|
return;
|
|
511
653
|
const op = this.operation(xid);
|
|
512
654
|
this.clearPrivate(op);
|
|
513
655
|
op.abandoned = true;
|
|
514
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Whether this local habitat is the party of DH transaction `xid` with `sender`.
|
|
659
|
+
*
|
|
660
|
+
* Messages carry no recipient, so a per-identifier registry selects the owner by transaction:
|
|
661
|
+
* an approved operation here, a stored Grant from `sender` addressed to this habitat, or, for a
|
|
662
|
+
* group, its own members' contributions, which KRAM must pool before this owner consents.
|
|
663
|
+
*/
|
|
664
|
+
inTransaction(sender, xid) {
|
|
665
|
+
return this.operations.has(xid) || (this.group && sender === this.hab.pre)
|
|
666
|
+
|| Dhke.recipients(this.hab.db, sender, xid).includes(this.hab.pre);
|
|
667
|
+
}
|
|
668
|
+
/** Recipients of the pending Grants `sender` opened in DH transaction `xid`, from KRAM-accepted store rows. */
|
|
669
|
+
static recipients(db, sender, xid) {
|
|
670
|
+
const recipients = [];
|
|
671
|
+
for (const [key] of db.tmsc.getTopItemIter([sender, xid])) {
|
|
672
|
+
const recipient = db.epse.get([key[2]])?.sad?.ri;
|
|
673
|
+
if (typeof recipient === "string")
|
|
674
|
+
recipients.push(recipient);
|
|
675
|
+
}
|
|
676
|
+
return recipients;
|
|
677
|
+
}
|
|
515
678
|
/** Release all process-local approvals and retry bytes; zero owned ephemeral scalar arrays. */
|
|
516
679
|
close() {
|
|
517
680
|
for (const op of this.operations.values())
|
|
@@ -519,6 +682,7 @@ export class Dhke {
|
|
|
519
682
|
this.operations.clear();
|
|
520
683
|
this.pendingQueries.clear();
|
|
521
684
|
this.outgoing.clear();
|
|
685
|
+
this.replicated.clear();
|
|
522
686
|
}
|
|
523
687
|
/** Retain public query evidence against one exact pending Grant, without creating keys or consent. */
|
|
524
688
|
retainQuery(envelope) {
|
|
@@ -540,11 +704,22 @@ export class Dhke {
|
|
|
540
704
|
for (const [, key] of entries)
|
|
541
705
|
decodePublicKey(key);
|
|
542
706
|
const expires = this.retainUntil(envelope, grant);
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
707
|
+
// After a restart the persisted copy is the prior one, so a successor is judged as it is before one.
|
|
708
|
+
const prior = this.pendingQueries.get(data.x) ?? this.loadHeld(data.x, grant.said);
|
|
709
|
+
if (prior && !bytesEqual(prior.envelope.serder.raw, query.raw)) {
|
|
710
|
+
// The issuer re-dates a query that aged before this side consented (`requery`): same sender, keys and
|
|
711
|
+
// Grant under a new date. It replaces the held one; any other difference is a conflict.
|
|
712
|
+
const held = this.parameters(prior.envelope.serder, "q");
|
|
713
|
+
const same = prior.envelope.serder.pre === query.pre && prior.grant === grant.said
|
|
714
|
+
&& JSON.stringify(Object.entries(held.pk).sort()) === JSON.stringify(entries.sort());
|
|
715
|
+
if (!same)
|
|
716
|
+
throw new ValidationError("Conflicting DH query");
|
|
717
|
+
}
|
|
718
|
+
if (!prior || !bytesEqual(prior.envelope.serder.raw, query.raw)) {
|
|
547
719
|
this.pendingQueries.set(data.x, { envelope: copyAuxiliaryQuery(envelope), expires, grant: grant.said });
|
|
720
|
+
// KRAM now holds this query as seen, so a resend of it is a replay: the held copy must outlive this process.
|
|
721
|
+
if (!envelope.nests.length)
|
|
722
|
+
this.hab.db.heldq.pin([data.x], auxiliaryQueryWire(envelope));
|
|
548
723
|
}
|
|
549
724
|
}
|
|
550
725
|
/** Expired evidence cannot survive another owner interaction. */
|
|
@@ -557,11 +732,32 @@ export class Dhke {
|
|
|
557
732
|
}
|
|
558
733
|
/** Consume the first authenticated request only after explicit approval; never renew either clock. */
|
|
559
734
|
replayQuery(xid) {
|
|
560
|
-
const
|
|
735
|
+
const grant = this.operations.get(xid)?.grant;
|
|
736
|
+
const pending = this.pendingQueries.get(xid) ?? (grant ? this.loadHeld(xid, grant) : undefined);
|
|
561
737
|
this.pendingQueries.delete(xid);
|
|
562
|
-
|
|
563
|
-
|
|
738
|
+
this.dropHeld(xid);
|
|
739
|
+
if (pending && pending.grant === grant && BigInt(this.now()) * 1000n < pending.expires) {
|
|
564
740
|
this.processQuery(pending.envelope);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
/** The persisted query for `xid` after a restart, with its lifetime recomputed from KRAM's durable records. */
|
|
744
|
+
loadHeld(xid, grant) {
|
|
745
|
+
const wire = this.hab.db.heldq.get([xid]);
|
|
746
|
+
const input = this.exc.retainedInput(grant, { pending: true });
|
|
747
|
+
if (!wire || !input)
|
|
748
|
+
return undefined;
|
|
749
|
+
try {
|
|
750
|
+
const envelope = restoreAuxiliaryQuery(wire);
|
|
751
|
+
return { envelope, expires: this.retainUntil(envelope, input.serder), grant };
|
|
752
|
+
}
|
|
753
|
+
catch (error) {
|
|
754
|
+
if (error instanceof ValidationError)
|
|
755
|
+
return undefined;
|
|
756
|
+
throw error;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
dropHeld(xid) {
|
|
760
|
+
this.hab.db.heldq.rem([xid]);
|
|
565
761
|
}
|
|
566
762
|
/** Bound process-local public evidence by the original query and accepted Grant lifetimes. */
|
|
567
763
|
retainUntil(envelope, grant) {
|
|
@@ -610,8 +806,12 @@ export class Dhke {
|
|
|
610
806
|
}
|
|
611
807
|
roots(op) {
|
|
612
808
|
for (const registry of op.registries) {
|
|
613
|
-
|
|
614
|
-
|
|
809
|
+
const held = this.hab.mgr.hasRegistryRoot(this.hab.pre, registry);
|
|
810
|
+
if (held !== op.completed && !(held && op.replaces.has(registry))) {
|
|
811
|
+
throw new ValidationError(held
|
|
812
|
+
? "Registry root conflicts with this live DH operation: a DH-issued registry must not have a custody root, "
|
|
813
|
+
+ "so do not call createCustody for it before issuance (use a registry without custody)"
|
|
814
|
+
: "Registry root conflicts with this live DH operation");
|
|
615
815
|
}
|
|
616
816
|
}
|
|
617
817
|
}
|
|
@@ -648,6 +848,9 @@ export class Dhke {
|
|
|
648
848
|
return { op, peer };
|
|
649
849
|
}
|
|
650
850
|
generate(op) {
|
|
851
|
+
// A completed operation, including a resumed one, never holds or makes ephemeral keys again.
|
|
852
|
+
if (op.completed)
|
|
853
|
+
throw new ValidationError("DH operation has already completed");
|
|
651
854
|
this.custody(op, true);
|
|
652
855
|
if (op.privateKeys.size)
|
|
653
856
|
return;
|
|
@@ -675,11 +878,20 @@ export class Dhke {
|
|
|
675
878
|
]));
|
|
676
879
|
}
|
|
677
880
|
retain(op, peer, roots) {
|
|
678
|
-
for (const [registry, root] of roots)
|
|
679
|
-
|
|
881
|
+
for (const [registry, root] of roots) {
|
|
882
|
+
const replacing = op.replaces.has(registry);
|
|
883
|
+
// Recheck at commit time, from stores: the held root must still be unused.
|
|
884
|
+
if (replacing && !registryUncommitted(this.registryStore, registry)) {
|
|
885
|
+
throw new ValidationError("Registry root conflicts with this live DH operation");
|
|
886
|
+
}
|
|
887
|
+
this.hab.mgr.putRegistryRoot(this.hab.pre, registry, root, replacing);
|
|
888
|
+
}
|
|
680
889
|
op.peer = { ...peer };
|
|
681
890
|
op.completed = true;
|
|
682
891
|
this.clearPrivate(op);
|
|
892
|
+
// Every current member must hold every root; the custodian replicates.
|
|
893
|
+
if (this.group)
|
|
894
|
+
this.replicated.push({ gid: this.hab.pre, registries: [...roots.keys()] });
|
|
683
895
|
}
|
|
684
896
|
clearPrivate(op) {
|
|
685
897
|
for (const key of op.privateKeys.values())
|
|
@@ -76,7 +76,7 @@ export class RegistryObserver {
|
|
|
76
76
|
const baser = this.store.baser;
|
|
77
77
|
if (baser.readonly)
|
|
78
78
|
throw new DatabaseOperationError("Cannot write readonly registry storage.");
|
|
79
|
-
return baser.
|
|
79
|
+
return baser.transaction(() => {
|
|
80
80
|
this.store.putEvent(serder);
|
|
81
81
|
this.store.escrowMissingAnchor(event.regid, Number(event.sn), event.said);
|
|
82
82
|
if (opening)
|
|
@@ -106,7 +106,7 @@ export class RegistryObserver {
|
|
|
106
106
|
}
|
|
107
107
|
/** Stored inception is durable issuer identity, including while its anchor is still absent. */
|
|
108
108
|
engine(regid) {
|
|
109
|
-
if (!this.store.baser.
|
|
109
|
+
if (!this.store.baser.opened)
|
|
110
110
|
throw new DatabaseNotOpenError("Registry observer store is closed.");
|
|
111
111
|
const rip = this.store.event(regid);
|
|
112
112
|
if (!rip) {
|