@origintrail-official/dkg-agent 10.0.19 → 10.0.21
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/dist/approved-private-replica.d.ts +54 -0
- package/dist/approved-private-replica.d.ts.map +1 -0
- package/dist/approved-private-replica.js +148 -0
- package/dist/approved-private-replica.js.map +1 -0
- package/dist/bounded-operation.d.ts +2 -0
- package/dist/bounded-operation.d.ts.map +1 -1
- package/dist/bounded-operation.js +5 -0
- package/dist/bounded-operation.js.map +1 -1
- package/dist/chain-finality-confirmations-v1.d.ts +7 -0
- package/dist/chain-finality-confirmations-v1.d.ts.map +1 -0
- package/dist/chain-finality-confirmations-v1.js +9 -0
- package/dist/chain-finality-confirmations-v1.js.map +1 -0
- package/dist/chain-reconciler.d.ts +23 -0
- package/dist/chain-reconciler.d.ts.map +1 -1
- package/dist/chain-reconciler.js +35 -0
- package/dist/chain-reconciler.js.map +1 -1
- package/dist/confirmed-graph-scoped-vm-resolver.d.ts +7 -1
- package/dist/confirmed-graph-scoped-vm-resolver.d.ts.map +1 -1
- package/dist/confirmed-graph-scoped-vm-resolver.js +5 -3
- package/dist/confirmed-graph-scoped-vm-resolver.js.map +1 -1
- package/dist/context-graph-authority-dependency.d.ts +11 -0
- package/dist/context-graph-authority-dependency.d.ts.map +1 -0
- package/dist/context-graph-authority-dependency.js +50 -0
- package/dist/context-graph-authority-dependency.js.map +1 -0
- package/dist/context-graph-binding-state.d.ts +6 -0
- package/dist/context-graph-binding-state.d.ts.map +1 -1
- package/dist/context-graph-binding-state.js +17 -10
- package/dist/context-graph-binding-state.js.map +1 -1
- package/dist/context-graph-claim-proof.d.ts +74 -0
- package/dist/context-graph-claim-proof.d.ts.map +1 -0
- package/dist/context-graph-claim-proof.js +137 -0
- package/dist/context-graph-claim-proof.js.map +1 -0
- package/dist/context-graph-member-proof.d.ts +33 -0
- package/dist/context-graph-member-proof.d.ts.map +1 -0
- package/dist/context-graph-member-proof.js +142 -0
- package/dist/context-graph-member-proof.js.map +1 -0
- package/dist/context-graph-membership-persist-scheduler.d.ts +7 -23
- package/dist/context-graph-membership-persist-scheduler.d.ts.map +1 -1
- package/dist/context-graph-membership-persist-scheduler.js +12 -88
- package/dist/context-graph-membership-persist-scheduler.js.map +1 -1
- package/dist/context-graph-meta-confirmation.d.ts +22 -2
- package/dist/context-graph-meta-confirmation.d.ts.map +1 -1
- package/dist/context-graph-meta-confirmation.js +54 -23
- package/dist/context-graph-meta-confirmation.js.map +1 -1
- package/dist/context-graph-meta-projection.d.ts +13 -2
- package/dist/context-graph-meta-projection.d.ts.map +1 -1
- package/dist/context-graph-meta-projection.js +61 -24
- package/dist/context-graph-meta-projection.js.map +1 -1
- package/dist/context-graph-metadata-relocation.d.ts +18 -30
- package/dist/context-graph-metadata-relocation.d.ts.map +1 -1
- package/dist/context-graph-metadata-relocation.js +32 -2
- package/dist/context-graph-metadata-relocation.js.map +1 -1
- package/dist/context-graph-private-meta-proof.d.ts +8 -9
- package/dist/context-graph-private-meta-proof.d.ts.map +1 -1
- package/dist/context-graph-private-meta-proof.js +25 -89
- package/dist/context-graph-private-meta-proof.js.map +1 -1
- package/dist/context-graph-public-meta-proof.d.ts +11 -1
- package/dist/context-graph-public-meta-proof.d.ts.map +1 -1
- package/dist/context-graph-public-meta-proof.js +23 -3
- package/dist/context-graph-public-meta-proof.js.map +1 -1
- package/dist/context-graph-read-authority.d.ts +30 -3
- package/dist/context-graph-read-authority.d.ts.map +1 -1
- package/dist/context-graph-read-authority.js +62 -18
- package/dist/context-graph-read-authority.js.map +1 -1
- package/dist/context-graph-storage-discovery.d.ts +14 -4
- package/dist/context-graph-storage-discovery.d.ts.map +1 -1
- package/dist/context-graph-storage-discovery.js +27 -7
- package/dist/context-graph-storage-discovery.js.map +1 -1
- package/dist/context-graph-subscription-authority-recovery.d.ts +7 -0
- package/dist/context-graph-subscription-authority-recovery.d.ts.map +1 -1
- package/dist/context-graph-subscription-authority-recovery.js +1 -0
- package/dist/context-graph-subscription-authority-recovery.js.map +1 -1
- package/dist/context-graph-subscription-persist-scheduler.d.ts +52 -0
- package/dist/context-graph-subscription-persist-scheduler.d.ts.map +1 -0
- package/dist/context-graph-subscription-persist-scheduler.js +78 -0
- package/dist/context-graph-subscription-persist-scheduler.js.map +1 -0
- package/dist/curator-dial-address.d.ts +16 -0
- package/dist/curator-dial-address.d.ts.map +1 -0
- package/dist/curator-dial-address.js +58 -0
- package/dist/curator-dial-address.js.map +1 -0
- package/dist/curator-meta-refresh.d.ts +18 -4
- package/dist/curator-meta-refresh.d.ts.map +1 -1
- package/dist/curator-meta-refresh.js +61 -58
- package/dist/curator-meta-refresh.js.map +1 -1
- package/dist/curator-peer-connection.d.ts +21 -0
- package/dist/curator-peer-connection.d.ts.map +1 -0
- package/dist/curator-peer-connection.js +41 -0
- package/dist/curator-peer-connection.js.map +1 -0
- package/dist/dkg-agent-agents-phonebook.d.ts +41 -0
- package/dist/dkg-agent-agents-phonebook.d.ts.map +1 -0
- package/dist/dkg-agent-agents-phonebook.js +155 -0
- package/dist/dkg-agent-agents-phonebook.js.map +1 -0
- package/dist/dkg-agent-base.d.ts +162 -24
- package/dist/dkg-agent-base.d.ts.map +1 -1
- package/dist/dkg-agent-base.js +175 -147
- package/dist/dkg-agent-base.js.map +1 -1
- package/dist/dkg-agent-cg-chain-observation.d.ts +6 -1
- package/dist/dkg-agent-cg-chain-observation.d.ts.map +1 -1
- package/dist/dkg-agent-cg-chain-observation.js +20 -5
- package/dist/dkg-agent-cg-chain-observation.js.map +1 -1
- package/dist/dkg-agent-cg-name-resolution.d.ts +38 -2
- package/dist/dkg-agent-cg-name-resolution.d.ts.map +1 -1
- package/dist/dkg-agent-cg-name-resolution.js +100 -8
- package/dist/dkg-agent-cg-name-resolution.js.map +1 -1
- package/dist/dkg-agent-cg-registry.d.ts +43 -3
- package/dist/dkg-agent-cg-registry.d.ts.map +1 -1
- package/dist/dkg-agent-cg-registry.js +267 -129
- package/dist/dkg-agent-cg-registry.js.map +1 -1
- package/dist/dkg-agent-cg-resolve.d.ts +6 -4
- package/dist/dkg-agent-cg-resolve.d.ts.map +1 -1
- package/dist/dkg-agent-cg-resolve.js +40 -18
- package/dist/dkg-agent-cg-resolve.js.map +1 -1
- package/dist/dkg-agent-constants.d.ts +10 -2
- package/dist/dkg-agent-constants.d.ts.map +1 -1
- package/dist/dkg-agent-constants.js +10 -2
- package/dist/dkg-agent-constants.js.map +1 -1
- package/dist/dkg-agent-context-graph.d.ts.map +1 -1
- package/dist/dkg-agent-context-graph.js +1 -5
- package/dist/dkg-agent-context-graph.js.map +1 -1
- package/dist/dkg-agent-crypto.d.ts +128 -21
- package/dist/dkg-agent-crypto.d.ts.map +1 -1
- package/dist/dkg-agent-crypto.js +824 -176
- package/dist/dkg-agent-crypto.js.map +1 -1
- package/dist/dkg-agent-diagnostics.d.ts.map +1 -1
- package/dist/dkg-agent-diagnostics.js +4 -3
- package/dist/dkg-agent-diagnostics.js.map +1 -1
- package/dist/dkg-agent-helpers.d.ts +2 -2
- package/dist/dkg-agent-helpers.d.ts.map +1 -1
- package/dist/dkg-agent-helpers.js +3 -3
- package/dist/dkg-agent-helpers.js.map +1 -1
- package/dist/dkg-agent-join.d.ts +12 -1
- package/dist/dkg-agent-join.d.ts.map +1 -1
- package/dist/dkg-agent-join.js +80 -92
- package/dist/dkg-agent-join.js.map +1 -1
- package/dist/dkg-agent-lifecycle.d.ts +129 -22
- package/dist/dkg-agent-lifecycle.d.ts.map +1 -1
- package/dist/dkg-agent-lifecycle.js +690 -211
- package/dist/dkg-agent-lifecycle.js.map +1 -1
- package/dist/dkg-agent-publish.d.ts +33 -40
- package/dist/dkg-agent-publish.d.ts.map +1 -1
- package/dist/dkg-agent-publish.js +194 -281
- package/dist/dkg-agent-publish.js.map +1 -1
- package/dist/dkg-agent-query.d.ts +7 -0
- package/dist/dkg-agent-query.d.ts.map +1 -1
- package/dist/dkg-agent-query.js +102 -86
- package/dist/dkg-agent-query.js.map +1 -1
- package/dist/dkg-agent-registered-private-empty-vm.d.ts +70 -0
- package/dist/dkg-agent-registered-private-empty-vm.d.ts.map +1 -0
- package/dist/dkg-agent-registered-private-empty-vm.js +133 -0
- package/dist/dkg-agent-registered-private-empty-vm.js.map +1 -0
- package/dist/dkg-agent-rfc64-catalog-auto-publish.d.ts +8 -3
- package/dist/dkg-agent-rfc64-catalog-auto-publish.d.ts.map +1 -1
- package/dist/dkg-agent-rfc64-catalog-auto-publish.js +45 -51
- package/dist/dkg-agent-rfc64-catalog-auto-publish.js.map +1 -1
- package/dist/dkg-agent-rfc64-catalog.d.ts +87 -80
- package/dist/dkg-agent-rfc64-catalog.d.ts.map +1 -1
- package/dist/dkg-agent-rfc64-catalog.js +726 -476
- package/dist/dkg-agent-rfc64-catalog.js.map +1 -1
- package/dist/dkg-agent-rfc64-meta-bootstrap.d.ts +6 -1
- package/dist/dkg-agent-rfc64-meta-bootstrap.d.ts.map +1 -1
- package/dist/dkg-agent-rfc64-meta-bootstrap.js +29 -13
- package/dist/dkg-agent-rfc64-meta-bootstrap.js.map +1 -1
- package/dist/dkg-agent-rfc64-swm-catalog-projection-supervisor.d.ts +8 -0
- package/dist/dkg-agent-rfc64-swm-catalog-projection-supervisor.d.ts.map +1 -1
- package/dist/dkg-agent-rfc64-swm-catalog-projection-supervisor.js +249 -40
- package/dist/dkg-agent-rfc64-swm-catalog-projection-supervisor.js.map +1 -1
- package/dist/dkg-agent-rfc64-swm-catalog-projection.d.ts.map +1 -1
- package/dist/dkg-agent-rfc64-swm-catalog-projection.js +3 -2
- package/dist/dkg-agent-rfc64-swm-catalog-projection.js.map +1 -1
- package/dist/dkg-agent-swm-host.d.ts +217 -52
- package/dist/dkg-agent-swm-host.d.ts.map +1 -1
- package/dist/dkg-agent-swm-host.js +1305 -858
- package/dist/dkg-agent-swm-host.js.map +1 -1
- package/dist/dkg-agent-swm-state.d.ts +15 -0
- package/dist/dkg-agent-swm-state.d.ts.map +1 -1
- package/dist/dkg-agent-swm-state.js +43 -0
- package/dist/dkg-agent-swm-state.js.map +1 -1
- package/dist/dkg-agent-swm-substrate.d.ts +49 -8
- package/dist/dkg-agent-swm-substrate.d.ts.map +1 -1
- package/dist/dkg-agent-swm-substrate.js +219 -46
- package/dist/dkg-agent-swm-substrate.js.map +1 -1
- package/dist/dkg-agent-types.d.ts +86 -27
- package/dist/dkg-agent-types.d.ts.map +1 -1
- package/dist/dkg-agent-types.js.map +1 -1
- package/dist/dkg-agent-vm-promotion.d.ts +4 -0
- package/dist/dkg-agent-vm-promotion.d.ts.map +1 -1
- package/dist/dkg-agent-vm-promotion.js +40 -5
- package/dist/dkg-agent-vm-promotion.js.map +1 -1
- package/dist/dkg-agent-vm-reconcile-scheduling.d.ts +7 -0
- package/dist/dkg-agent-vm-reconcile-scheduling.d.ts.map +1 -1
- package/dist/dkg-agent-vm-reconcile-scheduling.js +18 -0
- package/dist/dkg-agent-vm-reconcile-scheduling.js.map +1 -1
- package/dist/dkg-agent.d.ts +31 -2
- package/dist/dkg-agent.d.ts.map +1 -1
- package/dist/dkg-agent.js +188 -72
- package/dist/dkg-agent.js.map +1 -1
- package/dist/exact-graph-content-verifier.d.ts.map +1 -1
- package/dist/exact-graph-content-verifier.js +3 -2
- package/dist/exact-graph-content-verifier.js.map +1 -1
- package/dist/finalization-handler.d.ts +26 -211
- package/dist/finalization-handler.d.ts.map +1 -1
- package/dist/finalization-handler.js +94 -1652
- package/dist/finalization-handler.js.map +1 -1
- package/dist/finalization-recovery-sqlite-displacement.d.ts +37 -0
- package/dist/finalization-recovery-sqlite-displacement.d.ts.map +1 -0
- package/dist/finalization-recovery-sqlite-displacement.js +102 -0
- package/dist/finalization-recovery-sqlite-displacement.js.map +1 -0
- package/dist/finalization-recovery-sqlite-policy.d.ts +20 -4
- package/dist/finalization-recovery-sqlite-policy.d.ts.map +1 -1
- package/dist/finalization-recovery-sqlite-policy.js +21 -5
- package/dist/finalization-recovery-sqlite-policy.js.map +1 -1
- package/dist/finalization-recovery-sqlite-rows.d.ts +53 -0
- package/dist/finalization-recovery-sqlite-rows.d.ts.map +1 -0
- package/dist/finalization-recovery-sqlite-rows.js +77 -0
- package/dist/finalization-recovery-sqlite-rows.js.map +1 -0
- package/dist/finalization-recovery-sqlite-store.d.ts +10 -4
- package/dist/finalization-recovery-sqlite-store.d.ts.map +1 -1
- package/dist/finalization-recovery-sqlite-store.js +49 -50
- package/dist/finalization-recovery-sqlite-store.js.map +1 -1
- package/dist/finalization-recovery-store.d.ts +18 -0
- package/dist/finalization-recovery-store.d.ts.map +1 -1
- package/dist/finalization-recovery-store.js +24 -0
- package/dist/finalization-recovery-store.js.map +1 -1
- package/dist/finalization-recovery-worker.js +1 -1
- package/dist/finalization-recovery-worker.js.map +1 -1
- package/dist/finalization-recovery.d.ts +2 -3
- package/dist/finalization-recovery.d.ts.map +1 -1
- package/dist/finalization-recovery.js +12 -9
- package/dist/finalization-recovery.js.map +1 -1
- package/dist/finalized-authority-cold-resolution.d.ts +6 -1
- package/dist/finalized-authority-cold-resolution.d.ts.map +1 -1
- package/dist/finalized-authority-cold-resolution.js +22 -3
- package/dist/finalized-authority-cold-resolution.js.map +1 -1
- package/dist/gossip-publish-handler.d.ts.map +1 -1
- package/dist/gossip-publish-handler.js +4 -2
- package/dist/gossip-publish-handler.js.map +1 -1
- package/dist/gossip-session.d.ts +29 -0
- package/dist/gossip-session.d.ts.map +1 -0
- package/dist/gossip-session.js +48 -0
- package/dist/gossip-session.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/context-graph-authority/approved-member-acceptance.d.ts +61 -0
- package/dist/internal/context-graph-authority/approved-member-acceptance.d.ts.map +1 -0
- package/dist/internal/context-graph-authority/approved-member-acceptance.js +75 -0
- package/dist/internal/context-graph-authority/approved-member-acceptance.js.map +1 -0
- package/dist/internal/context-graph-authority/context-graph-agent-gate-authority.d.ts +5 -5
- package/dist/internal/context-graph-authority/context-graph-agent-gate-authority.d.ts.map +1 -1
- package/dist/internal/context-graph-authority/context-graph-agent-gate-authority.js +59 -49
- package/dist/internal/context-graph-authority/context-graph-agent-gate-authority.js.map +1 -1
- package/dist/internal/context-graph-authority/context-graph-authority.d.ts +1 -0
- package/dist/internal/context-graph-authority/context-graph-authority.d.ts.map +1 -1
- package/dist/internal/context-graph-authority/context-graph-authority.js +25 -0
- package/dist/internal/context-graph-authority/context-graph-authority.js.map +1 -1
- package/dist/internal/context-graph-authority/finalized-target-projection.d.ts +17 -0
- package/dist/internal/context-graph-authority/finalized-target-projection.d.ts.map +1 -0
- package/dist/internal/context-graph-authority/finalized-target-projection.js +36 -0
- package/dist/internal/context-graph-authority/finalized-target-projection.js.map +1 -0
- package/dist/internal/context-graph-authority/swm-transport-authority.d.ts +84 -0
- package/dist/internal/context-graph-authority/swm-transport-authority.d.ts.map +1 -0
- package/dist/internal/context-graph-authority/swm-transport-authority.js +175 -0
- package/dist/internal/context-graph-authority/swm-transport-authority.js.map +1 -0
- package/dist/internal/context-graph-binding-abort.d.ts +3 -0
- package/dist/internal/context-graph-binding-abort.d.ts.map +1 -0
- package/dist/internal/context-graph-binding-abort.js +32 -0
- package/dist/internal/context-graph-binding-abort.js.map +1 -0
- package/dist/internal/context-graph-cache-invalidating-store.d.ts +3 -0
- package/dist/internal/context-graph-cache-invalidating-store.d.ts.map +1 -0
- package/dist/internal/context-graph-cache-invalidating-store.js +167 -0
- package/dist/internal/context-graph-cache-invalidating-store.js.map +1 -0
- package/dist/internal/context-graph-meta-record-copy.d.ts +3 -0
- package/dist/internal/context-graph-meta-record-copy.d.ts.map +1 -0
- package/dist/internal/context-graph-meta-record-copy.js +21 -0
- package/dist/internal/context-graph-meta-record-copy.js.map +1 -0
- package/dist/internal/gossip/host-mode-handler.d.ts +11 -0
- package/dist/internal/gossip/host-mode-handler.d.ts.map +1 -0
- package/dist/internal/gossip/host-mode-handler.js +41 -0
- package/dist/internal/gossip/host-mode-handler.js.map +1 -0
- package/dist/internal/join-encryption-key-bundle.d.ts +10 -0
- package/dist/internal/join-encryption-key-bundle.d.ts.map +1 -0
- package/dist/internal/join-encryption-key-bundle.js +72 -0
- package/dist/internal/join-encryption-key-bundle.js.map +1 -0
- package/dist/internal/knowledge-asset-vm-publish-request.d.ts +31 -0
- package/dist/internal/knowledge-asset-vm-publish-request.d.ts.map +1 -0
- package/dist/internal/knowledge-asset-vm-publish-request.js +91 -0
- package/dist/internal/knowledge-asset-vm-publish-request.js.map +1 -0
- package/dist/internal/lifecycle-sync-policy.d.ts +5 -0
- package/dist/internal/lifecycle-sync-policy.d.ts.map +1 -0
- package/dist/internal/lifecycle-sync-policy.js +12 -0
- package/dist/internal/lifecycle-sync-policy.js.map +1 -0
- package/dist/internal/local-private-member.d.ts +14 -0
- package/dist/internal/local-private-member.d.ts.map +1 -0
- package/dist/internal/local-private-member.js +21 -0
- package/dist/internal/local-private-member.js.map +1 -0
- package/dist/internal/promote/assertion-promote-precommit.d.ts +41 -1
- package/dist/internal/promote/assertion-promote-precommit.d.ts.map +1 -1
- package/dist/internal/promote/assertion-promote-precommit.js +79 -22
- package/dist/internal/promote/assertion-promote-precommit.js.map +1 -1
- package/dist/internal/storage-ack-owned-request.d.ts +16 -0
- package/dist/internal/storage-ack-owned-request.d.ts.map +1 -0
- package/dist/internal/storage-ack-owned-request.js +16 -0
- package/dist/internal/storage-ack-owned-request.js.map +1 -0
- package/dist/internal/vm-reconcile-local-admission-wait.d.ts +96 -0
- package/dist/internal/vm-reconcile-local-admission-wait.d.ts.map +1 -0
- package/dist/internal/vm-reconcile-local-admission-wait.js +226 -0
- package/dist/internal/vm-reconcile-local-admission-wait.js.map +1 -0
- package/dist/internal/vm-reconcile-read-authority.d.ts +27 -0
- package/dist/internal/vm-reconcile-read-authority.d.ts.map +1 -0
- package/dist/internal/vm-reconcile-read-authority.js +33 -0
- package/dist/internal/vm-reconcile-read-authority.js.map +1 -0
- package/dist/internal/vm-reconcile-sweep-admission.d.ts +2 -0
- package/dist/internal/vm-reconcile-sweep-admission.d.ts.map +1 -1
- package/dist/internal/vm-reconcile-sweep.d.ts +16 -4
- package/dist/internal/vm-reconcile-sweep.d.ts.map +1 -1
- package/dist/internal/vm-reconcile-sweep.js +91 -50
- package/dist/internal/vm-reconcile-sweep.js.map +1 -1
- package/dist/internal/workspace-projected-delegatees.d.ts +3 -0
- package/dist/internal/workspace-projected-delegatees.d.ts.map +1 -0
- package/dist/internal/workspace-projected-delegatees.js +34 -0
- package/dist/internal/workspace-projected-delegatees.js.map +1 -0
- package/dist/join-approval-restart-projection.d.ts +14 -0
- package/dist/join-approval-restart-projection.d.ts.map +1 -0
- package/dist/join-approval-restart-projection.js +32 -0
- package/dist/join-approval-restart-projection.js.map +1 -0
- package/dist/keyed-persist-scheduler.d.ts +72 -0
- package/dist/keyed-persist-scheduler.d.ts.map +1 -0
- package/dist/keyed-persist-scheduler.js +140 -0
- package/dist/keyed-persist-scheduler.js.map +1 -0
- package/dist/map-with-concurrency.d.ts +7 -0
- package/dist/map-with-concurrency.d.ts.map +1 -1
- package/dist/map-with-concurrency.js +36 -0
- package/dist/map-with-concurrency.js.map +1 -1
- package/dist/p2p/network-admission-coordinator.d.ts +15 -0
- package/dist/p2p/network-admission-coordinator.d.ts.map +1 -1
- package/dist/p2p/network-admission-coordinator.js +20 -2
- package/dist/p2p/network-admission-coordinator.js.map +1 -1
- package/dist/p2p/peer-connect.d.ts +10 -1
- package/dist/p2p/peer-connect.d.ts.map +1 -1
- package/dist/p2p/peer-connect.js +11 -2
- package/dist/p2p/peer-connect.js.map +1 -1
- package/dist/p2p/peer-selection.d.ts +8 -0
- package/dist/p2p/peer-selection.d.ts.map +1 -1
- package/dist/p2p/peer-selection.js +21 -12
- package/dist/p2p/peer-selection.js.map +1 -1
- package/dist/p2p/protocol-readiness.d.ts +3 -3
- package/dist/p2p/protocol-readiness.d.ts.map +1 -1
- package/dist/p2p/protocol-readiness.js +4 -3
- package/dist/p2p/protocol-readiness.js.map +1 -1
- package/dist/prepare-unscoped-context-graph-read-checks.d.ts.map +1 -1
- package/dist/prepare-unscoped-context-graph-read-checks.js +12 -0
- package/dist/prepare-unscoped-context-graph-read-checks.js.map +1 -1
- package/dist/registered-context-graph-authority.d.ts +19 -0
- package/dist/registered-context-graph-authority.d.ts.map +1 -1
- package/dist/registered-private-empty-vm-attempt-v1.d.ts +34 -0
- package/dist/registered-private-empty-vm-attempt-v1.d.ts.map +1 -0
- package/dist/registered-private-empty-vm-attempt-v1.js +120 -0
- package/dist/registered-private-empty-vm-attempt-v1.js.map +1 -0
- package/dist/reserved-ka-id-allocation.d.ts +12 -0
- package/dist/reserved-ka-id-allocation.d.ts.map +1 -0
- package/dist/reserved-ka-id-allocation.js +25 -0
- package/dist/reserved-ka-id-allocation.js.map +1 -0
- package/dist/rfc64/applied-catalog-authority-transition-v1.d.ts.map +1 -1
- package/dist/rfc64/applied-catalog-authority-transition-v1.js +15 -17
- package/dist/rfc64/applied-catalog-authority-transition-v1.js.map +1 -1
- package/dist/rfc64/authority-rpc-circuit-breaker-v1.d.ts +5 -3
- package/dist/rfc64/authority-rpc-circuit-breaker-v1.d.ts.map +1 -1
- package/dist/rfc64/authority-rpc-circuit-breaker-v1.js +9 -0
- package/dist/rfc64/authority-rpc-circuit-breaker-v1.js.map +1 -1
- package/dist/rfc64/catalog-completion-evidence-v1.d.ts +38 -0
- package/dist/rfc64/catalog-completion-evidence-v1.d.ts.map +1 -0
- package/dist/rfc64/catalog-completion-evidence-v1.js +49 -0
- package/dist/rfc64/catalog-completion-evidence-v1.js.map +1 -0
- package/dist/rfc64/catalog-operational-applied-heads-v1.d.ts +12 -13
- package/dist/rfc64/catalog-operational-applied-heads-v1.d.ts.map +1 -1
- package/dist/rfc64/catalog-operational-applied-heads-v1.js +17 -52
- package/dist/rfc64/catalog-operational-applied-heads-v1.js.map +1 -1
- package/dist/rfc64/catalog-operational-reads-v1.d.ts +13 -0
- package/dist/rfc64/catalog-operational-reads-v1.d.ts.map +1 -0
- package/dist/rfc64/catalog-operational-reads-v1.js +56 -0
- package/dist/rfc64/catalog-operational-reads-v1.js.map +1 -0
- package/dist/rfc64/catalog-operational-targets-v1.d.ts +55 -0
- package/dist/rfc64/catalog-operational-targets-v1.d.ts.map +1 -0
- package/dist/rfc64/catalog-operational-targets-v1.js +379 -0
- package/dist/rfc64/catalog-operational-targets-v1.js.map +1 -0
- package/dist/rfc64/catalog-repair-diagnostics-v1.d.ts +28 -0
- package/dist/rfc64/catalog-repair-diagnostics-v1.d.ts.map +1 -0
- package/dist/rfc64/catalog-repair-diagnostics-v1.js +93 -0
- package/dist/rfc64/catalog-repair-diagnostics-v1.js.map +1 -0
- package/dist/rfc64/catalog-repair-retry-v1.d.ts +13 -0
- package/dist/rfc64/catalog-repair-retry-v1.d.ts.map +1 -0
- package/dist/rfc64/catalog-repair-retry-v1.js +39 -0
- package/dist/rfc64/catalog-repair-retry-v1.js.map +1 -0
- package/dist/rfc64/catalog-replay-recovery-runtime-v1.d.ts +52 -0
- package/dist/rfc64/catalog-replay-recovery-runtime-v1.d.ts.map +1 -1
- package/dist/rfc64/catalog-replay-recovery-runtime-v1.js +188 -32
- package/dist/rfc64/catalog-replay-recovery-runtime-v1.js.map +1 -1
- package/dist/rfc64/catalog-replay-snapshot-runtime-v1.d.ts +2 -8
- package/dist/rfc64/catalog-replay-snapshot-runtime-v1.d.ts.map +1 -1
- package/dist/rfc64/catalog-replay-snapshot-runtime-v1.js +10 -37
- package/dist/rfc64/catalog-replay-snapshot-runtime-v1.js.map +1 -1
- package/dist/rfc64/catalog-rollout-authority-v1.d.ts +13 -0
- package/dist/rfc64/catalog-rollout-authority-v1.d.ts.map +1 -1
- package/dist/rfc64/catalog-rollout-authority-v1.js +11 -0
- package/dist/rfc64/catalog-rollout-authority-v1.js.map +1 -1
- package/dist/rfc64/catalog-row-authorship.d.ts +12 -0
- package/dist/rfc64/catalog-row-authorship.d.ts.map +1 -1
- package/dist/rfc64/catalog-row-authorship.js +110 -57
- package/dist/rfc64/catalog-row-authorship.js.map +1 -1
- package/dist/rfc64/inventory-v1/candidate.d.ts +31 -10
- package/dist/rfc64/inventory-v1/candidate.d.ts.map +1 -1
- package/dist/rfc64/inventory-v1/candidate.js +51 -16
- package/dist/rfc64/inventory-v1/candidate.js.map +1 -1
- package/dist/rfc64/inventory-v1/index.d.ts +1 -1
- package/dist/rfc64/inventory-v1/index.d.ts.map +1 -1
- package/dist/rfc64/inventory-v1/index.js +1 -1
- package/dist/rfc64/inventory-v1/index.js.map +1 -1
- package/dist/rfc64/inventory-v1/open.d.ts.map +1 -1
- package/dist/rfc64/inventory-v1/open.js +7 -4
- package/dist/rfc64/inventory-v1/open.js.map +1 -1
- package/dist/rfc64/inventory-v1/swm-author-inventory-persistence.d.ts +3 -1
- package/dist/rfc64/inventory-v1/swm-author-inventory-persistence.d.ts.map +1 -1
- package/dist/rfc64/inventory-v1/swm-author-inventory-persistence.js +15 -0
- package/dist/rfc64/inventory-v1/swm-author-inventory-persistence.js.map +1 -1
- package/dist/rfc64/legacy-swm-boundary-codec-v1.d.ts +25 -0
- package/dist/rfc64/legacy-swm-boundary-codec-v1.d.ts.map +1 -0
- package/dist/rfc64/legacy-swm-boundary-codec-v1.js +127 -0
- package/dist/rfc64/legacy-swm-boundary-codec-v1.js.map +1 -0
- package/dist/rfc64/legacy-swm-boundary-v1.d.ts +12 -0
- package/dist/rfc64/legacy-swm-boundary-v1.d.ts.map +1 -1
- package/dist/rfc64/legacy-swm-boundary-v1.js +83 -144
- package/dist/rfc64/legacy-swm-boundary-v1.js.map +1 -1
- package/dist/rfc64/private-catalog-subscription-readiness-v1.d.ts +33 -0
- package/dist/rfc64/private-catalog-subscription-readiness-v1.d.ts.map +1 -0
- package/dist/rfc64/private-catalog-subscription-readiness-v1.js +97 -0
- package/dist/rfc64/private-catalog-subscription-readiness-v1.js.map +1 -0
- package/dist/rfc64/private-read-roster-v1.d.ts +14 -0
- package/dist/rfc64/private-read-roster-v1.d.ts.map +1 -0
- package/dist/rfc64/private-read-roster-v1.js +57 -0
- package/dist/rfc64/private-read-roster-v1.js.map +1 -0
- package/dist/rfc64/public-catalog-native-receiver-v1.d.ts.map +1 -1
- package/dist/rfc64/public-catalog-native-receiver-v1.js +26 -21
- package/dist/rfc64/public-catalog-native-receiver-v1.js.map +1 -1
- package/dist/rfc64/public-catalog-native-reconciler-v1.d.ts +17 -11
- package/dist/rfc64/public-catalog-native-reconciler-v1.d.ts.map +1 -1
- package/dist/rfc64/public-catalog-native-reconciler-v1.js +10 -8
- package/dist/rfc64/public-catalog-native-reconciler-v1.js.map +1 -1
- package/dist/rfc64/public-catalog-receiver-v1.d.ts +9 -0
- package/dist/rfc64/public-catalog-receiver-v1.d.ts.map +1 -1
- package/dist/rfc64/public-catalog-receiver-v1.js +11 -2
- package/dist/rfc64/public-catalog-receiver-v1.js.map +1 -1
- package/dist/rfc64/public-catalog-service-v1.d.ts.map +1 -1
- package/dist/rfc64/public-catalog-service-v1.js +21 -22
- package/dist/rfc64/public-catalog-service-v1.js.map +1 -1
- package/dist/rfc64/public-catalog-successor-producer-v1.d.ts.map +1 -1
- package/dist/rfc64/public-catalog-successor-producer-v1.js +5 -4
- package/dist/rfc64/public-catalog-successor-producer-v1.js.map +1 -1
- package/dist/rfc64/registered-private-empty-vm-proof-v1.d.ts +20 -0
- package/dist/rfc64/registered-private-empty-vm-proof-v1.d.ts.map +1 -0
- package/dist/rfc64/registered-private-empty-vm-proof-v1.js +26 -0
- package/dist/rfc64/registered-private-empty-vm-proof-v1.js.map +1 -0
- package/dist/rfc64/swm-catalog-durable-asset-resolver-v1.d.ts.map +1 -1
- package/dist/rfc64/swm-catalog-durable-asset-resolver-v1.js +60 -53
- package/dist/rfc64/swm-catalog-durable-asset-resolver-v1.js.map +1 -1
- package/dist/rfc64/swm-inventory-catalog-reconciler-v1.d.ts +2 -1
- package/dist/rfc64/swm-inventory-catalog-reconciler-v1.d.ts.map +1 -1
- package/dist/rfc64/swm-inventory-catalog-reconciler-v1.js +44 -4
- package/dist/rfc64/swm-inventory-catalog-reconciler-v1.js.map +1 -1
- package/dist/rfc64/swm-inventory-shadow-runtime-v1.d.ts +3 -1
- package/dist/rfc64/swm-inventory-shadow-runtime-v1.d.ts.map +1 -1
- package/dist/rfc64/swm-inventory-shadow-runtime-v1.js +34 -0
- package/dist/rfc64/swm-inventory-shadow-runtime-v1.js.map +1 -1
- package/dist/sync/auth/pipe-request-tail.d.ts +5 -1
- package/dist/sync/auth/pipe-request-tail.d.ts.map +1 -1
- package/dist/sync/auth/pipe-request-tail.js +13 -3
- package/dist/sync/auth/pipe-request-tail.js.map +1 -1
- package/dist/sync/auth/request-build.d.ts +3 -0
- package/dist/sync/auth/request-build.d.ts.map +1 -1
- package/dist/sync/auth/request-build.js +11 -2
- package/dist/sync/auth/request-build.js.map +1 -1
- package/dist/sync/backpressure.d.ts +27 -16
- package/dist/sync/backpressure.d.ts.map +1 -1
- package/dist/sync/backpressure.js +66 -40
- package/dist/sync/backpressure.js.map +1 -1
- package/dist/sync/catchup-policy.d.ts +2 -0
- package/dist/sync/catchup-policy.d.ts.map +1 -1
- package/dist/sync/catchup-policy.js +2 -0
- package/dist/sync/catchup-policy.js.map +1 -1
- package/dist/sync/exact-asset-fetch.d.ts +22 -0
- package/dist/sync/exact-asset-fetch.d.ts.map +1 -1
- package/dist/sync/exact-asset-fetch.js +30 -3
- package/dist/sync/exact-asset-fetch.js.map +1 -1
- package/dist/sync/exact-assets.d.ts +7 -5
- package/dist/sync/exact-assets.d.ts.map +1 -1
- package/dist/sync/exact-assets.js +13 -8
- package/dist/sync/exact-assets.js.map +1 -1
- package/dist/sync/exact-batch-observation.d.ts +3 -0
- package/dist/sync/exact-batch-observation.d.ts.map +1 -0
- package/dist/sync/exact-batch-observation.js +13 -0
- package/dist/sync/exact-batch-observation.js.map +1 -0
- package/dist/sync/exact-batch-stream-capability.d.ts +24 -0
- package/dist/sync/exact-batch-stream-capability.d.ts.map +1 -0
- package/dist/sync/exact-batch-stream-capability.js +88 -0
- package/dist/sync/exact-batch-stream-capability.js.map +1 -0
- package/dist/sync/exact-batch-stream-contract.d.ts +78 -0
- package/dist/sync/exact-batch-stream-contract.d.ts.map +1 -0
- package/dist/sync/exact-batch-stream-contract.js +206 -0
- package/dist/sync/exact-batch-stream-contract.js.map +1 -0
- package/dist/sync/on-connect/sync-on-connect.d.ts +1 -1
- package/dist/sync/on-connect/sync-on-connect.d.ts.map +1 -1
- package/dist/sync/on-connect/sync-on-connect.js +3 -3
- package/dist/sync/on-connect/sync-on-connect.js.map +1 -1
- package/dist/sync/on-demand-agents-phonebook.d.ts +162 -0
- package/dist/sync/on-demand-agents-phonebook.d.ts.map +1 -0
- package/dist/sync/on-demand-agents-phonebook.js +571 -0
- package/dist/sync/on-demand-agents-phonebook.js.map +1 -0
- package/dist/sync/peer-connection.d.ts.map +1 -1
- package/dist/sync/peer-connection.js +11 -2
- package/dist/sync/peer-connection.js.map +1 -1
- package/dist/sync/priority-admission-queue.d.ts +17 -0
- package/dist/sync/priority-admission-queue.d.ts.map +1 -1
- package/dist/sync/priority-admission-queue.js +58 -37
- package/dist/sync/priority-admission-queue.js.map +1 -1
- package/dist/sync/requester/admission-boundary.d.ts +12 -0
- package/dist/sync/requester/admission-boundary.d.ts.map +1 -0
- package/dist/sync/requester/admission-boundary.js +22 -0
- package/dist/sync/requester/admission-boundary.js.map +1 -0
- package/dist/sync/requester/durable-sync.d.ts +2 -1
- package/dist/sync/requester/durable-sync.d.ts.map +1 -1
- package/dist/sync/requester/durable-sync.js +3 -188
- package/dist/sync/requester/durable-sync.js.map +1 -1
- package/dist/sync/requester/exact-batch-stream-driver.d.ts +83 -0
- package/dist/sync/requester/exact-batch-stream-driver.d.ts.map +1 -0
- package/dist/sync/requester/exact-batch-stream-driver.js +299 -0
- package/dist/sync/requester/exact-batch-stream-driver.js.map +1 -0
- package/dist/sync/requester/exact-batch-stream.d.ts +72 -0
- package/dist/sync/requester/exact-batch-stream.d.ts.map +1 -0
- package/dist/sync/requester/exact-batch-stream.js +267 -0
- package/dist/sync/requester/exact-batch-stream.js.map +1 -0
- package/dist/sync/requester/exact-recovery-transport.d.ts +19 -0
- package/dist/sync/requester/exact-recovery-transport.d.ts.map +1 -0
- package/dist/sync/requester/exact-recovery-transport.js +3 -0
- package/dist/sync/requester/exact-recovery-transport.js.map +1 -0
- package/dist/sync/requester/finalized-swm-twin-reconciliation.js +12 -3
- package/dist/sync/requester/finalized-swm-twin-reconciliation.js.map +1 -1
- package/dist/sync/requester/graph-scoped-materialization.d.ts.map +1 -1
- package/dist/sync/requester/graph-scoped-materialization.js +61 -27
- package/dist/sync/requester/graph-scoped-materialization.js.map +1 -1
- package/dist/sync/requester/page-fetch.d.ts +7 -0
- package/dist/sync/requester/page-fetch.d.ts.map +1 -1
- package/dist/sync/requester/page-fetch.js +103 -49
- package/dist/sync/requester/page-fetch.js.map +1 -1
- package/dist/sync/requester/shared-memory-sync.d.ts +10 -5
- package/dist/sync/requester/shared-memory-sync.d.ts.map +1 -1
- package/dist/sync/requester/shared-memory-sync.js +149 -150
- package/dist/sync/requester/shared-memory-sync.js.map +1 -1
- package/dist/sync/requester/swm-materialization-memo.d.ts +12 -0
- package/dist/sync/requester/swm-materialization-memo.d.ts.map +1 -0
- package/dist/sync/requester/swm-materialization-memo.js +54 -0
- package/dist/sync/requester/swm-materialization-memo.js.map +1 -0
- package/dist/sync/requester/swm-recovery.d.ts +3 -29
- package/dist/sync/requester/swm-recovery.d.ts.map +1 -1
- package/dist/sync/requester/swm-recovery.js +11 -10
- package/dist/sync/requester/swm-recovery.js.map +1 -1
- package/dist/sync/requester/swm-snapshot-materializer.d.ts.map +1 -1
- package/dist/sync/requester/swm-snapshot-materializer.js +18 -0
- package/dist/sync/requester/swm-snapshot-materializer.js.map +1 -1
- package/dist/sync/requester/swm-target-executor.d.ts +6 -0
- package/dist/sync/requester/swm-target-executor.d.ts.map +1 -1
- package/dist/sync/requester/swm-target-executor.js +24 -3
- package/dist/sync/requester/swm-target-executor.js.map +1 -1
- package/dist/sync/requester/verified-asset-preparation.d.ts +9 -0
- package/dist/sync/requester/verified-asset-preparation.d.ts.map +1 -0
- package/dist/sync/requester/verified-asset-preparation.js +190 -0
- package/dist/sync/requester/verified-asset-preparation.js.map +1 -0
- package/dist/sync/responder/asset-metadata.d.ts +18 -0
- package/dist/sync/responder/asset-metadata.d.ts.map +1 -0
- package/dist/sync/responder/asset-metadata.js +27 -0
- package/dist/sync/responder/asset-metadata.js.map +1 -0
- package/dist/sync/responder/durable-data-request-policy.d.ts +2 -16
- package/dist/sync/responder/durable-data-request-policy.d.ts.map +1 -1
- package/dist/sync/responder/durable-data-request-policy.js +1 -31
- package/dist/sync/responder/durable-data-request-policy.js.map +1 -1
- package/dist/sync/responder/exact-asset-export-cache.d.ts +89 -0
- package/dist/sync/responder/exact-asset-export-cache.d.ts.map +1 -0
- package/dist/sync/responder/exact-asset-export-cache.js +550 -0
- package/dist/sync/responder/exact-asset-export-cache.js.map +1 -0
- package/dist/sync/responder/exact-batch-stream.d.ts +47 -0
- package/dist/sync/responder/exact-batch-stream.d.ts.map +1 -0
- package/dist/sync/responder/exact-batch-stream.js +151 -0
- package/dist/sync/responder/exact-batch-stream.js.map +1 -0
- package/dist/sync/responder/exact-data-session.d.ts +67 -0
- package/dist/sync/responder/exact-data-session.d.ts.map +1 -0
- package/dist/sync/responder/exact-data-session.js +130 -0
- package/dist/sync/responder/exact-data-session.js.map +1 -0
- package/dist/sync/responder/exact-graph-cursor-filter.d.ts +9 -0
- package/dist/sync/responder/exact-graph-cursor-filter.d.ts.map +1 -0
- package/dist/sync/responder/exact-graph-cursor-filter.js +101 -0
- package/dist/sync/responder/exact-graph-cursor-filter.js.map +1 -0
- package/dist/sync/responder/exact-graph-reader.d.ts +95 -0
- package/dist/sync/responder/exact-graph-reader.d.ts.map +1 -0
- package/dist/sync/responder/exact-graph-reader.js +623 -0
- package/dist/sync/responder/exact-graph-reader.js.map +1 -0
- package/dist/sync/responder/exact-page-reader.d.ts +37 -0
- package/dist/sync/responder/exact-page-reader.d.ts.map +1 -0
- package/dist/sync/responder/exact-page-reader.js +130 -0
- package/dist/sync/responder/exact-page-reader.js.map +1 -0
- package/dist/sync/responder/graph-plan.d.ts +19 -85
- package/dist/sync/responder/graph-plan.d.ts.map +1 -1
- package/dist/sync/responder/graph-plan.js +51 -988
- package/dist/sync/responder/graph-plan.js.map +1 -1
- package/dist/sync/responder/page-framing-policy.d.ts +31 -0
- package/dist/sync/responder/page-framing-policy.d.ts.map +1 -0
- package/dist/sync/responder/page-framing-policy.js +41 -0
- package/dist/sync/responder/page-framing-policy.js.map +1 -0
- package/dist/sync/responder/responder-row-page.d.ts +85 -0
- package/dist/sync/responder/responder-row-page.d.ts.map +1 -0
- package/dist/sync/responder/responder-row-page.js +181 -0
- package/dist/sync/responder/responder-row-page.js.map +1 -0
- package/dist/sync/responder/row-serialization.d.ts +34 -0
- package/dist/sync/responder/row-serialization.d.ts.map +1 -0
- package/dist/sync/responder/row-serialization.js +69 -0
- package/dist/sync/responder/row-serialization.js.map +1 -0
- package/dist/sync/responder/session-plan-memo.d.ts +20 -0
- package/dist/sync/responder/session-plan-memo.d.ts.map +1 -0
- package/dist/sync/responder/session-plan-memo.js +135 -0
- package/dist/sync/responder/session-plan-memo.js.map +1 -0
- package/dist/sync/responder/sync-handler.d.ts +26 -1
- package/dist/sync/responder/sync-handler.d.ts.map +1 -1
- package/dist/sync/responder/sync-handler.js +107 -58
- package/dist/sync/responder/sync-handler.js.map +1 -1
- package/dist/sync/shared-memory-completion.d.ts +30 -0
- package/dist/sync/shared-memory-completion.d.ts.map +1 -1
- package/dist/sync/shared-memory-completion.js +13 -0
- package/dist/sync/shared-memory-completion.js.map +1 -1
- package/dist/sync/system-context-graph-policy.d.ts +10 -0
- package/dist/sync/system-context-graph-policy.d.ts.map +1 -1
- package/dist/sync/system-context-graph-policy.js +11 -0
- package/dist/sync/system-context-graph-policy.js.map +1 -1
- package/dist/sync/wire-compression.d.ts +47 -0
- package/dist/sync/wire-compression.d.ts.map +1 -0
- package/dist/sync/wire-compression.js +111 -0
- package/dist/sync/wire-compression.js.map +1 -0
- package/dist/unscoped-query-consistency.d.ts +12 -0
- package/dist/unscoped-query-consistency.d.ts.map +1 -1
- package/dist/unscoped-query-consistency.js +17 -1
- package/dist/unscoped-query-consistency.js.map +1 -1
- package/dist/vm-promotion-audit.d.ts +2 -2
- package/dist/vm-promotion-audit.d.ts.map +1 -1
- package/dist/vm-promotion-audit.js +26 -9
- package/dist/vm-promotion-audit.js.map +1 -1
- package/dist/vm-publish-snapshot-preflight.d.ts +13 -0
- package/dist/vm-publish-snapshot-preflight.d.ts.map +1 -0
- package/dist/vm-publish-snapshot-preflight.js +94 -0
- package/dist/vm-publish-snapshot-preflight.js.map +1 -0
- package/dist/vm-reconcile-dispatcher.d.ts +42 -1
- package/dist/vm-reconcile-dispatcher.d.ts.map +1 -1
- package/dist/vm-reconcile-dispatcher.js +103 -4
- package/dist/vm-reconcile-dispatcher.js.map +1 -1
- package/dist/vm-reconcile-peer-topology.d.ts +7 -9
- package/dist/vm-reconcile-peer-topology.d.ts.map +1 -1
- package/dist/vm-reconcile-peer-topology.js +1 -37
- package/dist/vm-reconcile-peer-topology.js.map +1 -1
- package/dist/vm-recovery-candidate-order.d.ts +16 -0
- package/dist/vm-recovery-candidate-order.d.ts.map +1 -0
- package/dist/vm-recovery-candidate-order.js +24 -0
- package/dist/vm-recovery-candidate-order.js.map +1 -0
- package/dist/vm-recovery-core-transport-preference.d.ts +69 -0
- package/dist/vm-recovery-core-transport-preference.d.ts.map +1 -0
- package/dist/vm-recovery-core-transport-preference.js +131 -0
- package/dist/vm-recovery-core-transport-preference.js.map +1 -0
- package/dist/vm-recovery-experiment-policy.d.ts +24 -0
- package/dist/vm-recovery-experiment-policy.d.ts.map +1 -0
- package/dist/vm-recovery-experiment-policy.js +18 -0
- package/dist/vm-recovery-experiment-policy.js.map +1 -0
- package/dist/vm-recovery-footprint.d.ts +54 -0
- package/dist/vm-recovery-footprint.d.ts.map +1 -1
- package/dist/vm-recovery-footprint.js +88 -24
- package/dist/vm-recovery-footprint.js.map +1 -1
- package/dist/vm-recovery-microbatch.d.ts +2 -0
- package/dist/vm-recovery-microbatch.d.ts.map +1 -1
- package/dist/vm-recovery-microbatch.js +7 -3
- package/dist/vm-recovery-microbatch.js.map +1 -1
- package/dist/vm-recovery-pass-authority.d.ts +84 -0
- package/dist/vm-recovery-pass-authority.d.ts.map +1 -0
- package/dist/vm-recovery-pass-authority.js +126 -0
- package/dist/vm-recovery-pass-authority.js.map +1 -0
- package/dist/vm-recovery-phase-timing.d.ts +75 -0
- package/dist/vm-recovery-phase-timing.d.ts.map +1 -0
- package/dist/vm-recovery-phase-timing.js +236 -0
- package/dist/vm-recovery-phase-timing.js.map +1 -0
- package/dist/vm-recovery-preparation.d.ts +143 -0
- package/dist/vm-recovery-preparation.d.ts.map +1 -0
- package/dist/vm-recovery-preparation.js +433 -0
- package/dist/vm-recovery-preparation.js.map +1 -0
- package/dist/vm-recovery-provider-policy.d.ts +13 -1
- package/dist/vm-recovery-provider-policy.d.ts.map +1 -1
- package/dist/vm-recovery-provider-policy.js +37 -5
- package/dist/vm-recovery-provider-policy.js.map +1 -1
- package/dist/vm-recovery-stream-profile.d.ts +15 -0
- package/dist/vm-recovery-stream-profile.d.ts.map +1 -0
- package/dist/vm-recovery-stream-profile.js +53 -0
- package/dist/vm-recovery-stream-profile.js.map +1 -0
- package/dist/vm-recovery-stream-setback-policy.d.ts +54 -0
- package/dist/vm-recovery-stream-setback-policy.d.ts.map +1 -0
- package/dist/vm-recovery-stream-setback-policy.js +85 -0
- package/dist/vm-recovery-stream-setback-policy.js.map +1 -0
- package/dist/vm-recovery-timing-observer.d.ts +27 -0
- package/dist/vm-recovery-timing-observer.d.ts.map +1 -0
- package/dist/vm-recovery-timing-observer.js +49 -0
- package/dist/vm-recovery-timing-observer.js.map +1 -0
- package/dist/vm-recovery-transport-budget-policy.d.ts +32 -0
- package/dist/vm-recovery-transport-budget-policy.d.ts.map +1 -0
- package/dist/vm-recovery-transport-budget-policy.js +55 -0
- package/dist/vm-recovery-transport-budget-policy.js.map +1 -0
- package/dist/vm-recovery-transport-plan.d.ts +83 -0
- package/dist/vm-recovery-transport-plan.d.ts.map +1 -0
- package/dist/vm-recovery-transport-plan.js +117 -0
- package/dist/vm-recovery-transport-plan.js.map +1 -0
- package/dist/vm-refresh.d.ts +138 -0
- package/dist/vm-refresh.d.ts.map +1 -0
- package/dist/vm-refresh.js +201 -0
- package/dist/vm-refresh.js.map +1 -0
- package/package.json +19 -9
- package/dist/finalization-annotations.d.ts +0 -5
- package/dist/finalization-annotations.d.ts.map +0 -1
- package/dist/finalization-annotations.js +0 -6
- package/dist/finalization-annotations.js.map +0 -1
- package/dist/swm-ka-bound.d.ts +0 -21
- package/dist/swm-ka-bound.d.ts.map +0 -1
- package/dist/swm-ka-bound.js +0 -36
- package/dist/swm-ka-bound.js.map +0 -1
package/dist/dkg-agent-crypto.js
CHANGED
|
@@ -7,59 +7,30 @@
|
|
|
7
7
|
* 1:1 move; methods take `this: DKGAgent` so cross-calls resolve against the
|
|
8
8
|
* composed class.
|
|
9
9
|
*/
|
|
10
|
+
import { collectProjectedDelegatees } from './internal/workspace-projected-delegatees.js';
|
|
10
11
|
import { createHash, randomUUID } from 'node:crypto';
|
|
11
|
-
import { PROTOCOL_SWM_SENDER_KEY, encodeGossipEnvelope, computeGossipSigningPayload, GOSSIP_ENVELOPE_VERSION, GOSSIP_TYPE_WORKSPACE_PUBLISH, createOperationContext, logKaLifecycleEvent, WORKSPACE_AGENT_ENCRYPTION_KEY_ALGORITHM_X25519, WORKSPACE_RECIPIENT_ENCRYPTION_KEY_PURPOSE, decodeWorkspaceEncryptionKey, SWM_SENDER_KEY_PACKAGE_ACK_TYPE, SWM_SENDER_KEY_PACKAGE_ACK_RETRYABLE_REASON_CODES, SWM_SENDER_KEY_PACKAGE_VERSION, computeSwmSenderKeyMembershipHash, computeSwmSenderKeyPackageAAD, decodeWorkspacePublishRequest, decodeSwmSenderKeyPackage, decodeSwmSenderKeyPackageAck, decryptSwmSenderKeyMessage, decryptSwmSenderKeyPackage, encodeSwmSenderKeyMessage, encodeSwmSenderKeyPackage, encodeSwmSenderKeyPackageAck, encryptSwmSenderKeyMessage, encryptSwmSenderKeyPackage, generateEd25519Keypair, generateSwmSenderChainKey, generateSwmSenderEpochId, ratchetSwmSenderChainKey, uint64ForProto, SWM_SENDER_KEY_SKIPPED_MESSAGE_CACHE_LIMIT, } from '@origintrail-official/dkg-core';
|
|
12
|
+
import { PROTOCOL_SWM_SENDER_KEY, encodeGossipEnvelope, computeGossipSigningPayload, GOSSIP_ENVELOPE_VERSION, GOSSIP_TYPE_WORKSPACE_PUBLISH, createOperationContext, logKaLifecycleEvent, WORKSPACE_AGENT_ENCRYPTION_KEY_ALGORITHM_X25519, WORKSPACE_RECIPIENT_ENCRYPTION_KEY_PURPOSE, decodeWorkspaceEncryptionKey, SWM_SENDER_KEY_PACKAGE_ACK_TYPE, SWM_SENDER_KEY_PACKAGE_ACK_RETRYABLE_REASON_CODES, SWM_SENDER_KEY_PACKAGE_VERSION, computeSwmSenderKeyMembershipHash, computeSwmSenderKeyPackageAAD, decodeWorkspacePublishRequest, decodeSwmSenderKeyPackage, decodeSwmSenderKeyPackageAck, decryptSwmSenderKeyMessage, decryptSwmSenderKeyPackage, encodeSwmSenderKeyMessage, encodeSwmSenderKeyPackage, encodeSwmSenderKeyPackageAck, encryptSwmSenderKeyMessage, encryptSwmSenderKeyPackage, generateEd25519Keypair, generateSwmSenderChainKey, generateSwmSenderEpochId, ratchetSwmSenderChainKey, uint64ForProto, SWM_SENDER_KEY_SKIPPED_MESSAGE_CACHE_LIMIT, tryCanonicalPeerIdString, } from '@origintrail-official/dkg-core';
|
|
12
13
|
import { createRpcTimeoutError, withRpcRequestContext } from '@origintrail-official/dkg-chain';
|
|
13
|
-
import { resolveWorkspaceAgentRecipients, resolveWorkspaceAgentRecipientKeys, } from '@origintrail-official/dkg-publisher';
|
|
14
|
+
import { resolveWorkspaceAgentRecipients, resolveWorkspaceAgentRecipientKeys, isWorkspaceAgentEncryptionKeyMissingError, WorkspaceAgentEncryptionKeyMissingError, } from '@origintrail-official/dkg-publisher';
|
|
14
15
|
import { ethers } from 'ethers';
|
|
15
16
|
import { resolveActivePublicContextGraphChainProof as resolveStrictActivePublicChainProof, } from './active-public-context-graph-chain-proof.js';
|
|
16
17
|
import { resolveContextGraphAgentGateAuthorityDecision, } from './internal/context-graph-authority/context-graph-agent-gate-authority.js';
|
|
17
18
|
import { resolveLiveOnChainAccessPolicyState as resolveLiveAccessPolicyState, } from './internal/context-graph-authority/context-graph-access-policy.js';
|
|
18
|
-
import { createContextGraphAuthorityError, } from './internal/context-graph-authority/context-graph-authority.js';
|
|
19
|
+
import { createContextGraphAuthorityError, isContextGraphAuthorityUnavailableMarker, isRetryableContextGraphAuthorityUnavailableReason, } from './internal/context-graph-authority/context-graph-authority.js';
|
|
20
|
+
import { resolveSwmMemberRecoveryAuthorityDecision, resolveSwmRegisteredAuthorityDecision, resolveSwmTransportAuthorityDecision, } from './internal/context-graph-authority/swm-transport-authority.js';
|
|
19
21
|
import { FANOUT_RESPONSE_REJECTED, FANOUT_RESPONSE_RETRYABLE, } from './swm/substrate-fanout.js';
|
|
20
22
|
import { SyncTargetSupersededError } from './sync/error-tags.js';
|
|
21
23
|
import { resolveAssetUalFromKaIdentity } from './ka-identity.js';
|
|
22
|
-
import { TIMEOUT_SENTINEL, CHAIN_POLICY_READ_TIMEOUT_MS, SWM_SENDER_KEY_PENDING_DRAIN_LOG_CTX, } from './dkg-agent-constants.js';
|
|
24
|
+
import { SWM_RECIPIENT_KEY_FETCH_WAIT_MS, TIMEOUT_SENTINEL, CHAIN_POLICY_READ_TIMEOUT_MS, SWM_SENDER_KEY_PENDING_DRAIN_LOG_CTX, } from './dkg-agent-constants.js';
|
|
23
25
|
import { chainAuthorityReadBudgetsOf } from './chain-authority-read-budgets.js';
|
|
24
26
|
import { isBoundedOperationTimeoutError, runBoundedOperation, } from './bounded-operation.js';
|
|
25
27
|
import { StaleSenderKeyTargetError, SwmSenderKeySetupRejectionError, } from './dkg-agent-types.js';
|
|
26
|
-
import { swmSenderStateKey, swmReceiverStateKey, serializeSwmSenderSendState, serializeSwmSenderReceiveState, serializePendingSenderKeyEntry, deserializeSwmSenderSendState, deserializeSwmSenderReceiveState, deserializePendingSenderKeyEntry, } from './dkg-agent-swm-state.js';
|
|
28
|
+
import { computeSwmSenderKeyRecipientRouteHash, swmSenderStateKey, swmReceiverStateKey, serializeSwmSenderSendState, serializeSwmSenderReceiveState, serializePendingSenderKeyEntry, deserializeSwmSenderSendState, deserializeSwmSenderReceiveState, deserializePendingSenderKeyEntry, } from './dkg-agent-swm-state.js';
|
|
27
29
|
import { DKGAgentBase } from './dkg-agent-base.js';
|
|
28
|
-
import { localContextGraphIdMatchesCommittedNameHash } from './context-graph-binding-state.js';
|
|
30
|
+
import { isCanonicalPositiveContextGraphId, localContextGraphIdMatchesCommittedNameHash, } from './context-graph-binding-state.js';
|
|
29
31
|
import { CONTEXT_GRAPH_AUTHORITY_RPC_SITES as CG_AUTH_RPC_SITES, withRpcUsageSite, } from '@origintrail-official/dkg-chain';
|
|
30
32
|
const KA_LIFECYCLE_ASSET_UAL_RESOLVE_TIMEOUT_MS = 50;
|
|
31
|
-
|
|
32
|
-
if (expiresAtValues.length === 0)
|
|
33
|
-
return true;
|
|
34
|
-
return expiresAtValues.some((value) => {
|
|
35
|
-
const expiresAt = Number(value);
|
|
36
|
-
return !Number.isFinite(expiresAt) || expiresAt <= 0 || expiresAt >= nowMs;
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
function collectProjectedDelegatees(meta, field, normalizeValue) {
|
|
40
|
-
const members = new Set([...meta.allowedAgents, ...meta.participantAgents].map((agent) => agent.toLowerCase()));
|
|
41
|
-
const revoked = new Set(meta.revokedAgents.map((agent) => agent.toLowerCase()));
|
|
42
|
-
const out = new Map();
|
|
43
|
-
const nowMs = Date.now();
|
|
44
|
-
for (const delegation of meta.delegations) {
|
|
45
|
-
if (!delegationIsCurrentlyActive(delegation.expiresAtValues, nowMs))
|
|
46
|
-
continue;
|
|
47
|
-
for (const rawAgent of delegation.agents) {
|
|
48
|
-
const agent = rawAgent.toLowerCase();
|
|
49
|
-
if (!agent || !members.has(agent) || revoked.has(agent))
|
|
50
|
-
continue;
|
|
51
|
-
const values = out.get(agent) ?? [];
|
|
52
|
-
for (const rawValue of delegation[field]) {
|
|
53
|
-
const value = normalizeValue(rawValue);
|
|
54
|
-
if (value && !values.includes(value))
|
|
55
|
-
values.push(value);
|
|
56
|
-
}
|
|
57
|
-
if (values.length > 0)
|
|
58
|
-
out.set(agent, values);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return out;
|
|
62
|
-
}
|
|
33
|
+
const SWM_RECIPIENT_AUTHORITY_STABILITY_ATTEMPTS = 3;
|
|
63
34
|
function mapContextGraphSlotBindingOutcome(outcome, mode) {
|
|
64
35
|
if (outcome.kind === 'match')
|
|
65
36
|
return true;
|
|
@@ -172,6 +143,62 @@ function bindLiveAuthorityRead(chain, read, freshness) {
|
|
|
172
143
|
freshness,
|
|
173
144
|
});
|
|
174
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* The recipient-key failure a sender reports once fetching cannot help: why
|
|
148
|
+
* the keys are unknown and what gets them here (#2849).
|
|
149
|
+
*/
|
|
150
|
+
function withMemberKeyHint(error) {
|
|
151
|
+
const { agentAddresses } = error;
|
|
152
|
+
const one = agentAddresses.length === 1;
|
|
153
|
+
return new WorkspaceAgentEncryptionKeyMissingError(agentAddresses, `${new WorkspaceAgentEncryptionKeyMissingError(agentAddresses).message}: this node has neither `
|
|
154
|
+
+ (one ? 'a join request from the agent nor its profile. Have the member' : 'join requests from these agents nor their profiles. Have each member')
|
|
155
|
+
+ ' join through an invite, or retry once '
|
|
156
|
+
+ (one ? 'its profile has' : 'their profiles have')
|
|
157
|
+
+ ' reached this node (profiles are re-published about every 20 minutes).');
|
|
158
|
+
}
|
|
159
|
+
function hasExactRecipientAgentRoster(resolution, participantAgents) {
|
|
160
|
+
try {
|
|
161
|
+
const resolvedAgents = new Set(resolution.recipients.map(({ agentAddress }) => ethers.getAddress(agentAddress).toLowerCase()));
|
|
162
|
+
const currentAgents = new Set(participantAgents.map((address) => ethers.getAddress(address).toLowerCase()));
|
|
163
|
+
return currentAgents.size === resolvedAgents.size
|
|
164
|
+
&& [...currentAgents].every((address) => resolvedAgents.has(address));
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function hasExactWorkspaceRecipientSet(left, right) {
|
|
171
|
+
const canonical = (recipient) => [
|
|
172
|
+
ethers.getAddress(recipient.agentAddress).toLowerCase(),
|
|
173
|
+
recipient.recipientKeyId,
|
|
174
|
+
recipient.peerId ?? '',
|
|
175
|
+
].join('\u0000');
|
|
176
|
+
try {
|
|
177
|
+
const leftRecipients = left.recipients.map(canonical).sort();
|
|
178
|
+
const rightRecipients = right.recipients.map(canonical).sort();
|
|
179
|
+
return leftRecipients.length === rightRecipients.length
|
|
180
|
+
&& leftRecipients.every((recipient, index) => recipient === rightRecipients[index]);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function sameStringSet(left, right) {
|
|
187
|
+
const leftSet = new Set(left);
|
|
188
|
+
const rightSet = new Set(right);
|
|
189
|
+
return leftSet.size === rightSet.size && [...leftSet].every((value) => rightSet.has(value));
|
|
190
|
+
}
|
|
191
|
+
function pendingSenderKeyEntryMatchesDrainAuthority(entry, authority) {
|
|
192
|
+
return entry.contextGraphId === authority.contextGraphId
|
|
193
|
+
&& (authority.allSubgraphs === true
|
|
194
|
+
|| (entry.subGraphName ?? undefined) === (authority.subGraphName ?? undefined))
|
|
195
|
+
&& entry.recipientAgentAddress === authority.recipientAgentAddress
|
|
196
|
+
&& entry.recipientKeyId === authority.recipientKeyId
|
|
197
|
+
&& entry.recipientPeerId === authority.recipientPeerId
|
|
198
|
+
&& (authority.senderAgentAddress === undefined
|
|
199
|
+
|| entry.senderAgentAddress === authority.senderAgentAddress)
|
|
200
|
+
&& (authority.epochId === undefined || entry.epochId === authority.epochId);
|
|
201
|
+
}
|
|
175
202
|
export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
176
203
|
getWorkspaceGossipSigningAgent() {
|
|
177
204
|
const defaultAddress = this.defaultAgentAddress?.toLowerCase();
|
|
@@ -227,8 +254,8 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
227
254
|
async resolveContextGraphAgentGateAuthority(contextGraphId, options = {}) {
|
|
228
255
|
return withRpcUsageSite(CG_AUTH_RPC_SITES.gate, () => resolveContextGraphAgentGateAuthorityDecision({
|
|
229
256
|
contextGraphId,
|
|
230
|
-
|
|
231
|
-
|
|
257
|
+
getTransportAuthority: () => this.resolveSwmTransportAuthority(contextGraphId, { signal: options.signal }),
|
|
258
|
+
readMetadataRevision: () => this.contextGraphMetaProjection.readAuthorityFactsRevision,
|
|
232
259
|
getLegacyMeta: () => this.getCgMeta(contextGraphId, { signal: options.signal }),
|
|
233
260
|
getSubscriptionAgents: () => (this.subscribedContextGraphs.get(contextGraphId)?.participantAgents ?? []),
|
|
234
261
|
}));
|
|
@@ -243,32 +270,89 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
243
270
|
return [];
|
|
244
271
|
}
|
|
245
272
|
/**
|
|
246
|
-
* R9 (SECURITY) —
|
|
273
|
+
* R9 (SECURITY) — authoritative member-recovery gate.
|
|
247
274
|
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
275
|
+
* Registered and active accepted-private graphs use their exact authority
|
|
276
|
+
* roster. Only a legacy unregistered graph (including accepted public, whose
|
|
277
|
+
* local gate controls recovery rather than reads) resolves the effective
|
|
278
|
+
* store-backed metadata projection of
|
|
279
|
+
* `allowedAgents ∪ participantAgents` minus `revokedAgents` from the CG
|
|
280
|
+
* metadata. The network-influenced `subscribedContextGraphs`
|
|
281
|
+
* subscription cache is DELIBERATELY OMITTED — that cache is poisonable, and
|
|
282
|
+
* folding it in is exactly what `member-recovery-auth.ts` forbids.
|
|
253
283
|
*
|
|
254
284
|
* Unlike {@link getContextGraphAgentGateAddresses} (which also feeds normal
|
|
255
285
|
* sync admission and may fold in the subscription cache only for graphs that
|
|
256
286
|
* are not registered on-chain), this read is used ONLY for `request.recovery`
|
|
257
287
|
* and is passed straight to
|
|
258
288
|
* `isMemberRecoveryAuthorized`, which hard-denies on null/empty. Returns
|
|
259
|
-
* `null` when the CG has no
|
|
289
|
+
* `null` when the CG has no projected agent gate at all (⇒ hard-deny).
|
|
260
290
|
*/
|
|
261
291
|
async getMemberRecoveryGate(contextGraphId, options = {}) {
|
|
262
|
-
const
|
|
263
|
-
if (
|
|
264
|
-
return
|
|
265
|
-
|
|
292
|
+
const recoveryAuthority = await withRpcUsageSite(CG_AUTH_RPC_SITES.recoveryGate, () => resolveSwmMemberRecoveryAuthorityDecision(this, contextGraphId, { signal: options.signal }));
|
|
293
|
+
if (recoveryAuthority.kind === 'private-roster') {
|
|
294
|
+
return [...recoveryAuthority.participantAgents];
|
|
295
|
+
}
|
|
296
|
+
if (recoveryAuthority.kind !== 'legacy-unregistered')
|
|
266
297
|
return null;
|
|
298
|
+
const metadataRevision = this.contextGraphMetaProjection
|
|
299
|
+
.readContextGraphAuthorityFactsRevision(contextGraphId);
|
|
300
|
+
const metadataGate = await this.getLocalMetadataMemberRecoveryGate(contextGraphId, options);
|
|
301
|
+
// Metadata is another async boundary. Re-resolve the authoritative state
|
|
302
|
+
// before returning it so a private policy activation/rotation or a chain
|
|
303
|
+
// registration that commits during the store read takes precedence over
|
|
304
|
+
// the now-stale local projection.
|
|
305
|
+
const currentRecoveryAuthority = await withRpcUsageSite(CG_AUTH_RPC_SITES.recoveryGate, () => resolveSwmMemberRecoveryAuthorityDecision(this, contextGraphId, { signal: options.signal }));
|
|
306
|
+
if (currentRecoveryAuthority.kind === 'private-roster') {
|
|
307
|
+
return [...currentRecoveryAuthority.participantAgents];
|
|
308
|
+
}
|
|
309
|
+
if (currentRecoveryAuthority.kind !== 'legacy-unregistered')
|
|
310
|
+
return null;
|
|
311
|
+
// A revocation or other authority-fact mutation during the metadata read
|
|
312
|
+
// invalidates the captured roster even if registration remained absent.
|
|
313
|
+
// Recovery is retryable, so fail closed instead of serving that snapshot.
|
|
314
|
+
return this.contextGraphMetaProjection
|
|
315
|
+
.readContextGraphAuthorityFactsRevision(contextGraphId) === metadataRevision
|
|
316
|
+
? metadataGate
|
|
317
|
+
: null;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Authority source used while constructing or mutating a private roster.
|
|
321
|
+
* Registered private graphs retain their finalized chain participant set;
|
|
322
|
+
* unregistered graphs use the effective store-backed metadata projection.
|
|
323
|
+
* This deliberately ignores an accepted-private overlay roster so rotation
|
|
324
|
+
* does not ask the roster it is replacing to define its own successor.
|
|
325
|
+
*/
|
|
326
|
+
async getMemberRecoveryRosterSource(contextGraphId, options = {}) {
|
|
327
|
+
const registered = await this.resolveSwmRegisteredAuthority(contextGraphId, { signal: options.signal });
|
|
328
|
+
if (registered.kind === 'private')
|
|
329
|
+
return [...registered.participantAgents];
|
|
330
|
+
if (registered.kind !== 'unregistered')
|
|
331
|
+
return null;
|
|
332
|
+
const metadataRevision = this.contextGraphMetaProjection
|
|
333
|
+
.readContextGraphAuthorityFactsRevision(contextGraphId);
|
|
334
|
+
const metadataGate = await this.getLocalMetadataMemberRecoveryGate(contextGraphId, options);
|
|
335
|
+
const currentRegistered = await this.resolveSwmRegisteredAuthority(contextGraphId, { signal: options.signal });
|
|
336
|
+
if (currentRegistered.kind === 'private') {
|
|
337
|
+
return [...currentRegistered.participantAgents];
|
|
338
|
+
}
|
|
339
|
+
if (currentRegistered.kind !== 'unregistered')
|
|
340
|
+
return null;
|
|
341
|
+
return this.contextGraphMetaProjection
|
|
342
|
+
.readContextGraphAuthorityFactsRevision(contextGraphId) === metadataRevision
|
|
343
|
+
? metadataGate
|
|
344
|
+
: null;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Fresh effective store-backed metadata member set. This deliberately stays
|
|
348
|
+
* separate from the transport-authoritative recovery decision.
|
|
349
|
+
*/
|
|
350
|
+
async getLocalMetadataMemberRecoveryGate(contextGraphId, options = {}) {
|
|
267
351
|
const seen = new Set();
|
|
268
352
|
const agents = [];
|
|
269
353
|
const meta = await this.getCgMeta(contextGraphId, { signal: options.signal });
|
|
270
354
|
if (meta.allowedAgents.length === 0 && meta.participantAgents.length === 0) {
|
|
271
|
-
return null; // no
|
|
355
|
+
return null; // no projected agent gate ⇒ hard-deny at the recovery gate
|
|
272
356
|
}
|
|
273
357
|
const revoked = new Set(meta.revokedAgents.map((addr) => addr.toLowerCase()));
|
|
274
358
|
const add = (value) => {
|
|
@@ -494,7 +578,24 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
494
578
|
const trimmed = contextGraphId.trim();
|
|
495
579
|
let onChainId = null;
|
|
496
580
|
let resolvedFromLocalCg = false;
|
|
497
|
-
if (
|
|
581
|
+
if (this.chain?.contextGraphAuthorityIndexRevisionReader !== undefined
|
|
582
|
+
&& typeof this.resolveContextGraphRegistrationBinding === 'function'
|
|
583
|
+
&& !isCanonicalPositiveContextGraphId(trimmed)) {
|
|
584
|
+
// An indexed adapter takes the identity from the finalized registration
|
|
585
|
+
// binding too, never from a live registry range scan (#2827 follow-up).
|
|
586
|
+
// Finalized absence is `unregistered`, as a scan's miss was; any other
|
|
587
|
+
// unanswered read is `unknown`.
|
|
588
|
+
const binding = await this.resolveContextGraphRegistrationBinding(contextGraphId, { signal });
|
|
589
|
+
if (binding.kind === 'registered') {
|
|
590
|
+
onChainId = binding.onChainId.toString();
|
|
591
|
+
resolvedFromLocalCg = true;
|
|
592
|
+
}
|
|
593
|
+
else if (binding.kind === 'unavailable'
|
|
594
|
+
&& binding.reason !== 'finalized-name-absence-unaccepted') {
|
|
595
|
+
return 'unknown';
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
else if (typeof this.getContextGraphOnChainId === 'function') {
|
|
498
599
|
onChainId = await this.getContextGraphOnChainId(contextGraphId, { signal });
|
|
499
600
|
if (onChainId)
|
|
500
601
|
resolvedFromLocalCg = true;
|
|
@@ -553,6 +654,96 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
553
654
|
this.onChainAccessPolicyCache.set(onChainId, accessPolicy);
|
|
554
655
|
return accessPolicy;
|
|
555
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Registered-chain authority for the SWM consumers that need the raw roster,
|
|
659
|
+
* the agent gate and member recovery (#2827). The policy, and why the
|
|
660
|
+
* finalized authority index is the only registration evidence, live in
|
|
661
|
+
* {@link resolveSwmRegisteredAuthorityDecision}.
|
|
662
|
+
*/
|
|
663
|
+
resolveSwmRegisteredAuthority(contextGraphId, options = {}) {
|
|
664
|
+
return resolveSwmRegisteredAuthorityDecision(this, contextGraphId, options);
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* How SWM on this graph may travel, for both ends of the wire
|
|
668
|
+
* ({@link resolveSwmTransportAuthorityDecision}).
|
|
669
|
+
*/
|
|
670
|
+
resolveSwmTransportAuthority(contextGraphId, options = {}) {
|
|
671
|
+
return resolveSwmTransportAuthorityDecision(this, contextGraphId, options);
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Resolve the transport peer gate that applies to inbound SWM traffic.
|
|
675
|
+
*
|
|
676
|
+
* Ordinary graphs retain the legacy merged metadata projection. A graph
|
|
677
|
+
* carrying a durable local join approval must instead use the peer roster
|
|
678
|
+
* from the same source-qualified proof that authorized its private replica;
|
|
679
|
+
* falling back to the merged projection there would let an unrelated
|
|
680
|
+
* AGENTS/ONTOLOGY row widen the inbound gate. Registration (or a proven
|
|
681
|
+
* public policy) supersedes that participant proof and keeps the established
|
|
682
|
+
* registered/public behaviour.
|
|
683
|
+
*/
|
|
684
|
+
async resolveApprovedPrivateReplicaSwmAllowedPeersOverride(contextGraphId) {
|
|
685
|
+
if (!this.localApprovedAgentByCG.has(contextGraphId)) {
|
|
686
|
+
return undefined;
|
|
687
|
+
}
|
|
688
|
+
const transport = await this.resolveSwmTransportAuthority(contextGraphId, {
|
|
689
|
+
authorityReadMode: 'finalized-index-or-live',
|
|
690
|
+
});
|
|
691
|
+
switch (transport.kind) {
|
|
692
|
+
case 'approved-private-replica':
|
|
693
|
+
// An empty proved list is an authoritative open peer gate. Keep it
|
|
694
|
+
// distinct from `undefined` (this override does not apply) so the
|
|
695
|
+
// SharedMemoryHandler projection wrapper never falls back to a merged
|
|
696
|
+
// secondary-source row.
|
|
697
|
+
return [...new Set(transport.allowedPeers)];
|
|
698
|
+
case 'plaintext':
|
|
699
|
+
case 'private-roster':
|
|
700
|
+
return undefined;
|
|
701
|
+
case 'unavailable':
|
|
702
|
+
throw createContextGraphAuthorityError(`Context graph "${contextGraphId}" SWM peer gate authority is unavailable (${transport.reason})`, transport);
|
|
703
|
+
case 'legacy-unregistered':
|
|
704
|
+
// The approval may have been removed while the authority read was in
|
|
705
|
+
// flight. Only that transition restores ordinary legacy behaviour.
|
|
706
|
+
if (!this.localApprovedAgentByCG.has(contextGraphId)) {
|
|
707
|
+
return undefined;
|
|
708
|
+
}
|
|
709
|
+
throw createContextGraphAuthorityError(`Context graph "${contextGraphId}" still has a local join approval but no approved private replica authority`, {
|
|
710
|
+
reason: 'finalized-name-absence-unaccepted',
|
|
711
|
+
detail: 'approved private replica authority did not survive current SWM authority resolution',
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
/** List/null adapter for SWM consumers that do not consume meta records. */
|
|
716
|
+
async resolveSwmAllowedPeersForCurrentAuthority(contextGraphId) {
|
|
717
|
+
const approvedReplicaOverride = await this.resolveApprovedPrivateReplicaSwmAllowedPeersOverride(contextGraphId);
|
|
718
|
+
if (approvedReplicaOverride === undefined) {
|
|
719
|
+
return this.getContextGraphAllowedPeers(contextGraphId);
|
|
720
|
+
}
|
|
721
|
+
return approvedReplicaOverride.length > 0 ? approvedReplicaOverride : null;
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Whether SWM on this graph is public-readable, so plaintext may be both
|
|
725
|
+
* sent and accepted. One predicate for both ends of the wire: the sender's
|
|
726
|
+
* recipient resolver and the receiver's plaintext oracle.
|
|
727
|
+
*
|
|
728
|
+
* Without an active accepted owner-signed public policy it is exactly the
|
|
729
|
+
* live on-chain probe (isContextGraphPublicOnChain). With one, it is the
|
|
730
|
+
* `plaintext` transport authority of {@link resolveSwmTransportAuthority},
|
|
731
|
+
* the same answer the sender's recipient selection uses.
|
|
732
|
+
*/
|
|
733
|
+
async isContextGraphSwmPublic(contextGraphId, opCtx) {
|
|
734
|
+
if (!this.hasActiveAcceptedRfc64PublicUnregisteredAuthorityV1(contextGraphId)) {
|
|
735
|
+
return this.isContextGraphPublicOnChain(contextGraphId, opCtx);
|
|
736
|
+
}
|
|
737
|
+
try {
|
|
738
|
+
const transport = await withRpcUsageSite(CG_AUTH_RPC_SITES.publicProbe, () => this.resolveSwmTransportAuthority(contextGraphId, { authorityReadMode: 'finalized-index-or-live' }));
|
|
739
|
+
return transport.kind === 'plaintext';
|
|
740
|
+
}
|
|
741
|
+
catch (err) {
|
|
742
|
+
this.log.warn(opCtx ?? createOperationContext('share'), `isContextGraphSwmPublic(${contextGraphId}) could not resolve registered authority — `
|
|
743
|
+
+ `treating the graph as NOT public (fail-closed): ${err instanceof Error ? err.message : String(err)}`);
|
|
744
|
+
return false;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
556
747
|
/**
|
|
557
748
|
* True iff `contextGraphId` is DEFINITIVELY public per its on-chain
|
|
558
749
|
* access policy (policy enum `0`). Gates SWM encryption: an on-chain
|
|
@@ -820,9 +1011,18 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
820
1011
|
* avoids the resolver's "Missing public encryption key" throw for an
|
|
821
1012
|
* allowlisted agent whose key isn't locally available — irrelevant for
|
|
822
1013
|
* a public CG that never encrypts. Private graphs resolve recipients from
|
|
823
|
-
* the live roster; unavailable registered authority fails closed.
|
|
1014
|
+
* the live roster; unavailable registered authority fails closed. An
|
|
1015
|
+
* unregistered graph whose accepted owner-signed policy is public is
|
|
1016
|
+
* treated like an on-chain public one. An approved private replica retains
|
|
1017
|
+
* the full effective metadata roster, while any explicit graph peer
|
|
1018
|
+
* allowlist restricts the recipient keys available to every roster member.
|
|
824
1019
|
*/
|
|
825
1020
|
async resolveWorkspaceRecipientsGated(input) {
|
|
1021
|
+
// Hydrate durable sender-key state before resolving recipients. The
|
|
1022
|
+
// publisher invokes the encryptor synchronously after this resolver, so
|
|
1023
|
+
// this keeps state I/O out of the authority-fenced interval between the
|
|
1024
|
+
// final recipient recheck and sender-key epoch selection/creation.
|
|
1025
|
+
await this.loadSwmSenderKeyState();
|
|
826
1026
|
return this.resolveWorkspaceAgentRecipientsForCurrentAuthority(input);
|
|
827
1027
|
}
|
|
828
1028
|
/**
|
|
@@ -842,60 +1042,231 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
842
1042
|
* current chain state (`requireLiveRosterForPrivate`), never from the index.
|
|
843
1043
|
*/
|
|
844
1044
|
async resolveWorkspaceAgentRecipientsForCurrentAuthority(input) {
|
|
845
|
-
|
|
1045
|
+
// The receiver decides plaintext from this same transport authority
|
|
1046
|
+
// (isContextGraphSwmPublic), so the two ends cannot disagree (#2827).
|
|
1047
|
+
const transport = await withRpcUsageSite(CG_AUTH_RPC_SITES.recipients, () => this.resolveSwmTransportAuthority(input.contextGraphId, {
|
|
846
1048
|
authorityReadMode: 'finalized-index-or-live',
|
|
847
1049
|
requireLiveRosterForPrivate: true,
|
|
848
1050
|
}));
|
|
849
|
-
if (
|
|
850
|
-
return resolveWorkspaceAgentRecipients(this.store, input);
|
|
851
|
-
}
|
|
852
|
-
if (registeredAuthority.kind === 'public') {
|
|
1051
|
+
if (transport.kind === 'plaintext') {
|
|
853
1052
|
return { requiresEncryption: false, recipients: [] };
|
|
854
1053
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
1054
|
+
let recipientAuthorityRevision = null;
|
|
1055
|
+
let resolveKeys;
|
|
1056
|
+
if (transport.kind === 'legacy-unregistered') {
|
|
1057
|
+
resolveKeys = async () => {
|
|
1058
|
+
const attemptRevision = this.contextGraphMetaProjection.readAuthorityFactsRevision;
|
|
1059
|
+
const resolution = await resolveWorkspaceAgentRecipients(this.store, input);
|
|
1060
|
+
recipientAuthorityRevision = attemptRevision;
|
|
1061
|
+
return resolution;
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
else if (transport.kind === 'approved-private-replica') {
|
|
1065
|
+
// Resolve the complete effective metadata roster first. Participant
|
|
1066
|
+
// approval authorizes this receiver; it is not a replacement roster.
|
|
1067
|
+
// The peer gate comes from the same source-qualified, revision-fenced
|
|
1068
|
+
// proof as the transport classification, never the merged projection.
|
|
1069
|
+
resolveKeys = async () => {
|
|
1070
|
+
const attemptRevision = this.contextGraphMetaProjection.readAuthorityFactsRevision;
|
|
1071
|
+
const resolution = await resolveWorkspaceAgentRecipients(this.store, input);
|
|
1072
|
+
if (!resolution.requiresEncryption) {
|
|
1073
|
+
throw new Error(`Approved private replica "${input.contextGraphId}" resolved a plaintext SWM roster`);
|
|
1074
|
+
}
|
|
1075
|
+
if (transport.allowedPeers.length === 0) {
|
|
1076
|
+
recipientAuthorityRevision = attemptRevision;
|
|
1077
|
+
return resolution;
|
|
1078
|
+
}
|
|
1079
|
+
const allowedPeerSet = new Set(transport.allowedPeers);
|
|
1080
|
+
const effectiveAgentAddresses = new Set(resolution.recipients.map(({ agentAddress }) => agentAddress.toLowerCase()));
|
|
1081
|
+
const authorizedRecipients = resolution.recipients.filter((recipient) => (recipient.peerId !== undefined && allowedPeerSet.has(recipient.peerId)));
|
|
1082
|
+
const authorizedAgentAddresses = new Set(authorizedRecipients.map(({ agentAddress }) => agentAddress.toLowerCase()));
|
|
1083
|
+
for (const agentAddress of effectiveAgentAddresses) {
|
|
1084
|
+
if (!authorizedAgentAddresses.has(agentAddress)) {
|
|
1085
|
+
throw new Error(`Approved private replica "${input.contextGraphId}" requires encrypted SWM gossip but `
|
|
1086
|
+
+ `effective DKG agent ${ethers.getAddress(agentAddress)} has no recipient key `
|
|
1087
|
+
+ 'advertised by a peer in the context graph allowlist');
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
const [firstRecipient, ...remainingRecipients] = authorizedRecipients;
|
|
1091
|
+
if (!firstRecipient) {
|
|
1092
|
+
throw new Error(`Approved private replica "${input.contextGraphId}" requires encrypted SWM gossip but has no allowed DKG agent recipients`);
|
|
1093
|
+
}
|
|
1094
|
+
const authorizedResolution = {
|
|
1095
|
+
requiresEncryption: true,
|
|
1096
|
+
recipients: [firstRecipient, ...remainingRecipients],
|
|
1097
|
+
};
|
|
1098
|
+
recipientAuthorityRevision = attemptRevision;
|
|
1099
|
+
return authorizedResolution;
|
|
1100
|
+
};
|
|
885
1101
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
1102
|
+
else {
|
|
1103
|
+
if (transport.kind === 'unavailable') {
|
|
1104
|
+
const message = `Registered context graph "${input.contextGraphId}" authority is unavailable (${transport.reason})`;
|
|
1105
|
+
throw createContextGraphAuthorityError(message, transport);
|
|
1106
|
+
}
|
|
1107
|
+
const participantAgents = transport.participantAgents;
|
|
1108
|
+
if (participantAgents.length === 0) {
|
|
1109
|
+
throw new Error(`Registered context graph "${input.contextGraphId}" requires encrypted SWM gossip but its authoritative chain roster is empty or unavailable`);
|
|
1110
|
+
}
|
|
1111
|
+
// Resolve only the live chain-authorized addresses. Filtering a completed
|
|
1112
|
+
// local resolution afterward is too late: stale removed members can have
|
|
1113
|
+
// malformed/missing key metadata that makes the local resolver throw
|
|
1114
|
+
// before the chain intersection is reached, blocking every post-revoke
|
|
1115
|
+
// write until the local cleanup retry succeeds.
|
|
1116
|
+
resolveKeys = async () => {
|
|
1117
|
+
// The registered/accepted private roster, local peer gate, and verified
|
|
1118
|
+
// recipient-key routes are conjunctive authorities. Capture their shared
|
|
1119
|
+
// revision before every attempt so a phonebook-hydration retry owns a new
|
|
1120
|
+
// snapshot, while the final transport recheck cannot return a route
|
|
1121
|
+
// removed or revoked meanwhile.
|
|
1122
|
+
const attemptRevision = this.contextGraphMetaProjection.readAuthorityFactsRevision;
|
|
1123
|
+
const allowedPeers = await this.getContextGraphAllowedPeers(input.contextGraphId);
|
|
1124
|
+
const allowedPeerSet = allowedPeers === null ? null : new Set(allowedPeers);
|
|
1125
|
+
const recipients = [];
|
|
1126
|
+
// Every member without a key is named at once, so one phonebook fetch
|
|
1127
|
+
// can cover them all (#2849). Any other key failure still stops here.
|
|
1128
|
+
const missingKeys = [];
|
|
1129
|
+
for (const agentAddress of participantAgents) {
|
|
1130
|
+
let agentRecipients;
|
|
1131
|
+
try {
|
|
1132
|
+
agentRecipients = await resolveWorkspaceAgentRecipientKeys(this.store, agentAddress);
|
|
1133
|
+
}
|
|
1134
|
+
catch (error) {
|
|
1135
|
+
if (!isWorkspaceAgentEncryptionKeyMissingError(error))
|
|
1136
|
+
throw error;
|
|
1137
|
+
missingKeys.push(...error.agentAddresses);
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
const authorizedRecipients = allowedPeerSet === null
|
|
1141
|
+
? agentRecipients
|
|
1142
|
+
: agentRecipients.filter((recipient) => (recipient.peerId !== undefined && allowedPeerSet.has(recipient.peerId)));
|
|
1143
|
+
if (authorizedRecipients.length === 0) {
|
|
1144
|
+
throw new Error(`Registered context graph "${input.contextGraphId}" requires encrypted SWM gossip but `
|
|
1145
|
+
+ `chain-authorized DKG agent ${ethers.getAddress(agentAddress)} has no recipient key `
|
|
1146
|
+
+ 'advertised by a peer in the context graph allowlist');
|
|
1147
|
+
}
|
|
1148
|
+
recipients.push(...authorizedRecipients);
|
|
1149
|
+
}
|
|
1150
|
+
if (missingKeys.length > 0)
|
|
1151
|
+
throw new WorkspaceAgentEncryptionKeyMissingError(missingKeys);
|
|
1152
|
+
const [firstRecipient, ...remainingRecipients] = recipients;
|
|
1153
|
+
if (!firstRecipient) {
|
|
1154
|
+
throw new Error(`Registered context graph "${input.contextGraphId}" requires encrypted SWM gossip but has no chain-authorized DKG agent recipients`);
|
|
1155
|
+
}
|
|
1156
|
+
// Publish only the snapshot owned by the attempt that actually
|
|
1157
|
+
// completed. A failed pre-hydration attempt must not pin its revision
|
|
1158
|
+
// across the phonebook write and the successful retry.
|
|
1159
|
+
recipientAuthorityRevision = attemptRevision;
|
|
1160
|
+
return {
|
|
1161
|
+
requiresEncryption: true,
|
|
1162
|
+
recipients: [firstRecipient, ...remainingRecipients],
|
|
1163
|
+
};
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
// A member added by address before it joined is known here only by its
|
|
1167
|
+
// profile, which an Edge fetches on demand (#2849). One fetch asks for
|
|
1168
|
+
// every member whose key is missing, then the keys are resolved once more.
|
|
1169
|
+
// Every member still needs a key, so a share that cannot get one stays
|
|
1170
|
+
// closed.
|
|
1171
|
+
const resolveWithPhonebookHydration = async () => {
|
|
1172
|
+
try {
|
|
1173
|
+
return await resolveKeys();
|
|
1174
|
+
}
|
|
1175
|
+
catch (error) {
|
|
1176
|
+
if (!isWorkspaceAgentEncryptionKeyMissingError(error))
|
|
1177
|
+
throw error;
|
|
1178
|
+
if (typeof this.ensureAgentsInOnDemandPhonebook !== 'function') {
|
|
1179
|
+
throw withMemberKeyHint(error);
|
|
1180
|
+
}
|
|
1181
|
+
await this.ensureAgentsInOnDemandPhonebook(error.agentAddresses.map((address) => address.toLowerCase()), AbortSignal.timeout(SWM_RECIPIENT_KEY_FETCH_WAIT_MS));
|
|
1182
|
+
}
|
|
1183
|
+
try {
|
|
1184
|
+
return await resolveKeys();
|
|
1185
|
+
}
|
|
1186
|
+
catch (error) {
|
|
1187
|
+
throw isWorkspaceAgentEncryptionKeyMissingError(error) ? withMemberKeyHint(error) : error;
|
|
1188
|
+
}
|
|
889
1189
|
};
|
|
1190
|
+
let resolution = await resolveWithPhonebookHydration();
|
|
1191
|
+
if (transport.kind === 'private-roster'
|
|
1192
|
+
|| transport.kind === 'approved-private-replica'
|
|
1193
|
+
|| transport.kind === 'legacy-unregistered') {
|
|
1194
|
+
// Key and phonebook lookup are asynchronous. Re-read the paired
|
|
1195
|
+
// transport decision after them so an accepted-private (or registered)
|
|
1196
|
+
// roster rotation cannot return keys for a member removed meanwhile.
|
|
1197
|
+
// The store revision is deliberately conservative because recipient
|
|
1198
|
+
// facts can live in any named graph. Unrelated graph activity therefore
|
|
1199
|
+
// triggers a bounded optimistic retry, but a retry is accepted only when
|
|
1200
|
+
// both the exact (agent,key,peer) set and transport authority are stable.
|
|
1201
|
+
for (let attempt = 0; attempt < SWM_RECIPIENT_AUTHORITY_STABILITY_ATTEMPTS; attempt += 1) {
|
|
1202
|
+
const currentTransport = await withRpcUsageSite(CG_AUTH_RPC_SITES.recipients, () => this.resolveSwmTransportAuthority(input.contextGraphId, {
|
|
1203
|
+
authorityReadMode: 'finalized-index-or-live',
|
|
1204
|
+
requireLiveRosterForPrivate: true,
|
|
1205
|
+
}));
|
|
1206
|
+
if (currentTransport.kind === 'unavailable') {
|
|
1207
|
+
throw createContextGraphAuthorityError(`Context graph "${input.contextGraphId}" recipient authority is unavailable (${currentTransport.reason})`, currentTransport);
|
|
1208
|
+
}
|
|
1209
|
+
const transportStayedCurrent = transport.kind === 'private-roster'
|
|
1210
|
+
? currentTransport.kind === 'private-roster'
|
|
1211
|
+
&& resolution.requiresEncryption
|
|
1212
|
+
&& hasExactRecipientAgentRoster(resolution, currentTransport.participantAgents)
|
|
1213
|
+
: transport.kind === 'approved-private-replica'
|
|
1214
|
+
? currentTransport.kind === 'approved-private-replica'
|
|
1215
|
+
&& sameStringSet(transport.allowedPeers, currentTransport.allowedPeers)
|
|
1216
|
+
: currentTransport.kind === 'legacy-unregistered';
|
|
1217
|
+
const revisionStayedCurrent = recipientAuthorityRevision
|
|
1218
|
+
=== this.contextGraphMetaProjection.readAuthorityFactsRevision;
|
|
1219
|
+
if (transportStayedCurrent && revisionStayedCurrent)
|
|
1220
|
+
break;
|
|
1221
|
+
const hasAnotherAttempt = attempt + 1 < SWM_RECIPIENT_AUTHORITY_STABILITY_ATTEMPTS;
|
|
1222
|
+
if (!transportStayedCurrent || !hasAnotherAttempt) {
|
|
1223
|
+
throw createContextGraphAuthorityError(`Context graph "${input.contextGraphId}" private authority changed while recipient keys were resolving`, {
|
|
1224
|
+
reason: 'chain-participant-authority-unavailable',
|
|
1225
|
+
detail: 'retry recipient resolution against the current private authority',
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
1228
|
+
const retriedResolution = await resolveWithPhonebookHydration();
|
|
1229
|
+
const recipientSnapshotStayedCurrent = resolution.requiresEncryption
|
|
1230
|
+
? retriedResolution.requiresEncryption
|
|
1231
|
+
&& hasExactWorkspaceRecipientSet(resolution, retriedResolution)
|
|
1232
|
+
: !retriedResolution.requiresEncryption;
|
|
1233
|
+
if (!recipientSnapshotStayedCurrent) {
|
|
1234
|
+
throw createContextGraphAuthorityError(`Context graph "${input.contextGraphId}" private authority changed while recipient keys were resolving`, {
|
|
1235
|
+
reason: 'chain-participant-authority-unavailable',
|
|
1236
|
+
detail: 'recipient routes changed while retrying against current private authority',
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
resolution = retriedResolution;
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
return resolution;
|
|
890
1243
|
}
|
|
891
1244
|
async encryptWorkspacePayloadWithSenderKey(input) {
|
|
892
|
-
|
|
1245
|
+
let resolution = input.resolution;
|
|
1246
|
+
if (!this.swmSenderKeyStateLoaded) {
|
|
1247
|
+
await this.loadSwmSenderKeyState();
|
|
1248
|
+
// Recipient authority may have changed while durable state was loading.
|
|
1249
|
+
// Resolve once against the now-hydrated state and proceed only when the
|
|
1250
|
+
// exact agent/key/peer snapshot is unchanged. The production publisher
|
|
1251
|
+
// avoids this compatibility reread by hydrating in
|
|
1252
|
+
// resolveWorkspaceRecipientsGated above.
|
|
1253
|
+
const currentResolution = await this.resolveWorkspaceAgentRecipientsForCurrentAuthority({
|
|
1254
|
+
contextGraphId: input.contextGraphId,
|
|
1255
|
+
});
|
|
1256
|
+
if (!currentResolution.requiresEncryption
|
|
1257
|
+
|| !hasExactWorkspaceRecipientSet(resolution, currentResolution)) {
|
|
1258
|
+
throw createContextGraphAuthorityError(`Context graph "${input.contextGraphId}" authority changed while sender-key state was loading`, {
|
|
1259
|
+
reason: 'chain-participant-authority-unavailable',
|
|
1260
|
+
detail: 'retry recipient resolution before creating or reusing a sender-key epoch',
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
resolution = currentResolution;
|
|
1264
|
+
}
|
|
893
1265
|
const ctx = createOperationContext('share', input.operationId);
|
|
894
1266
|
const sender = this.getLocalSigningAgentForAddress(input.senderAgentAddress);
|
|
895
1267
|
if (!sender) {
|
|
896
1268
|
throw new Error(`Cannot create SWM Sender Key epoch: no local custodial signing key for agent ${input.senderAgentAddress}`);
|
|
897
1269
|
}
|
|
898
|
-
const resolution = input.resolution;
|
|
899
1270
|
const senderAddress = ethers.getAddress(sender.agentAddress);
|
|
900
1271
|
const recipientSet = new Set(resolution.recipients.map((recipient) => recipient.agentAddress.toLowerCase()));
|
|
901
1272
|
if (!recipientSet.has(senderAddress.toLowerCase())) {
|
|
@@ -914,9 +1285,16 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
914
1285
|
recipientKeyId: recipient.recipientKeyId,
|
|
915
1286
|
})),
|
|
916
1287
|
});
|
|
1288
|
+
const recipientRouteHash = computeSwmSenderKeyRecipientRouteHash({
|
|
1289
|
+
contextGraphId: input.contextGraphId,
|
|
1290
|
+
subGraphName: input.subGraphName,
|
|
1291
|
+
recipients: resolution.recipients,
|
|
1292
|
+
});
|
|
917
1293
|
const stateKey = swmSenderStateKey(input.contextGraphId, input.subGraphName, senderAddress);
|
|
918
1294
|
let state = this.swmSenderKeySendStates.get(stateKey);
|
|
919
|
-
if (!state
|
|
1295
|
+
if (!state
|
|
1296
|
+
|| state.membershipHash !== membershipHash
|
|
1297
|
+
|| state.recipientRouteHash !== recipientRouteHash) {
|
|
920
1298
|
const pruned = this.prunePendingSenderKeysForEpochRotation({
|
|
921
1299
|
contextGraphId: input.contextGraphId,
|
|
922
1300
|
subGraphName: input.subGraphName,
|
|
@@ -939,7 +1317,12 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
939
1317
|
await this.saveSwmSenderKeyState();
|
|
940
1318
|
}
|
|
941
1319
|
else {
|
|
942
|
-
await this.drainPendingSenderKeyForRecipients(resolution.recipients, ctx
|
|
1320
|
+
await this.drainPendingSenderKeyForRecipients(resolution.recipients, ctx, {
|
|
1321
|
+
contextGraphId: input.contextGraphId,
|
|
1322
|
+
subGraphName: input.subGraphName,
|
|
1323
|
+
senderAgentAddress: state.senderAgentAddress,
|
|
1324
|
+
epochId: state.epochId,
|
|
1325
|
+
});
|
|
943
1326
|
}
|
|
944
1327
|
const encrypted = await encryptSwmSenderKeyMessage({
|
|
945
1328
|
chainKey: state.chainKey,
|
|
@@ -974,6 +1357,11 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
974
1357
|
senderAgentAddress,
|
|
975
1358
|
epochId,
|
|
976
1359
|
membershipHash: input.membershipHash,
|
|
1360
|
+
recipientRouteHash: computeSwmSenderKeyRecipientRouteHash({
|
|
1361
|
+
contextGraphId: input.contextGraphId,
|
|
1362
|
+
subGraphName: input.subGraphName,
|
|
1363
|
+
recipients: input.recipients,
|
|
1364
|
+
}),
|
|
977
1365
|
chainKey,
|
|
978
1366
|
nextMessageIndex: 0,
|
|
979
1367
|
senderSigningSecretKey: senderSigningKeypair.secretKey,
|
|
@@ -989,7 +1377,18 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
989
1377
|
senderPrivateKey: input.sender.privateKey,
|
|
990
1378
|
});
|
|
991
1379
|
const packageBytes = encodeSwmSenderKeyPackage(pkg);
|
|
992
|
-
|
|
1380
|
+
const recipientIsLocal = this.hasLocalAgent(recipientAgentAddress);
|
|
1381
|
+
let targetsLocalPeer = recipient.peerId === undefined;
|
|
1382
|
+
if (recipientIsLocal && recipient.peerId !== undefined) {
|
|
1383
|
+
const localPeerId = this.node.peerId.toString();
|
|
1384
|
+
const canonicalRecipientPeerId = tryCanonicalPeerIdString(recipient.peerId);
|
|
1385
|
+
const canonicalLocalPeerId = tryCanonicalPeerIdString(localPeerId);
|
|
1386
|
+
targetsLocalPeer = recipient.peerId === localPeerId
|
|
1387
|
+
|| (canonicalRecipientPeerId !== null
|
|
1388
|
+
&& canonicalLocalPeerId !== null
|
|
1389
|
+
&& canonicalRecipientPeerId === canonicalLocalPeerId);
|
|
1390
|
+
}
|
|
1391
|
+
if (recipientIsLocal && targetsLocalPeer) {
|
|
993
1392
|
try {
|
|
994
1393
|
await this.acceptSwmSenderKeyPackage(pkg, this.node.peerId.toString(), input.ctx);
|
|
995
1394
|
return { kind: 'success', agentAddress: recipientAgentAddress };
|
|
@@ -1026,7 +1425,7 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1026
1425
|
});
|
|
1027
1426
|
pendingSenderKeyQueued = true;
|
|
1028
1427
|
this.log.warn(input.ctx, `SWM sender-key setup for ${recipientAgentAddress} keyId=${recipient.recipientKeyId} ` +
|
|
1029
|
-
`queued (no advertised peerId) — will deliver
|
|
1428
|
+
`queued (no advertised peerId) — will deliver after a verified peer route is learned`);
|
|
1030
1429
|
return { kind: 'success', agentAddress: recipientAgentAddress };
|
|
1031
1430
|
}
|
|
1032
1431
|
this.log.info(input.ctx, `SWM sender-key setup send: senderAgent=${senderAgentAddress} recipientAgent=${recipientAgentAddress} ` +
|
|
@@ -1067,6 +1466,7 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1067
1466
|
senderAgentAddress: senderAgentAddress.toLowerCase(),
|
|
1068
1467
|
recipientAgentAddress: recipientAgentAddress.toLowerCase(),
|
|
1069
1468
|
recipientKeyId: recipient.recipientKeyId,
|
|
1469
|
+
recipientPeerId: recipient.peerId,
|
|
1070
1470
|
epochId: state.epochId,
|
|
1071
1471
|
contextGraphId: state.contextGraphId,
|
|
1072
1472
|
subGraphName: state.subGraphName,
|
|
@@ -1088,6 +1488,7 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1088
1488
|
senderAgentAddress: senderAgentAddress.toLowerCase(),
|
|
1089
1489
|
recipientAgentAddress: recipientAgentAddress.toLowerCase(),
|
|
1090
1490
|
recipientKeyId: recipient.recipientKeyId,
|
|
1491
|
+
recipientPeerId: recipient.peerId,
|
|
1091
1492
|
epochId: state.epochId,
|
|
1092
1493
|
contextGraphId: state.contextGraphId,
|
|
1093
1494
|
subGraphName: state.subGraphName,
|
|
@@ -1106,6 +1507,7 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1106
1507
|
senderAgentAddress: senderAgentAddress.toLowerCase(),
|
|
1107
1508
|
recipientAgentAddress: recipientAgentAddress.toLowerCase(),
|
|
1108
1509
|
recipientKeyId: recipient.recipientKeyId,
|
|
1510
|
+
recipientPeerId: recipient.peerId,
|
|
1109
1511
|
epochId: state.epochId,
|
|
1110
1512
|
contextGraphId: state.contextGraphId,
|
|
1111
1513
|
subGraphName: state.subGraphName,
|
|
@@ -1125,6 +1527,7 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1125
1527
|
senderAgentAddress: senderAgentAddress.toLowerCase(),
|
|
1126
1528
|
recipientAgentAddress: recipientAgentAddress.toLowerCase(),
|
|
1127
1529
|
recipientKeyId: recipient.recipientKeyId,
|
|
1530
|
+
recipientPeerId: recipient.peerId,
|
|
1128
1531
|
epochId: state.epochId,
|
|
1129
1532
|
contextGraphId: state.contextGraphId,
|
|
1130
1533
|
subGraphName: state.subGraphName,
|
|
@@ -1233,26 +1636,34 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1233
1636
|
/**
|
|
1234
1637
|
* PR-2 (SWM-fanout plan): enqueue a sender-key package whose recipient
|
|
1235
1638
|
* has no advertised `dkg:peerId` (so we can't even ask the messenger
|
|
1236
|
-
* to queue it). Older epochs for the same `(sender, recipient
|
|
1237
|
-
* are evicted — a newer epoch supersedes them by
|
|
1639
|
+
* to queue it). Older epochs for the same `(sender, recipient, context
|
|
1640
|
+
* graph, subgraph)` scope are evicted — a newer epoch supersedes them by
|
|
1641
|
+
* definition. Other graph/subgraph obligations remain independent.
|
|
1238
1642
|
*
|
|
1239
|
-
* Per-
|
|
1240
|
-
* matches an existing row, we replace it
|
|
1643
|
+
* Per-route dedup: `(senderAgentAddress, recipientKeyId,
|
|
1644
|
+
* recipientPeerId, epochId)` matches an existing row, we replace it
|
|
1645
|
+
* (idempotent re-enqueue). Distinct peers advertising the same key retain
|
|
1646
|
+
* independent delivery obligations.
|
|
1241
1647
|
*/
|
|
1242
1648
|
enqueuePendingSenderKey(entry) {
|
|
1243
1649
|
const recipientKey = entry.recipientAgentAddress.toLowerCase();
|
|
1244
1650
|
const existing = this.pendingSenderKeyByAgent.get(recipientKey) ?? [];
|
|
1245
|
-
// Drop older epochs
|
|
1246
|
-
// epoch's membership
|
|
1247
|
-
//
|
|
1651
|
+
// Drop older epochs only within the same sender + graph/subgraph scope;
|
|
1652
|
+
// the newer epoch's membership hash supersedes those rows. The map key
|
|
1653
|
+
// already scopes recipient agent. Keep every other scope unchanged.
|
|
1248
1654
|
const filtered = existing.filter((e) => {
|
|
1249
1655
|
if (e.senderAgentAddress !== entry.senderAgentAddress)
|
|
1250
1656
|
return true;
|
|
1657
|
+
if (e.contextGraphId !== entry.contextGraphId
|
|
1658
|
+
|| (e.subGraphName ?? undefined) !== (entry.subGraphName ?? undefined)) {
|
|
1659
|
+
return true;
|
|
1660
|
+
}
|
|
1251
1661
|
if (e.epochId === entry.epochId) {
|
|
1252
|
-
// Same epoch: dedupe
|
|
1253
|
-
//
|
|
1254
|
-
//
|
|
1255
|
-
return e.recipientKeyId !== entry.recipientKeyId
|
|
1662
|
+
// Same epoch: dedupe only the exact key + peer route. A successful
|
|
1663
|
+
// ACK from one peer must never overwrite a retry owed to another peer
|
|
1664
|
+
// that advertises the same agent/key pair.
|
|
1665
|
+
return e.recipientKeyId !== entry.recipientKeyId
|
|
1666
|
+
|| e.recipientPeerId !== entry.recipientPeerId;
|
|
1256
1667
|
}
|
|
1257
1668
|
return false;
|
|
1258
1669
|
});
|
|
@@ -1281,17 +1692,21 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1281
1692
|
return removed;
|
|
1282
1693
|
}
|
|
1283
1694
|
async drainPendingSenderKeyQueueForPeer(input) {
|
|
1284
|
-
const
|
|
1695
|
+
const authority = {
|
|
1696
|
+
...input.authority,
|
|
1697
|
+
recipientAgentAddress: input.authority.recipientAgentAddress.toLowerCase(),
|
|
1698
|
+
senderAgentAddress: input.authority.senderAgentAddress?.toLowerCase(),
|
|
1699
|
+
};
|
|
1700
|
+
const recipientAgentAddress = authority.recipientAgentAddress;
|
|
1285
1701
|
const existingDrain = this.pendingSenderKeyDrainByAgent.get(recipientAgentAddress);
|
|
1286
1702
|
if (existingDrain) {
|
|
1287
1703
|
await existingDrain;
|
|
1288
1704
|
if (!this.pendingSenderKeyByAgent.has(recipientAgentAddress))
|
|
1289
1705
|
return 0;
|
|
1290
|
-
return this.drainPendingSenderKeyQueueForPeer(input);
|
|
1706
|
+
return this.drainPendingSenderKeyQueueForPeer({ authority, ctx: input.ctx });
|
|
1291
1707
|
}
|
|
1292
1708
|
const drain = this.drainPendingSenderKeyQueueForPeerLocked({
|
|
1293
|
-
|
|
1294
|
-
recipientAgentAddress,
|
|
1709
|
+
authority,
|
|
1295
1710
|
ctx: input.ctx,
|
|
1296
1711
|
}).finally(() => {
|
|
1297
1712
|
if (this.pendingSenderKeyDrainByAgent.get(recipientAgentAddress) === drain) {
|
|
@@ -1302,19 +1717,75 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1302
1717
|
return drain;
|
|
1303
1718
|
}
|
|
1304
1719
|
async drainPendingSenderKeyQueueForPeerLocked(input) {
|
|
1305
|
-
const
|
|
1720
|
+
const { authority } = input;
|
|
1721
|
+
const recipientAgentAddress = authority.recipientAgentAddress;
|
|
1306
1722
|
const queue = this.pendingSenderKeyByAgent.get(recipientAgentAddress);
|
|
1307
1723
|
if (!queue || queue.length === 0)
|
|
1308
1724
|
return 0;
|
|
1309
1725
|
let drained = 0;
|
|
1310
|
-
|
|
1726
|
+
// `sendReliable` yields. Enqueue/epoch rotation can replace the live array
|
|
1727
|
+
// while this drain is in flight, so record outcomes against the exact
|
|
1728
|
+
// snapshot objects instead of later overwriting the whole map entry. At
|
|
1729
|
+
// commit, only original objects still present in the live queue are
|
|
1730
|
+
// transformed; concurrently inserted replacements/new scopes survive and
|
|
1731
|
+
// originals concurrently superseded by a new epoch are not resurrected.
|
|
1732
|
+
const outcomes = new Map();
|
|
1733
|
+
const commitOutcomes = () => {
|
|
1734
|
+
const live = this.pendingSenderKeyByAgent.get(recipientAgentAddress) ?? [];
|
|
1735
|
+
const reconciled = [];
|
|
1736
|
+
for (const liveEntry of live) {
|
|
1737
|
+
if (!outcomes.has(liveEntry)) {
|
|
1738
|
+
reconciled.push(liveEntry);
|
|
1739
|
+
continue;
|
|
1740
|
+
}
|
|
1741
|
+
const replacement = outcomes.get(liveEntry);
|
|
1742
|
+
if (replacement)
|
|
1743
|
+
reconciled.push(replacement);
|
|
1744
|
+
}
|
|
1745
|
+
if (reconciled.length === 0) {
|
|
1746
|
+
this.pendingSenderKeyByAgent.delete(recipientAgentAddress);
|
|
1747
|
+
}
|
|
1748
|
+
else {
|
|
1749
|
+
this.pendingSenderKeyByAgent.set(recipientAgentAddress, reconciled);
|
|
1750
|
+
}
|
|
1751
|
+
};
|
|
1311
1752
|
for (let i = 0; i < queue.length; i += 1) {
|
|
1312
1753
|
const entry = queue[i];
|
|
1754
|
+
// A row may only be consumed by the caller's exact current-authority
|
|
1755
|
+
// route and graph scope. Legacy/no-peer rows are expanded into explicit
|
|
1756
|
+
// peer-bound obligations before reaching this drain. Foreground callers
|
|
1757
|
+
// additionally bind the current sender + epoch; connection-open callers
|
|
1758
|
+
// explicitly authorize every subgraph for one resolved CG.
|
|
1759
|
+
if (!pendingSenderKeyEntryMatchesDrainAuthority(entry, authority)) {
|
|
1760
|
+
outcomes.set(entry, entry);
|
|
1761
|
+
continue;
|
|
1762
|
+
}
|
|
1763
|
+
// Authority can change while this route waits for the per-agent drain
|
|
1764
|
+
// lock, or while a preceding row is in flight. Re-resolve immediately
|
|
1765
|
+
// before every send so a stale caller snapshot can never consume a row.
|
|
1766
|
+
let routeStillCurrent = false;
|
|
1313
1767
|
try {
|
|
1314
|
-
const
|
|
1768
|
+
const resolution = await this.resolveWorkspaceAgentRecipientsForCurrentAuthority({
|
|
1769
|
+
contextGraphId: entry.contextGraphId,
|
|
1770
|
+
});
|
|
1771
|
+
routeStillCurrent = resolution.requiresEncryption
|
|
1772
|
+
&& resolution.recipients.some((recipient) => (recipient.agentAddress.toLowerCase() === entry.recipientAgentAddress
|
|
1773
|
+
&& recipient.recipientKeyId === entry.recipientKeyId
|
|
1774
|
+
&& recipient.peerId === entry.recipientPeerId));
|
|
1775
|
+
}
|
|
1776
|
+
catch {
|
|
1777
|
+
// Fail closed. The queued obligation remains available for a later
|
|
1778
|
+
// current-authority retry.
|
|
1779
|
+
}
|
|
1780
|
+
if (!routeStillCurrent) {
|
|
1781
|
+
outcomes.set(entry, entry);
|
|
1782
|
+
continue;
|
|
1783
|
+
}
|
|
1784
|
+
try {
|
|
1785
|
+
const sendResult = await this.messenger.sendReliable(authority.recipientPeerId, PROTOCOL_SWM_SENDER_KEY, entry.packageBytes, { messageId: this.swmSenderKeyPendingMessageId(entry) });
|
|
1315
1786
|
if (!sendResult.delivered) {
|
|
1316
1787
|
if (sendResult.queued || ('inFlight' in sendResult && sendResult.inFlight)) {
|
|
1317
|
-
|
|
1788
|
+
outcomes.set(entry, entry);
|
|
1318
1789
|
continue;
|
|
1319
1790
|
}
|
|
1320
1791
|
throw new Error(`Unexpected undelivered Sender Key retry result: ${sendResult.error}`);
|
|
@@ -1326,65 +1797,134 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1326
1797
|
catch {
|
|
1327
1798
|
// Malformed/legacy ACK: no positive acceptance yet. Keep the
|
|
1328
1799
|
// row queued so a mixed-version rollout cannot strand the recipient.
|
|
1329
|
-
|
|
1800
|
+
outcomes.set(entry, this.rotateSwmSenderKeyPendingMessageId(entry));
|
|
1330
1801
|
continue;
|
|
1331
1802
|
}
|
|
1332
1803
|
if (ack.version !== SWM_SENDER_KEY_PACKAGE_VERSION ||
|
|
1333
1804
|
ack.type !== SWM_SENDER_KEY_PACKAGE_ACK_TYPE) {
|
|
1334
1805
|
// Malformed/legacy ACK: no positive acceptance yet. Keep the
|
|
1335
1806
|
// row queued so a mixed-version rollout cannot strand the recipient.
|
|
1336
|
-
|
|
1807
|
+
outcomes.set(entry, this.rotateSwmSenderKeyPendingMessageId(entry));
|
|
1337
1808
|
continue;
|
|
1338
1809
|
}
|
|
1339
1810
|
if (ack.accepted) {
|
|
1340
1811
|
drained += 1;
|
|
1812
|
+
outcomes.set(entry, null);
|
|
1341
1813
|
}
|
|
1342
1814
|
else if (this.isRetryableSwmSenderKeySetupAckReason(ack.reasonCode)) {
|
|
1343
|
-
|
|
1815
|
+
outcomes.set(entry, this.rotateSwmSenderKeyPendingMessageId(entry));
|
|
1344
1816
|
}
|
|
1345
1817
|
else {
|
|
1346
1818
|
const reason = ack.reason ?? 'unknown reason';
|
|
1347
1819
|
const reasonCode = ack.reasonCode ?? 'legacy-unknown';
|
|
1348
1820
|
this.log.warn(input.ctx ?? SWM_SENDER_KEY_PENDING_DRAIN_LOG_CTX, `SWM sender-key pending retry for ${entry.recipientAgentAddress} keyId=${entry.recipientKeyId} ` +
|
|
1349
|
-
`peerId=${
|
|
1821
|
+
`peerId=${authority.recipientPeerId} contextGraph=${entry.contextGraphId}${entry.subGraphName ? `/${entry.subGraphName}` : ''} ` +
|
|
1350
1822
|
`dropped after terminal rejection (${reasonCode}): ${reason}`);
|
|
1351
1823
|
// Terminal rejection: keep it out of the queue, but do not
|
|
1352
1824
|
// report it as a successful drain.
|
|
1825
|
+
outcomes.set(entry, null);
|
|
1353
1826
|
}
|
|
1354
1827
|
}
|
|
1355
1828
|
catch (err) {
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
}
|
|
1360
|
-
else {
|
|
1361
|
-
this.pendingSenderKeyByAgent.set(recipientAgentAddress, remaining);
|
|
1829
|
+
outcomes.set(entry, entry);
|
|
1830
|
+
for (const unprocessed of queue.slice(i + 1)) {
|
|
1831
|
+
outcomes.set(unprocessed, unprocessed);
|
|
1362
1832
|
}
|
|
1833
|
+
commitOutcomes();
|
|
1363
1834
|
await this.saveSwmSenderKeyState();
|
|
1364
1835
|
const message = err instanceof Error ? err.message : String(err);
|
|
1365
1836
|
this.log.warn(input.ctx ?? SWM_SENDER_KEY_PENDING_DRAIN_LOG_CTX, `SWM sender-key pending retry for ${entry.recipientAgentAddress} keyId=${entry.recipientKeyId} ` +
|
|
1366
|
-
`peerId=${
|
|
1837
|
+
`peerId=${authority.recipientPeerId} contextGraph=${entry.contextGraphId}${entry.subGraphName ? `/${entry.subGraphName}` : ''} ` +
|
|
1367
1838
|
`failed before the Messenger substrate queued a retry: ${message}`);
|
|
1368
1839
|
throw err;
|
|
1369
1840
|
}
|
|
1370
1841
|
}
|
|
1371
|
-
|
|
1372
|
-
this.pendingSenderKeyByAgent.delete(recipientAgentAddress);
|
|
1373
|
-
}
|
|
1374
|
-
else {
|
|
1375
|
-
this.pendingSenderKeyByAgent.set(recipientAgentAddress, remaining);
|
|
1376
|
-
}
|
|
1842
|
+
commitOutcomes();
|
|
1377
1843
|
await this.saveSwmSenderKeyState();
|
|
1378
1844
|
return drained;
|
|
1379
1845
|
}
|
|
1380
1846
|
/**
|
|
1381
|
-
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1847
|
+
* Upgrade legacy/no-peer pending rows into one durable obligation per exact
|
|
1848
|
+
* `(agent, key, peer)` route in a current authority-fenced recipient
|
|
1849
|
+
* snapshot. The replacement is synchronous so drains can never observe a
|
|
1850
|
+
* partially expanded multi-peer obligation.
|
|
1851
|
+
*/
|
|
1852
|
+
expandUnboundPendingSenderKeyRoutes(input) {
|
|
1853
|
+
const peersByAgentAndKey = new Map();
|
|
1854
|
+
for (const recipient of input.recipients) {
|
|
1855
|
+
if (!recipient.peerId)
|
|
1856
|
+
continue;
|
|
1857
|
+
const routeKey = `${recipient.agentAddress.toLowerCase()}\0${recipient.recipientKeyId}`;
|
|
1858
|
+
const peers = peersByAgentAndKey.get(routeKey) ?? new Set();
|
|
1859
|
+
peers.add(recipient.peerId);
|
|
1860
|
+
peersByAgentAndKey.set(routeKey, peers);
|
|
1861
|
+
}
|
|
1862
|
+
if (peersByAgentAndKey.size === 0)
|
|
1863
|
+
return 0;
|
|
1864
|
+
const boundRouteIdentity = (entry, peerId) => JSON.stringify([
|
|
1865
|
+
entry.senderAgentAddress,
|
|
1866
|
+
entry.recipientKeyId,
|
|
1867
|
+
peerId,
|
|
1868
|
+
entry.epochId,
|
|
1869
|
+
entry.contextGraphId,
|
|
1870
|
+
entry.subGraphName ?? null,
|
|
1871
|
+
]);
|
|
1872
|
+
const senderAgentAddress = input.senderAgentAddress?.toLowerCase();
|
|
1873
|
+
let expanded = 0;
|
|
1874
|
+
for (const [recipientAgentAddress, queue] of this.pendingSenderKeyByAgent.entries()) {
|
|
1875
|
+
const existingBoundRoutes = new Set(queue
|
|
1876
|
+
.flatMap((entry) => entry.recipientPeerId === undefined
|
|
1877
|
+
? []
|
|
1878
|
+
: [boundRouteIdentity(entry, entry.recipientPeerId)]));
|
|
1879
|
+
let changed = false;
|
|
1880
|
+
const replacement = [];
|
|
1881
|
+
for (const entry of queue) {
|
|
1882
|
+
const matchesScope = entry.contextGraphId === input.contextGraphId
|
|
1883
|
+
&& (input.allSubgraphs
|
|
1884
|
+
|| (entry.subGraphName ?? undefined) === (input.subGraphName ?? undefined))
|
|
1885
|
+
&& (senderAgentAddress === undefined || entry.senderAgentAddress === senderAgentAddress)
|
|
1886
|
+
&& (input.epochId === undefined || entry.epochId === input.epochId);
|
|
1887
|
+
if (entry.recipientPeerId !== undefined || !matchesScope) {
|
|
1888
|
+
replacement.push(entry);
|
|
1889
|
+
continue;
|
|
1890
|
+
}
|
|
1891
|
+
const peers = peersByAgentAndKey.get(`${entry.recipientAgentAddress}\0${entry.recipientKeyId}`);
|
|
1892
|
+
if (!peers || peers.size === 0) {
|
|
1893
|
+
replacement.push(entry);
|
|
1894
|
+
continue;
|
|
1895
|
+
}
|
|
1896
|
+
changed = true;
|
|
1897
|
+
expanded += 1;
|
|
1898
|
+
for (const peerId of peers) {
|
|
1899
|
+
const identity = boundRouteIdentity(entry, peerId);
|
|
1900
|
+
if (existingBoundRoutes.has(identity))
|
|
1901
|
+
continue;
|
|
1902
|
+
replacement.push({ ...entry, recipientPeerId: peerId });
|
|
1903
|
+
existingBoundRoutes.add(identity);
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
if (changed) {
|
|
1907
|
+
if (replacement.length === 0) {
|
|
1908
|
+
this.pendingSenderKeyByAgent.delete(recipientAgentAddress);
|
|
1909
|
+
}
|
|
1910
|
+
else {
|
|
1911
|
+
this.pendingSenderKeyByAgent.set(recipientAgentAddress, replacement);
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
return expanded;
|
|
1916
|
+
}
|
|
1917
|
+
/**
|
|
1918
|
+
* Drain queued sender-key packages whose exact current recipient route is
|
|
1919
|
+
* the newly connected `peerId`. Returns the number of rows successfully
|
|
1920
|
+
* delivered (acked) and removed.
|
|
1384
1921
|
*
|
|
1385
1922
|
* Fired from the `connection:open` listener — see line 2382 — so the
|
|
1386
1923
|
* cost lives on the cold path of "we just connected to a new peer",
|
|
1387
|
-
* not on every share.
|
|
1924
|
+
* not on every share. Every context graph represented by either a bound or
|
|
1925
|
+
* legacy row is resolved first; bound rows never bypass that authority read.
|
|
1926
|
+
* Legacy/no-peer rows are expanded only from that graph's current,
|
|
1927
|
+
* authority-fenced recipient snapshot. Each successful `sendReliable` with
|
|
1388
1928
|
* `delivered=true && ack.accepted=true` deletes the row and counts as
|
|
1389
1929
|
* drained; soft (`delivered=false`) and explicitly retryable delivered
|
|
1390
1930
|
* rejections leave it queued for the next attempt; terminal delivered
|
|
@@ -1395,21 +1935,80 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1395
1935
|
if (this.pendingSenderKeyByAgent.size === 0)
|
|
1396
1936
|
return 0;
|
|
1397
1937
|
let drained = 0;
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1938
|
+
const pendingContextGraphIds = new Set([...this.pendingSenderKeyByAgent.values()]
|
|
1939
|
+
.flatMap((queue) => queue
|
|
1940
|
+
.filter((entry) => entry.recipientPeerId === undefined || entry.recipientPeerId === peerId)
|
|
1941
|
+
.map((entry) => entry.contextGraphId)));
|
|
1942
|
+
let expandedRows = 0;
|
|
1943
|
+
for (const contextGraphId of pendingContextGraphIds) {
|
|
1944
|
+
let resolution;
|
|
1945
|
+
try {
|
|
1946
|
+
resolution = await this.resolveWorkspaceAgentRecipientsForCurrentAuthority({
|
|
1947
|
+
contextGraphId,
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
catch {
|
|
1951
|
+
// Authority/key resolution failure is benign on connection-open. No
|
|
1952
|
+
// row for this CG — including already bound rows — may bypass it.
|
|
1953
|
+
continue;
|
|
1954
|
+
}
|
|
1955
|
+
if (!resolution.requiresEncryption)
|
|
1956
|
+
continue;
|
|
1957
|
+
expandedRows += this.expandUnboundPendingSenderKeyRoutes({
|
|
1958
|
+
recipients: resolution.recipients,
|
|
1959
|
+
contextGraphId,
|
|
1960
|
+
allSubgraphs: true,
|
|
1961
|
+
});
|
|
1962
|
+
const routes = new Map();
|
|
1963
|
+
for (const recipient of resolution.recipients) {
|
|
1964
|
+
if (recipient.peerId !== peerId)
|
|
1965
|
+
continue;
|
|
1966
|
+
const recipientAgentAddress = recipient.agentAddress.toLowerCase();
|
|
1967
|
+
const authority = {
|
|
1968
|
+
contextGraphId,
|
|
1969
|
+
allSubgraphs: true,
|
|
1970
|
+
recipientAgentAddress,
|
|
1971
|
+
recipientKeyId: recipient.recipientKeyId,
|
|
1972
|
+
recipientPeerId: peerId,
|
|
1973
|
+
};
|
|
1974
|
+
const queue = this.pendingSenderKeyByAgent.get(recipientAgentAddress);
|
|
1975
|
+
if (!queue?.some((entry) => (pendingSenderKeyEntryMatchesDrainAuthority(entry, authority))))
|
|
1976
|
+
continue;
|
|
1977
|
+
routes.set(`${recipientAgentAddress}\0${recipient.recipientKeyId}\0${peerId}`, authority);
|
|
1978
|
+
}
|
|
1979
|
+
for (const authority of routes.values()) {
|
|
1980
|
+
drained += await this.drainPendingSenderKeyQueueForPeer({ authority, ctx });
|
|
1403
1981
|
}
|
|
1404
1982
|
}
|
|
1405
|
-
|
|
1406
|
-
//
|
|
1407
|
-
//
|
|
1983
|
+
if (expandedRows > 0) {
|
|
1984
|
+
// A connection can teach us routes for another peer. Persist that legacy
|
|
1985
|
+
// migration even when this peer had no exact authorized row to drain.
|
|
1986
|
+
await this.saveSwmSenderKeyState();
|
|
1408
1987
|
}
|
|
1409
|
-
|
|
1988
|
+
return drained;
|
|
1989
|
+
}
|
|
1990
|
+
/**
|
|
1991
|
+
* A delivered Sender Key setup can receive a retryable authority denial.
|
|
1992
|
+
* That leaves a durable pending row but does not create a Messenger outbox
|
|
1993
|
+
* retry, and an already-connected recipient may never produce another
|
|
1994
|
+
* connection:open event. Retry only peer-bound rows on the ordinary outbox
|
|
1995
|
+
* cadence. The drain below re-resolves current graph authority and the exact
|
|
1996
|
+
* recipient key/peer route before sending any package.
|
|
1997
|
+
*/
|
|
1998
|
+
async drainPendingSenderKeysForConnectedPeers() {
|
|
1999
|
+
await this.loadSwmSenderKeyState();
|
|
2000
|
+
if (this.pendingSenderKeyByAgent.size === 0 || !this.node.isStarted)
|
|
2001
|
+
return 0;
|
|
2002
|
+
const pendingPeers = new Set([...this.pendingSenderKeyByAgent.values()]
|
|
2003
|
+
.flatMap((queue) => queue.flatMap((entry) => entry.recipientPeerId === undefined ? [] : [entry.recipientPeerId])));
|
|
2004
|
+
if (pendingPeers.size === 0)
|
|
1410
2005
|
return 0;
|
|
1411
|
-
|
|
1412
|
-
|
|
2006
|
+
let drained = 0;
|
|
2007
|
+
for (const peer of this.node.libp2p.getPeers()) {
|
|
2008
|
+
const peerId = peer.toString();
|
|
2009
|
+
if (!pendingPeers.has(peerId))
|
|
2010
|
+
continue;
|
|
2011
|
+
drained += await this.drainPendingSenderKeyForPeer(peerId);
|
|
1413
2012
|
}
|
|
1414
2013
|
return drained;
|
|
1415
2014
|
}
|
|
@@ -1419,25 +2018,41 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1419
2018
|
* connections where no fresh connection:open event will fire after the
|
|
1420
2019
|
* remote membership/key view converges.
|
|
1421
2020
|
*/
|
|
1422
|
-
async drainPendingSenderKeyForRecipients(recipients, ctx) {
|
|
2021
|
+
async drainPendingSenderKeyForRecipients(recipients, ctx, scope) {
|
|
1423
2022
|
if (this.pendingSenderKeyByAgent.size === 0)
|
|
1424
2023
|
return 0;
|
|
1425
|
-
const
|
|
2024
|
+
const senderAgentAddress = scope.senderAgentAddress.toLowerCase();
|
|
2025
|
+
this.expandUnboundPendingSenderKeyRoutes({
|
|
2026
|
+
recipients,
|
|
2027
|
+
contextGraphId: scope.contextGraphId,
|
|
2028
|
+
subGraphName: scope.subGraphName,
|
|
2029
|
+
senderAgentAddress,
|
|
2030
|
+
epochId: scope.epochId,
|
|
2031
|
+
});
|
|
2032
|
+
const routes = new Map();
|
|
1426
2033
|
for (const recipient of recipients) {
|
|
1427
2034
|
if (!recipient.peerId)
|
|
1428
2035
|
continue;
|
|
1429
2036
|
const recipientAgentAddress = recipient.agentAddress.toLowerCase();
|
|
1430
2037
|
if (!this.pendingSenderKeyByAgent.has(recipientAgentAddress))
|
|
1431
2038
|
continue;
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
2039
|
+
const authority = {
|
|
2040
|
+
contextGraphId: scope.contextGraphId,
|
|
2041
|
+
subGraphName: scope.subGraphName,
|
|
2042
|
+
senderAgentAddress,
|
|
2043
|
+
epochId: scope.epochId,
|
|
2044
|
+
recipientAgentAddress,
|
|
2045
|
+
recipientKeyId: recipient.recipientKeyId,
|
|
2046
|
+
recipientPeerId: recipient.peerId,
|
|
2047
|
+
};
|
|
2048
|
+
const routeKey = `${recipientAgentAddress}\0${recipient.recipientKeyId}\0${recipient.peerId}`;
|
|
2049
|
+
routes.set(routeKey, authority);
|
|
1435
2050
|
}
|
|
1436
|
-
if (
|
|
2051
|
+
if (routes.size === 0)
|
|
1437
2052
|
return 0;
|
|
1438
2053
|
let drained = 0;
|
|
1439
|
-
for (const
|
|
1440
|
-
drained += await this.drainPendingSenderKeyQueueForPeer({
|
|
2054
|
+
for (const authority of routes.values()) {
|
|
2055
|
+
drained += await this.drainPendingSenderKeyQueueForPeer({ authority, ctx });
|
|
1441
2056
|
}
|
|
1442
2057
|
if (drained > 0 && ctx) {
|
|
1443
2058
|
this.log.info(ctx, `SWM sender-key pending retry drained ${drained} queued package(s) during publish`);
|
|
@@ -1667,7 +2282,21 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1667
2282
|
if (recovered.toLowerCase() !== senderAgentAddress.toLowerCase()) {
|
|
1668
2283
|
throw new SwmSenderKeySetupRejectionError('bad-signature', `Sender Key setup signature recovered ${recovered}, expected ${senderAgentAddress}`);
|
|
1669
2284
|
}
|
|
1670
|
-
const
|
|
2285
|
+
const agentGateAuthority = await withRpcUsageSite(CG_AUTH_RPC_SITES.senderKeyAccept, () => this.resolveContextGraphAgentGateAuthority(pkg.contextGraphId));
|
|
2286
|
+
if (agentGateAuthority.kind === 'unavailable') {
|
|
2287
|
+
// Not knowing the gate is not evidence that either endpoint is outside
|
|
2288
|
+
// it. Answering `sender-not-allowed` here made an authority failure look
|
|
2289
|
+
// like a membership decision (#2827). A transient failure asks the
|
|
2290
|
+
// sender to retain and retry the package; one that needs a software or
|
|
2291
|
+
// configuration change is terminal, classified exactly as the promote
|
|
2292
|
+
// retry is (isRetryableContextGraphAuthorityUnavailableReason).
|
|
2293
|
+
throw new SwmSenderKeySetupRejectionError(isRetryableContextGraphAuthorityUnavailableReason(agentGateAuthority.reason)
|
|
2294
|
+
? 'agent-gate-pending'
|
|
2295
|
+
: 'agent-gate-unavailable', `Context graph "${pkg.contextGraphId}" agent gate authority is unavailable (${agentGateAuthority.reason})`);
|
|
2296
|
+
}
|
|
2297
|
+
const agentGateAddresses = agentGateAuthority.kind === 'available'
|
|
2298
|
+
? agentGateAuthority.agentAddresses
|
|
2299
|
+
: null;
|
|
1671
2300
|
if (!agentGateAddresses) {
|
|
1672
2301
|
// A cold private member can receive Sender Key setup after the finalized
|
|
1673
2302
|
// chain binding but before its accepted RFC-64 roster or legacy `_meta`
|
|
@@ -1689,7 +2318,17 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
1689
2318
|
if (!agentGateSet.has(recipientAgentAddress.toLowerCase())) {
|
|
1690
2319
|
throw new SwmSenderKeySetupRejectionError('recipient-not-allowed', `Recipient agent ${recipientAgentAddress} is not allowed for context graph "${pkg.contextGraphId}"`);
|
|
1691
2320
|
}
|
|
1692
|
-
|
|
2321
|
+
let allowedPeers;
|
|
2322
|
+
try {
|
|
2323
|
+
allowedPeers = await this.resolveSwmAllowedPeersForCurrentAuthority(pkg.contextGraphId);
|
|
2324
|
+
}
|
|
2325
|
+
catch (error) {
|
|
2326
|
+
if (!isContextGraphAuthorityUnavailableMarker(error))
|
|
2327
|
+
throw error;
|
|
2328
|
+
throw new SwmSenderKeySetupRejectionError(isRetryableContextGraphAuthorityUnavailableReason(error.reason)
|
|
2329
|
+
? 'agent-gate-pending'
|
|
2330
|
+
: 'agent-gate-unavailable', `Context graph "${pkg.contextGraphId}" SWM peer gate authority is unavailable (${error.reason})`);
|
|
2331
|
+
}
|
|
1693
2332
|
if (allowedPeers !== null && !allowedPeers.includes(fromPeerId)) {
|
|
1694
2333
|
throw new SwmSenderKeySetupRejectionError('sender-not-allowed', `Sender peer ${fromPeerId} is not allowed for context graph "${pkg.contextGraphId}"`);
|
|
1695
2334
|
}
|
|
@@ -2018,23 +2657,32 @@ export class WorkspaceCryptoMethods extends DKGAgentBase {
|
|
|
2018
2657
|
const path = this.swmSenderKeyStatePath();
|
|
2019
2658
|
if (!path)
|
|
2020
2659
|
return;
|
|
2021
|
-
const
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2660
|
+
const save = this.swmSenderKeyStateSaveQueue.then(async () => {
|
|
2661
|
+
const { mkdir, writeFile, chmod } = await import('node:fs/promises');
|
|
2662
|
+
const { dirname } = await import('node:path');
|
|
2663
|
+
await mkdir(dirname(path), { recursive: true });
|
|
2664
|
+
// Capture inside the serialized section. A caller queued behind an
|
|
2665
|
+
// in-flight write must persist the state current when its turn begins,
|
|
2666
|
+
// not a stale snapshot captured while the older write was outstanding.
|
|
2667
|
+
const payload = {
|
|
2668
|
+
version: 1,
|
|
2669
|
+
send: [...this.swmSenderKeySendStates.values()].map(serializeSwmSenderSendState),
|
|
2670
|
+
receive: [...this.swmSenderKeyReceiveStates.values()].map(serializeSwmSenderReceiveState),
|
|
2671
|
+
pending: [...this.pendingSenderKeyByAgent.values()]
|
|
2672
|
+
.flatMap((queue) => queue.map(serializePendingSenderKeyEntry)),
|
|
2673
|
+
};
|
|
2674
|
+
await writeFile(path, JSON.stringify(payload, null, 2), { mode: 0o600 });
|
|
2675
|
+
try {
|
|
2676
|
+
await chmod(path, 0o600);
|
|
2677
|
+
}
|
|
2678
|
+
catch {
|
|
2679
|
+
// Best-effort on platforms/filesystems that do not support chmod.
|
|
2680
|
+
}
|
|
2681
|
+
});
|
|
2682
|
+
// A failed save is still reported to its caller, but must not poison the
|
|
2683
|
+
// queue and suppress every later persistence attempt.
|
|
2684
|
+
this.swmSenderKeyStateSaveQueue = save.catch(() => undefined);
|
|
2685
|
+
await save;
|
|
2038
2686
|
}
|
|
2039
2687
|
async resolveWorkspaceGossipSigningAgent(contextGraphId) {
|
|
2040
2688
|
const authority = await withRpcUsageSite(CG_AUTH_RPC_SITES.signer, () => this.resolveContextGraphAgentGateAuthority(contextGraphId));
|