@cello-protocol/daemon 0.0.227 → 0.0.229
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/agent-admin-handlers.d.ts +56 -0
- package/dist/agent-admin-handlers.d.ts.map +1 -0
- package/dist/agent-admin-handlers.js +73 -0
- package/dist/agent-admin-handlers.js.map +1 -0
- package/dist/agent-handlers.d.ts +72 -0
- package/dist/agent-handlers.d.ts.map +1 -0
- package/dist/agent-handlers.js +604 -0
- package/dist/agent-handlers.js.map +1 -0
- package/dist/agent-id-migration.d.ts +70 -0
- package/dist/agent-id-migration.d.ts.map +1 -0
- package/dist/agent-id-migration.js +468 -0
- package/dist/agent-id-migration.js.map +1 -0
- package/dist/agent-loader.d.ts +37 -0
- package/dist/agent-loader.d.ts.map +1 -0
- package/dist/agent-loader.js +37 -0
- package/dist/agent-loader.js.map +1 -0
- package/dist/agent-selection-root.d.ts +29 -0
- package/dist/agent-selection-root.d.ts.map +1 -0
- package/dist/agent-selection-root.js +126 -0
- package/dist/agent-selection-root.js.map +1 -0
- package/dist/agent-selection.d.ts +73 -0
- package/dist/agent-selection.d.ts.map +1 -0
- package/dist/agent-selection.js +80 -0
- package/dist/agent-selection.js.map +1 -0
- package/dist/agent-settings-keys.d.ts +52 -0
- package/dist/agent-settings-keys.d.ts.map +1 -0
- package/dist/agent-settings-keys.js +114 -0
- package/dist/agent-settings-keys.js.map +1 -0
- package/dist/agent-state.d.ts +67 -0
- package/dist/agent-state.d.ts.map +1 -0
- package/dist/agent-state.js +66 -0
- package/dist/agent-state.js.map +1 -0
- package/dist/assignment-verify.d.ts +90 -0
- package/dist/assignment-verify.d.ts.map +1 -0
- package/dist/assignment-verify.js +301 -0
- package/dist/assignment-verify.js.map +1 -0
- package/dist/attendance-wiring.d.ts +23 -0
- package/dist/attendance-wiring.d.ts.map +1 -0
- package/dist/attendance-wiring.js +248 -0
- package/dist/attendance-wiring.js.map +1 -0
- package/dist/attestation-body.d.ts +47 -0
- package/dist/attestation-body.d.ts.map +1 -0
- package/dist/attestation-body.js +71 -0
- package/dist/attestation-body.js.map +1 -0
- package/dist/authorship-verification.d.ts +91 -0
- package/dist/authorship-verification.d.ts.map +1 -0
- package/dist/authorship-verification.js +532 -0
- package/dist/authorship-verification.js.map +1 -0
- package/dist/away-detection.d.ts +139 -0
- package/dist/away-detection.d.ts.map +1 -0
- package/dist/away-detection.js +186 -0
- package/dist/away-detection.js.map +1 -0
- package/dist/away-inbox-oneshot.d.ts +40 -0
- package/dist/away-inbox-oneshot.d.ts.map +1 -0
- package/dist/away-inbox-oneshot.js +311 -0
- package/dist/away-inbox-oneshot.js.map +1 -0
- package/dist/backup-restore-handlers.d.ts +10 -0
- package/dist/backup-restore-handlers.d.ts.map +1 -0
- package/dist/backup-restore-handlers.js +82 -0
- package/dist/backup-restore-handlers.js.map +1 -0
- package/dist/backup-restore.d.ts +102 -0
- package/dist/backup-restore.d.ts.map +1 -0
- package/dist/backup-restore.js +341 -0
- package/dist/backup-restore.js.map +1 -0
- package/dist/bin/cello-daemon.d.ts +13 -0
- package/dist/bin/cello-daemon.d.ts.map +1 -0
- package/dist/bin/cello-daemon.js.map +1 -0
- package/dist/boot-agents.d.ts +64 -0
- package/dist/boot-agents.d.ts.map +1 -0
- package/dist/boot-agents.js +241 -0
- package/dist/boot-agents.js.map +1 -0
- package/dist/boot-connection-state.d.ts +38 -0
- package/dist/boot-connection-state.d.ts.map +1 -0
- package/dist/boot-connection-state.js +95 -0
- package/dist/boot-connection-state.js.map +1 -0
- package/dist/boot-core.d.ts +36 -0
- package/dist/boot-core.d.ts.map +1 -0
- package/dist/boot-core.js +293 -0
- package/dist/boot-core.js.map +1 -0
- package/dist/boot-parked-content.d.ts +34 -0
- package/dist/boot-parked-content.d.ts.map +1 -0
- package/dist/boot-parked-content.js +528 -0
- package/dist/boot-parked-content.js.map +1 -0
- package/dist/boot-sweeps.d.ts +22 -0
- package/dist/boot-sweeps.d.ts.map +1 -0
- package/dist/boot-sweeps.js +51 -0
- package/dist/boot-sweeps.js.map +1 -0
- package/dist/bundled-consortium-manifest.d.ts +47 -0
- package/dist/bundled-consortium-manifest.d.ts.map +1 -0
- package/dist/bundled-consortium-manifest.js +116 -0
- package/dist/bundled-consortium-manifest.js.map +1 -0
- package/dist/cbor-blob-migration.d.ts +8 -0
- package/dist/cbor-blob-migration.d.ts.map +1 -0
- package/dist/cbor-blob-migration.js +116 -0
- package/dist/cbor-blob-migration.js.map +1 -0
- package/dist/challenge-verifier.d.ts +12 -0
- package/dist/challenge-verifier.d.ts.map +1 -0
- package/dist/challenge-verifier.js +11 -0
- package/dist/challenge-verifier.js.map +1 -0
- package/dist/channel-log-store.d.ts +80 -0
- package/dist/channel-log-store.d.ts.map +1 -0
- package/dist/channel-log-store.js +290 -0
- package/dist/channel-log-store.js.map +1 -0
- package/dist/close-commitment.d.ts +67 -0
- package/dist/close-commitment.d.ts.map +1 -0
- package/dist/close-commitment.js +78 -0
- package/dist/close-commitment.js.map +1 -0
- package/dist/close-session-handler.d.ts +94 -0
- package/dist/close-session-handler.d.ts.map +1 -0
- package/dist/close-session-handler.js +1418 -0
- package/dist/close-session-handler.js.map +1 -0
- package/dist/co-attendance.d.ts +29 -0
- package/dist/co-attendance.d.ts.map +1 -0
- package/dist/co-attendance.js +32 -0
- package/dist/co-attendance.js.map +1 -0
- package/dist/column-birth.d.ts +40 -0
- package/dist/column-birth.d.ts.map +1 -0
- package/dist/column-birth.js +61 -0
- package/dist/column-birth.js.map +1 -0
- package/dist/connect-or-start.d.ts +25 -0
- package/dist/connect-or-start.d.ts.map +1 -0
- package/dist/connect-or-start.js +175 -0
- package/dist/connect-or-start.js.map +1 -0
- package/dist/connection-agents.d.ts +16 -0
- package/dist/connection-agents.d.ts.map +1 -0
- package/dist/connection-agents.js +68 -0
- package/dist/connection-agents.js.map +1 -0
- package/dist/consent-migration.d.ts +49 -0
- package/dist/consent-migration.d.ts.map +1 -0
- package/dist/consent-migration.js +128 -0
- package/dist/consent-migration.js.map +1 -0
- package/dist/consortium-bootstrap.d.ts +138 -0
- package/dist/consortium-bootstrap.d.ts.map +1 -0
- package/dist/consortium-bootstrap.js +339 -0
- package/dist/consortium-bootstrap.js.map +1 -0
- package/dist/consortium-fingerprint.d.ts +115 -0
- package/dist/consortium-fingerprint.d.ts.map +1 -0
- package/dist/consortium-fingerprint.js +175 -0
- package/dist/consortium-fingerprint.js.map +1 -0
- package/dist/contact-handlers.d.ts +59 -0
- package/dist/contact-handlers.d.ts.map +1 -0
- package/dist/contact-handlers.js +343 -0
- package/dist/contact-handlers.js.map +1 -0
- package/dist/contact-pubkey-case.d.ts +65 -0
- package/dist/contact-pubkey-case.d.ts.map +1 -0
- package/dist/contact-pubkey-case.js +136 -0
- package/dist/contact-pubkey-case.js.map +1 -0
- package/dist/contacts-tier-migration.d.ts +90 -0
- package/dist/contacts-tier-migration.d.ts.map +1 -0
- package/dist/contacts-tier-migration.js +150 -0
- package/dist/contacts-tier-migration.js.map +1 -0
- package/dist/content-encryption-status.d.ts +111 -0
- package/dist/content-encryption-status.d.ts.map +1 -0
- package/dist/content-encryption-status.js +158 -0
- package/dist/content-encryption-status.js.map +1 -0
- package/dist/content-park-client.d.ts +90 -0
- package/dist/content-park-client.d.ts.map +1 -0
- package/dist/content-park-client.js +362 -0
- package/dist/content-park-client.js.map +1 -0
- package/dist/content-park.d.ts +52 -0
- package/dist/content-park.d.ts.map +1 -0
- package/dist/content-park.js +1309 -0
- package/dist/content-park.js.map +1 -0
- package/dist/cross-node-negotiation.d.ts +44 -0
- package/dist/cross-node-negotiation.d.ts.map +1 -0
- package/dist/cross-node-negotiation.js +34 -0
- package/dist/cross-node-negotiation.js.map +1 -0
- package/dist/daemon-handle.d.ts +57 -0
- package/dist/daemon-handle.d.ts.map +1 -0
- package/dist/daemon-handle.js +2 -0
- package/dist/daemon-handle.js.map +1 -0
- package/dist/daemon-status-report.d.ts +50 -0
- package/dist/daemon-status-report.d.ts.map +1 -0
- package/dist/daemon-status-report.js +81 -0
- package/dist/daemon-status-report.js.map +1 -0
- package/dist/daemon.d.ts +45 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +1177 -0
- package/dist/daemon.js.map +1 -0
- package/dist/db-identity-store.d.ts +159 -0
- package/dist/db-identity-store.d.ts.map +1 -0
- package/dist/db-identity-store.js +502 -0
- package/dist/db-identity-store.js.map +1 -0
- package/dist/delivery-open-registry.d.ts +92 -0
- package/dist/delivery-open-registry.d.ts.map +1 -0
- package/dist/delivery-open-registry.js +121 -0
- package/dist/delivery-open-registry.js.map +1 -0
- package/dist/delivery-session-suspects.d.ts +56 -0
- package/dist/delivery-session-suspects.d.ts.map +1 -0
- package/dist/delivery-session-suspects.js +94 -0
- package/dist/delivery-session-suspects.js.map +1 -0
- package/dist/directory-auth-posture.d.ts +87 -0
- package/dist/directory-auth-posture.d.ts.map +1 -0
- package/dist/directory-auth-posture.js +134 -0
- package/dist/directory-auth-posture.js.map +1 -0
- package/dist/directory-bootstrap.d.ts +310 -0
- package/dist/directory-bootstrap.d.ts.map +1 -0
- package/dist/directory-bootstrap.js +557 -0
- package/dist/directory-bootstrap.js.map +1 -0
- package/dist/directory-connect.d.ts +27 -0
- package/dist/directory-connect.d.ts.map +1 -0
- package/dist/directory-connect.js +106 -0
- package/dist/directory-connect.js.map +1 -0
- package/dist/disconnect-cleanup.d.ts +51 -0
- package/dist/disconnect-cleanup.d.ts.map +1 -0
- package/dist/disconnect-cleanup.js +72 -0
- package/dist/disconnect-cleanup.js.map +1 -0
- package/dist/document-amendment-store.d.ts +120 -0
- package/dist/document-amendment-store.d.ts.map +1 -0
- package/dist/document-amendment-store.js +266 -0
- package/dist/document-amendment-store.js.map +1 -0
- package/dist/document-delivery-transport.d.ts +168 -0
- package/dist/document-delivery-transport.d.ts.map +1 -0
- package/dist/document-delivery-transport.js +206 -0
- package/dist/document-delivery-transport.js.map +1 -0
- package/dist/document-engine.d.ts +134 -0
- package/dist/document-engine.d.ts.map +1 -0
- package/dist/document-engine.js +282 -0
- package/dist/document-engine.js.map +1 -0
- package/dist/document-flag.d.ts +58 -0
- package/dist/document-flag.d.ts.map +1 -0
- package/dist/document-flag.js +70 -0
- package/dist/document-flag.js.map +1 -0
- package/dist/document-frame-router.d.ts +245 -0
- package/dist/document-frame-router.d.ts.map +1 -0
- package/dist/document-frame-router.js +397 -0
- package/dist/document-frame-router.js.map +1 -0
- package/dist/document-gate-wiring.d.ts +61 -0
- package/dist/document-gate-wiring.d.ts.map +1 -0
- package/dist/document-gate-wiring.js +125 -0
- package/dist/document-gate-wiring.js.map +1 -0
- package/dist/document-gate.d.ts +149 -0
- package/dist/document-gate.d.ts.map +1 -0
- package/dist/document-gate.js +509 -0
- package/dist/document-gate.js.map +1 -0
- package/dist/document-handlers.d.ts +47 -0
- package/dist/document-handlers.d.ts.map +1 -0
- package/dist/document-handlers.js +2203 -0
- package/dist/document-handlers.js.map +1 -0
- package/dist/document-handshake.d.ts +176 -0
- package/dist/document-handshake.d.ts.map +1 -0
- package/dist/document-handshake.js +452 -0
- package/dist/document-handshake.js.map +1 -0
- package/dist/document-inbound.d.ts +162 -0
- package/dist/document-inbound.d.ts.map +1 -0
- package/dist/document-inbound.js +530 -0
- package/dist/document-inbound.js.map +1 -0
- package/dist/document-json.d.ts +120 -0
- package/dist/document-json.d.ts.map +1 -0
- package/dist/document-json.js +191 -0
- package/dist/document-json.js.map +1 -0
- package/dist/document-layer.d.ts +215 -0
- package/dist/document-layer.d.ts.map +1 -0
- package/dist/document-layer.js +1025 -0
- package/dist/document-layer.js.map +1 -0
- package/dist/document-lifecycle.d.ts +52 -0
- package/dist/document-lifecycle.d.ts.map +1 -0
- package/dist/document-lifecycle.js +134 -0
- package/dist/document-lifecycle.js.map +1 -0
- package/dist/document-live-docs.d.ts +58 -0
- package/dist/document-live-docs.d.ts.map +1 -0
- package/dist/document-live-docs.js +126 -0
- package/dist/document-live-docs.js.map +1 -0
- package/dist/document-notify.d.ts +228 -0
- package/dist/document-notify.d.ts.map +1 -0
- package/dist/document-notify.js +580 -0
- package/dist/document-notify.js.map +1 -0
- package/dist/document-profile.d.ts +61 -0
- package/dist/document-profile.d.ts.map +1 -0
- package/dist/document-profile.js +112 -0
- package/dist/document-profile.js.map +1 -0
- package/dist/document-publish.d.ts +87 -0
- package/dist/document-publish.d.ts.map +1 -0
- package/dist/document-publish.js +173 -0
- package/dist/document-publish.js.map +1 -0
- package/dist/document-reachability.d.ts +42 -0
- package/dist/document-reachability.d.ts.map +1 -0
- package/dist/document-reachability.js +80 -0
- package/dist/document-reachability.js.map +1 -0
- package/dist/document-reconcile-engine.d.ts +66 -0
- package/dist/document-reconcile-engine.d.ts.map +1 -0
- package/dist/document-reconcile-engine.js +225 -0
- package/dist/document-reconcile-engine.js.map +1 -0
- package/dist/document-reconcile-scheduler.d.ts +163 -0
- package/dist/document-reconcile-scheduler.d.ts.map +1 -0
- package/dist/document-reconcile-scheduler.js +303 -0
- package/dist/document-reconcile-scheduler.js.map +1 -0
- package/dist/document-rejection.d.ts +251 -0
- package/dist/document-rejection.d.ts.map +1 -0
- package/dist/document-rejection.js +435 -0
- package/dist/document-rejection.js.map +1 -0
- package/dist/document-screen.d.ts +114 -0
- package/dist/document-screen.d.ts.map +1 -0
- package/dist/document-screen.js +223 -0
- package/dist/document-screen.js.map +1 -0
- package/dist/document-store.d.ts +372 -0
- package/dist/document-store.d.ts.map +1 -0
- package/dist/document-store.js +931 -0
- package/dist/document-store.js.map +1 -0
- package/dist/document-surface.d.ts +32 -0
- package/dist/document-surface.d.ts.map +1 -0
- package/dist/document-surface.js +151 -0
- package/dist/document-surface.js.map +1 -0
- package/dist/document-types.d.ts +94 -0
- package/dist/document-types.d.ts.map +1 -0
- package/dist/document-types.js +90 -0
- package/dist/document-types.js.map +1 -0
- package/dist/document-watch.d.ts +69 -0
- package/dist/document-watch.d.ts.map +1 -0
- package/dist/document-watch.js +108 -0
- package/dist/document-watch.js.map +1 -0
- package/dist/document-wiring.d.ts +53 -0
- package/dist/document-wiring.d.ts.map +1 -0
- package/dist/document-wiring.js +323 -0
- package/dist/document-wiring.js.map +1 -0
- package/dist/document-write-guard.d.ts +66 -0
- package/dist/document-write-guard.d.ts.map +1 -0
- package/dist/document-write-guard.js +98 -0
- package/dist/document-write-guard.js.map +1 -0
- package/dist/document-write-path.d.ts +94 -0
- package/dist/document-write-path.d.ts.map +1 -0
- package/dist/document-write-path.js +530 -0
- package/dist/document-write-path.js.map +1 -0
- package/dist/error-message.d.ts +7 -0
- package/dist/error-message.d.ts.map +1 -0
- package/dist/error-message.js +19 -0
- package/dist/error-message.js.map +1 -0
- package/dist/file-manifest-provider.d.ts +37 -0
- package/dist/file-manifest-provider.d.ts.map +1 -0
- package/dist/file-manifest-provider.js +105 -0
- package/dist/file-manifest-provider.js.map +1 -0
- package/dist/frame-values.d.ts +3 -0
- package/dist/frame-values.d.ts.map +1 -0
- package/dist/frame-values.js +84 -0
- package/dist/frame-values.js.map +1 -0
- package/dist/frontier-mismatch.d.ts +73 -0
- package/dist/frontier-mismatch.d.ts.map +1 -0
- package/dist/frontier-mismatch.js +89 -0
- package/dist/frontier-mismatch.js.map +1 -0
- package/dist/gateway-config-handlers.d.ts +26 -0
- package/dist/gateway-config-handlers.d.ts.map +1 -0
- package/dist/gateway-config-handlers.js +454 -0
- package/dist/gateway-config-handlers.js.map +1 -0
- package/dist/held-content.d.ts +145 -0
- package/dist/held-content.d.ts.map +1 -0
- package/dist/held-content.js +389 -0
- package/dist/held-content.js.map +1 -0
- package/dist/http-manifest-poll.d.ts +67 -0
- package/dist/http-manifest-poll.d.ts.map +1 -0
- package/dist/http-manifest-poll.js +150 -0
- package/dist/http-manifest-poll.js.map +1 -0
- package/dist/identity-migration.d.ts +40 -0
- package/dist/identity-migration.d.ts.map +1 -0
- package/dist/identity-migration.js +461 -0
- package/dist/identity-migration.js.map +1 -0
- package/dist/inbound-refusals.d.ts +283 -0
- package/dist/inbound-refusals.d.ts.map +1 -0
- package/dist/inbound-refusals.js +919 -0
- package/dist/inbound-refusals.js.map +1 -0
- package/dist/inbound-seal-request.d.ts +32 -0
- package/dist/inbound-seal-request.d.ts.map +1 -0
- package/dist/inbound-seal-request.js +228 -0
- package/dist/inbound-seal-request.js.map +1 -0
- package/dist/inbound-sessions.d.ts +291 -0
- package/dist/inbound-sessions.d.ts.map +1 -0
- package/dist/inbound-sessions.js +1609 -0
- package/dist/inbound-sessions.js.map +1 -0
- package/dist/inclusion-proof-handlers.d.ts +43 -0
- package/dist/inclusion-proof-handlers.d.ts.map +1 -0
- package/dist/inclusion-proof-handlers.js +565 -0
- package/dist/inclusion-proof-handlers.js.map +1 -0
- package/dist/inclusion-proof.d.ts +151 -0
- package/dist/inclusion-proof.d.ts.map +1 -0
- package/dist/inclusion-proof.js +228 -0
- package/dist/inclusion-proof.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/initiate-session-handler.d.ts +55 -0
- package/dist/initiate-session-handler.d.ts.map +1 -0
- package/dist/initiate-session-handler.js +310 -0
- package/dist/initiate-session-handler.js.map +1 -0
- package/dist/ipc-client.d.ts +31 -0
- package/dist/ipc-client.d.ts.map +1 -0
- package/dist/ipc-client.js +113 -0
- package/dist/ipc-client.js.map +1 -0
- package/dist/ipc-server.d.ts +63 -0
- package/dist/ipc-server.d.ts.map +1 -0
- package/dist/ipc-server.js +429 -0
- package/dist/ipc-server.js.map +1 -0
- package/dist/ipc-surface.d.ts +44 -0
- package/dist/ipc-surface.d.ts.map +1 -0
- package/dist/ipc-surface.js +107 -0
- package/dist/ipc-surface.js.map +1 -0
- package/dist/line-lcs.d.ts +51 -0
- package/dist/line-lcs.d.ts.map +1 -0
- package/dist/line-lcs.js +71 -0
- package/dist/line-lcs.js.map +1 -0
- package/dist/lock-file.d.ts +39 -0
- package/dist/lock-file.d.ts.map +1 -0
- package/dist/lock-file.js +120 -0
- package/dist/lock-file.js.map +1 -0
- package/dist/log-collapse.d.ts +66 -0
- package/dist/log-collapse.d.ts.map +1 -0
- package/dist/log-collapse.js +244 -0
- package/dist/log-collapse.js.map +1 -0
- package/dist/log-rotate.d.ts +67 -0
- package/dist/log-rotate.d.ts.map +1 -0
- package/dist/log-rotate.js +134 -0
- package/dist/log-rotate.js.map +1 -0
- package/dist/manifest-deps.d.ts +25 -0
- package/dist/manifest-deps.d.ts.map +1 -0
- package/dist/manifest-deps.js +151 -0
- package/dist/manifest-deps.js.map +1 -0
- package/dist/manifest-poll-scheduler.d.ts +31 -0
- package/dist/manifest-poll-scheduler.d.ts.map +1 -0
- package/dist/manifest-poll-scheduler.js +59 -0
- package/dist/manifest-poll-scheduler.js.map +1 -0
- package/dist/manifest-validity.d.ts +153 -0
- package/dist/manifest-validity.d.ts.map +1 -0
- package/dist/manifest-validity.js +268 -0
- package/dist/manifest-validity.js.map +1 -0
- package/dist/manifest-version-store-db.d.ts +24 -0
- package/dist/manifest-version-store-db.d.ts.map +1 -0
- package/dist/manifest-version-store-db.js +58 -0
- package/dist/manifest-version-store-db.js.map +1 -0
- package/dist/manifest-version-store.d.ts +16 -0
- package/dist/manifest-version-store.d.ts.map +1 -0
- package/dist/manifest-version-store.js +15 -0
- package/dist/manifest-version-store.js.map +1 -0
- package/dist/network-directory-node.d.ts +136 -0
- package/dist/network-directory-node.d.ts.map +1 -0
- package/dist/network-directory-node.js +810 -0
- package/dist/network-directory-node.js.map +1 -0
- package/dist/nonce-dedup.d.ts +68 -0
- package/dist/nonce-dedup.d.ts.map +1 -0
- package/dist/nonce-dedup.js +205 -0
- package/dist/nonce-dedup.js.map +1 -0
- package/dist/notification-dispatcher.d.ts +92 -0
- package/dist/notification-dispatcher.d.ts.map +1 -0
- package/dist/notification-dispatcher.js +210 -0
- package/dist/notification-dispatcher.js.map +1 -0
- package/dist/notification-handlers.d.ts +53 -0
- package/dist/notification-handlers.d.ts.map +1 -0
- package/dist/notification-handlers.js +461 -0
- package/dist/notification-handlers.js.map +1 -0
- package/dist/onboarding-guidance.d.ts +79 -0
- package/dist/onboarding-guidance.d.ts.map +1 -0
- package/dist/onboarding-guidance.js +95 -0
- package/dist/onboarding-guidance.js.map +1 -0
- package/dist/operator-guidance.d.ts +25 -0
- package/dist/operator-guidance.d.ts.map +1 -0
- package/dist/operator-guidance.js +50 -0
- package/dist/operator-guidance.js.map +1 -0
- package/dist/orphan-triage.d.ts +130 -0
- package/dist/orphan-triage.d.ts.map +1 -0
- package/dist/orphan-triage.js +207 -0
- package/dist/orphan-triage.js.map +1 -0
- package/dist/outbound-sessions.d.ts +126 -0
- package/dist/outbound-sessions.d.ts.map +1 -0
- package/dist/outbound-sessions.js +1052 -0
- package/dist/outbound-sessions.js.map +1 -0
- package/dist/park-envelope.d.ts +329 -0
- package/dist/park-envelope.d.ts.map +1 -0
- package/dist/park-envelope.js +509 -0
- package/dist/park-envelope.js.map +1 -0
- package/dist/park-recovery.d.ts +273 -0
- package/dist/park-recovery.d.ts.map +1 -0
- package/dist/park-recovery.js +717 -0
- package/dist/park-recovery.js.map +1 -0
- package/dist/park-refusals.d.ts +147 -0
- package/dist/park-refusals.d.ts.map +1 -0
- package/dist/park-refusals.js +331 -0
- package/dist/park-refusals.js.map +1 -0
- package/dist/quarantine-framing.d.ts +92 -0
- package/dist/quarantine-framing.d.ts.map +1 -0
- package/dist/quarantine-framing.js +111 -0
- package/dist/quarantine-framing.js.map +1 -0
- package/dist/reconnect-drain.d.ts +22 -0
- package/dist/reconnect-drain.d.ts.map +1 -0
- package/dist/reconnect-drain.js +65 -0
- package/dist/reconnect-drain.js.map +1 -0
- package/dist/recovered-position.d.ts +14 -0
- package/dist/recovered-position.d.ts.map +1 -0
- package/dist/recovered-position.js +59 -0
- package/dist/recovered-position.js.map +1 -0
- package/dist/refusal-notices.d.ts +196 -0
- package/dist/refusal-notices.d.ts.map +1 -0
- package/dist/refusal-notices.js +516 -0
- package/dist/refusal-notices.js.map +1 -0
- package/dist/refusal-reasons.d.ts +245 -0
- package/dist/refusal-reasons.d.ts.map +1 -0
- package/dist/refusal-reasons.js +363 -0
- package/dist/refusal-reasons.js.map +1 -0
- package/dist/register-handler.d.ts +36 -0
- package/dist/register-handler.d.ts.map +1 -0
- package/dist/register-handler.js +285 -0
- package/dist/register-handler.js.map +1 -0
- package/dist/registration-context.d.ts +72 -0
- package/dist/registration-context.d.ts.map +1 -0
- package/dist/registration-context.js +126 -0
- package/dist/registration-context.js.map +1 -0
- package/dist/registration-manager.d.ts +94 -0
- package/dist/registration-manager.d.ts.map +1 -0
- package/dist/registration-manager.js +585 -0
- package/dist/registration-manager.js.map +1 -0
- package/dist/registration-persistence.d.ts +183 -0
- package/dist/registration-persistence.d.ts.map +1 -0
- package/dist/registration-persistence.js +263 -0
- package/dist/registration-persistence.js.map +1 -0
- package/dist/registry-poll.d.ts +52 -0
- package/dist/registry-poll.d.ts.map +1 -0
- package/dist/registry-poll.js +140 -0
- package/dist/registry-poll.js.map +1 -0
- package/dist/registry-version-store-db.d.ts +22 -0
- package/dist/registry-version-store-db.d.ts.map +1 -0
- package/dist/registry-version-store-db.js +50 -0
- package/dist/registry-version-store-db.js.map +1 -0
- package/dist/relay-endpoints.d.ts +18 -0
- package/dist/relay-endpoints.d.ts.map +1 -0
- package/dist/relay-endpoints.js +9 -0
- package/dist/relay-endpoints.js.map +1 -0
- package/dist/relay-only.d.ts +140 -0
- package/dist/relay-only.d.ts.map +1 -0
- package/dist/relay-only.js +193 -0
- package/dist/relay-only.js.map +1 -0
- package/dist/relay-receipt-store.d.ts +155 -0
- package/dist/relay-receipt-store.d.ts.map +1 -0
- package/dist/relay-receipt-store.js +284 -0
- package/dist/relay-receipt-store.js.map +1 -0
- package/dist/relay-reconnect.d.ts +32 -0
- package/dist/relay-reconnect.d.ts.map +1 -0
- package/dist/relay-reconnect.js +29 -0
- package/dist/relay-reconnect.js.map +1 -0
- package/dist/reply-lag.d.ts +11 -0
- package/dist/reply-lag.d.ts.map +1 -0
- package/dist/reply-lag.js +46 -0
- package/dist/reply-lag.js.map +1 -0
- package/dist/resolve-named-agent.d.ts +49 -0
- package/dist/resolve-named-agent.d.ts.map +1 -0
- package/dist/resolve-named-agent.js +77 -0
- package/dist/resolve-named-agent.js.map +1 -0
- package/dist/restart-seal-resolver.d.ts +110 -0
- package/dist/restart-seal-resolver.d.ts.map +1 -0
- package/dist/restart-seal-resolver.js +353 -0
- package/dist/restart-seal-resolver.js.map +1 -0
- package/dist/resume-last-seen.d.ts +15 -0
- package/dist/resume-last-seen.d.ts.map +1 -0
- package/dist/resume-last-seen.js +44 -0
- package/dist/resume-last-seen.js.map +1 -0
- package/dist/retry-queue.d.ts +203 -0
- package/dist/retry-queue.d.ts.map +1 -0
- package/dist/retry-queue.js +701 -0
- package/dist/retry-queue.js.map +1 -0
- package/dist/roster-freshness.d.ts +160 -0
- package/dist/roster-freshness.d.ts.map +1 -0
- package/dist/roster-freshness.js +250 -0
- package/dist/roster-freshness.js.map +1 -0
- package/dist/screening-status.d.ts +15 -0
- package/dist/screening-status.d.ts.map +1 -0
- package/dist/screening-status.js +65 -0
- package/dist/screening-status.js.map +1 -0
- package/dist/seal-carried-close.d.ts +37 -0
- package/dist/seal-carried-close.d.ts.map +1 -0
- package/dist/seal-carried-close.js +179 -0
- package/dist/seal-carried-close.js.map +1 -0
- package/dist/seal-certificate-pull.d.ts +79 -0
- package/dist/seal-certificate-pull.d.ts.map +1 -0
- package/dist/seal-certificate-pull.js +186 -0
- package/dist/seal-certificate-pull.js.map +1 -0
- package/dist/seal-certified-root-check.d.ts +37 -0
- package/dist/seal-certified-root-check.d.ts.map +1 -0
- package/dist/seal-certified-root-check.js +127 -0
- package/dist/seal-certified-root-check.js.map +1 -0
- package/dist/seal-coordinator.d.ts +118 -0
- package/dist/seal-coordinator.d.ts.map +1 -0
- package/dist/seal-coordinator.js +927 -0
- package/dist/seal-coordinator.js.map +1 -0
- package/dist/seal-escalation.d.ts +80 -0
- package/dist/seal-escalation.d.ts.map +1 -0
- package/dist/seal-escalation.js +283 -0
- package/dist/seal-escalation.js.map +1 -0
- package/dist/seal-evidence-root-check.d.ts +70 -0
- package/dist/seal-evidence-root-check.d.ts.map +1 -0
- package/dist/seal-evidence-root-check.js +199 -0
- package/dist/seal-evidence-root-check.js.map +1 -0
- package/dist/seal-failure-store.d.ts +139 -0
- package/dist/seal-failure-store.d.ts.map +1 -0
- package/dist/seal-failure-store.js +207 -0
- package/dist/seal-failure-store.js.map +1 -0
- package/dist/seal-flows.d.ts +107 -0
- package/dist/seal-flows.d.ts.map +1 -0
- package/dist/seal-flows.js +638 -0
- package/dist/seal-flows.js.map +1 -0
- package/dist/seal-frontier-verify.d.ts +103 -0
- package/dist/seal-frontier-verify.d.ts.map +1 -0
- package/dist/seal-frontier-verify.js +143 -0
- package/dist/seal-frontier-verify.js.map +1 -0
- package/dist/seal-leaf.d.ts +58 -0
- package/dist/seal-leaf.d.ts.map +1 -0
- package/dist/seal-leaf.js +112 -0
- package/dist/seal-leaf.js.map +1 -0
- package/dist/seal-legibility-tbs.d.ts +25 -0
- package/dist/seal-legibility-tbs.d.ts.map +1 -0
- package/dist/seal-legibility-tbs.js +77 -0
- package/dist/seal-legibility-tbs.js.map +1 -0
- package/dist/seal-local-terminus.d.ts +41 -0
- package/dist/seal-local-terminus.d.ts.map +1 -0
- package/dist/seal-local-terminus.js +170 -0
- package/dist/seal-local-terminus.js.map +1 -0
- package/dist/seal-receipt-upgrade.d.ts +30 -0
- package/dist/seal-receipt-upgrade.d.ts.map +1 -0
- package/dist/seal-receipt-upgrade.js +49 -0
- package/dist/seal-receipt-upgrade.js.map +1 -0
- package/dist/seal-relay-silence.d.ts +51 -0
- package/dist/seal-relay-silence.d.ts.map +1 -0
- package/dist/seal-relay-silence.js +76 -0
- package/dist/seal-relay-silence.js.map +1 -0
- package/dist/seal-settle.d.ts +38 -0
- package/dist/seal-settle.d.ts.map +1 -0
- package/dist/seal-settle.js +33 -0
- package/dist/seal-settle.js.map +1 -0
- package/dist/seal-upgrade.d.ts +107 -0
- package/dist/seal-upgrade.d.ts.map +1 -0
- package/dist/seal-upgrade.js +200 -0
- package/dist/seal-upgrade.js.map +1 -0
- package/dist/sealed-conversation.d.ts +36 -0
- package/dist/sealed-conversation.d.ts.map +1 -0
- package/dist/sealed-conversation.js +171 -0
- package/dist/sealed-conversation.js.map +1 -0
- package/dist/sealed-leaf-set.d.ts +92 -0
- package/dist/sealed-leaf-set.d.ts.map +1 -0
- package/dist/sealed-leaf-set.js +122 -0
- package/dist/sealed-leaf-set.js.map +1 -0
- package/dist/send-claims.d.ts +56 -0
- package/dist/send-claims.d.ts.map +1 -0
- package/dist/send-claims.js +50 -0
- package/dist/send-claims.js.map +1 -0
- package/dist/session-assignment-parser.d.ts +104 -0
- package/dist/session-assignment-parser.d.ts.map +1 -0
- package/dist/session-assignment-parser.js +345 -0
- package/dist/session-assignment-parser.js.map +1 -0
- package/dist/session-category.d.ts +19 -0
- package/dist/session-category.d.ts.map +1 -0
- package/dist/session-category.js +14 -0
- package/dist/session-category.js.map +1 -0
- package/dist/session-ceremony.d.ts +297 -0
- package/dist/session-ceremony.d.ts.map +1 -0
- package/dist/session-ceremony.js +964 -0
- package/dist/session-ceremony.js.map +1 -0
- package/dist/session-closed.d.ts +79 -0
- package/dist/session-closed.d.ts.map +1 -0
- package/dist/session-closed.js +189 -0
- package/dist/session-closed.js.map +1 -0
- package/dist/session-connection-gater.d.ts +148 -0
- package/dist/session-connection-gater.d.ts.map +1 -0
- package/dist/session-connection-gater.js +332 -0
- package/dist/session-connection-gater.js.map +1 -0
- package/dist/session-content-context.d.ts +162 -0
- package/dist/session-content-context.d.ts.map +1 -0
- package/dist/session-content-context.js +2 -0
- package/dist/session-content-context.js.map +1 -0
- package/dist/session-content-handlers.d.ts +82 -0
- package/dist/session-content-handlers.d.ts.map +1 -0
- package/dist/session-content-handlers.js +1382 -0
- package/dist/session-content-handlers.js.map +1 -0
- package/dist/session-content-ingest.d.ts +206 -0
- package/dist/session-content-ingest.d.ts.map +1 -0
- package/dist/session-content-ingest.js +2167 -0
- package/dist/session-content-ingest.js.map +1 -0
- package/dist/session-content-send.d.ts +191 -0
- package/dist/session-content-send.d.ts.map +1 -0
- package/dist/session-content-send.js +1360 -0
- package/dist/session-content-send.js.map +1 -0
- package/dist/session-delivery-acks.d.ts +169 -0
- package/dist/session-delivery-acks.d.ts.map +1 -0
- package/dist/session-delivery-acks.js +569 -0
- package/dist/session-delivery-acks.js.map +1 -0
- package/dist/session-ephemerals.d.ts +279 -0
- package/dist/session-ephemerals.d.ts.map +1 -0
- package/dist/session-ephemerals.js +591 -0
- package/dist/session-ephemerals.js.map +1 -0
- package/dist/session-leaf-records.d.ts +159 -0
- package/dist/session-leaf-records.d.ts.map +1 -0
- package/dist/session-leaf-records.js +408 -0
- package/dist/session-leaf-records.js.map +1 -0
- package/dist/session-lifecycle.d.ts +303 -0
- package/dist/session-lifecycle.d.ts.map +1 -0
- package/dist/session-lifecycle.js +1679 -0
- package/dist/session-lifecycle.js.map +1 -0
- package/dist/session-liveness.d.ts +135 -0
- package/dist/session-liveness.d.ts.map +1 -0
- package/dist/session-liveness.js +347 -0
- package/dist/session-liveness.js.map +1 -0
- package/dist/session-name.d.ts +35 -0
- package/dist/session-name.d.ts.map +1 -0
- package/dist/session-name.js +60 -0
- package/dist/session-name.js.map +1 -0
- package/dist/session-node-factory.d.ts +18 -0
- package/dist/session-node-factory.d.ts.map +1 -0
- package/dist/session-node-factory.js +182 -0
- package/dist/session-node-factory.js.map +1 -0
- package/dist/session-node-manager.d.ts +877 -0
- package/dist/session-node-manager.d.ts.map +1 -0
- package/dist/session-node-manager.js +2998 -0
- package/dist/session-node-manager.js.map +1 -0
- package/dist/session-node-types.d.ts +1057 -0
- package/dist/session-node-types.d.ts.map +1 -0
- package/dist/session-node-types.js +657 -0
- package/dist/session-node-types.js.map +1 -0
- package/dist/session-notify.d.ts +46 -0
- package/dist/session-notify.d.ts.map +1 -0
- package/dist/session-notify.js +116 -0
- package/dist/session-notify.js.map +1 -0
- package/dist/session-own-chain-store.d.ts +65 -0
- package/dist/session-own-chain-store.d.ts.map +1 -0
- package/dist/session-own-chain-store.js +75 -0
- package/dist/session-own-chain-store.js.map +1 -0
- package/dist/session-queries.d.ts +476 -0
- package/dist/session-queries.d.ts.map +1 -0
- package/dist/session-queries.js +1007 -0
- package/dist/session-queries.js.map +1 -0
- package/dist/session-read-handlers.d.ts +87 -0
- package/dist/session-read-handlers.d.ts.map +1 -0
- package/dist/session-read-handlers.js +689 -0
- package/dist/session-read-handlers.js.map +1 -0
- package/dist/session-records.d.ts +341 -0
- package/dist/session-records.d.ts.map +1 -0
- package/dist/session-records.js +858 -0
- package/dist/session-records.js.map +1 -0
- package/dist/session-relay-client.d.ts +659 -0
- package/dist/session-relay-client.d.ts.map +1 -0
- package/dist/session-relay-client.js +2876 -0
- package/dist/session-relay-client.js.map +1 -0
- package/dist/session-relay.d.ts +397 -0
- package/dist/session-relay.d.ts.map +1 -0
- package/dist/session-relay.js +1636 -0
- package/dist/session-relay.js.map +1 -0
- package/dist/session-salt-agreement.d.ts +331 -0
- package/dist/session-salt-agreement.d.ts.map +1 -0
- package/dist/session-salt-agreement.js +472 -0
- package/dist/session-salt-agreement.js.map +1 -0
- package/dist/session-salts.d.ts +432 -0
- package/dist/session-salts.d.ts.map +1 -0
- package/dist/session-salts.js +1540 -0
- package/dist/session-salts.js.map +1 -0
- package/dist/session-schema.d.ts +30 -0
- package/dist/session-schema.d.ts.map +1 -0
- package/dist/session-schema.js +877 -0
- package/dist/session-schema.js.map +1 -0
- package/dist/session-seal-leaf-store.d.ts +70 -0
- package/dist/session-seal-leaf-store.d.ts.map +1 -0
- package/dist/session-seal-leaf-store.js +105 -0
- package/dist/session-seal-leaf-store.js.map +1 -0
- package/dist/session-seal.d.ts +334 -0
- package/dist/session-seal.d.ts.map +1 -0
- package/dist/session-seal.js +1017 -0
- package/dist/session-seal.js.map +1 -0
- package/dist/session-terminal-refusal.d.ts +65 -0
- package/dist/session-terminal-refusal.d.ts.map +1 -0
- package/dist/session-terminal-refusal.js +87 -0
- package/dist/session-terminal-refusal.js.map +1 -0
- package/dist/session-tree.d.ts +110 -0
- package/dist/session-tree.d.ts.map +1 -0
- package/dist/session-tree.js +144 -0
- package/dist/session-tree.js.map +1 -0
- package/dist/session-views.d.ts +47 -0
- package/dist/session-views.d.ts.map +1 -0
- package/dist/session-views.js +278 -0
- package/dist/session-views.js.map +1 -0
- package/dist/signal-handlers.d.ts +63 -0
- package/dist/signal-handlers.d.ts.map +1 -0
- package/dist/signal-handlers.js +980 -0
- package/dist/signal-handlers.js.map +1 -0
- package/dist/signal-requirement-policy.d.ts +51 -0
- package/dist/signal-requirement-policy.d.ts.map +1 -0
- package/dist/signal-requirement-policy.js +89 -0
- package/dist/signal-requirement-policy.js.map +1 -0
- package/dist/signal-revocability.d.ts +49 -0
- package/dist/signal-revocability.d.ts.map +1 -0
- package/dist/signal-revocability.js +93 -0
- package/dist/signal-revocability.js.map +1 -0
- package/dist/signal-submission.d.ts +181 -0
- package/dist/signal-submission.d.ts.map +1 -0
- package/dist/signal-submission.js +368 -0
- package/dist/signal-submission.js.map +1 -0
- package/dist/signaling-connect.d.ts +118 -0
- package/dist/signaling-connect.d.ts.map +1 -0
- package/dist/signaling-connect.js +538 -0
- package/dist/signaling-connect.js.map +1 -0
- package/dist/signaling-wiring.d.ts +105 -0
- package/dist/signaling-wiring.d.ts.map +1 -0
- package/dist/signaling-wiring.js +393 -0
- package/dist/signaling-wiring.js.map +1 -0
- package/dist/singleton-lock.d.ts +85 -0
- package/dist/singleton-lock.d.ts.map +1 -0
- package/dist/singleton-lock.js +219 -0
- package/dist/singleton-lock.js.map +1 -0
- package/dist/sqlcipher-db.d.ts +139 -0
- package/dist/sqlcipher-db.d.ts.map +1 -0
- package/dist/sqlcipher-db.js +357 -0
- package/dist/sqlcipher-db.js.map +1 -0
- package/dist/standing-receivers.d.ts +319 -0
- package/dist/standing-receivers.d.ts.map +1 -0
- package/dist/standing-receivers.js +1295 -0
- package/dist/standing-receivers.js.map +1 -0
- package/dist/start-agent.d.ts +64 -0
- package/dist/start-agent.d.ts.map +1 -0
- package/dist/start-agent.js +136 -0
- package/dist/start-agent.js.map +1 -0
- package/dist/status-handler.d.ts +54 -0
- package/dist/status-handler.d.ts.map +1 -0
- package/dist/status-handler.js +61 -0
- package/dist/status-handler.js.map +1 -0
- package/dist/submission-retry.d.ts +208 -0
- package/dist/submission-retry.d.ts.map +1 -0
- package/dist/submission-retry.js +506 -0
- package/dist/submission-retry.js.map +1 -0
- package/dist/telegram-bot-client.d.ts +34 -0
- package/dist/telegram-bot-client.d.ts.map +1 -0
- package/dist/telegram-bot-client.js +36 -0
- package/dist/telegram-bot-client.js.map +1 -0
- package/dist/telegram-doorbell.d.ts +38 -0
- package/dist/telegram-doorbell.d.ts.map +1 -0
- package/dist/telegram-doorbell.js +140 -0
- package/dist/telegram-doorbell.js.map +1 -0
- package/dist/test-handlers.d.ts +62 -0
- package/dist/test-handlers.d.ts.map +1 -0
- package/dist/test-handlers.js +240 -0
- package/dist/test-handlers.js.map +1 -0
- package/dist/testing.d.ts +10 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +10 -0
- package/dist/testing.js.map +1 -0
- package/dist/transport-composition.d.ts +31 -0
- package/dist/transport-composition.d.ts.map +1 -0
- package/dist/transport-composition.js +55 -0
- package/dist/transport-composition.js.map +1 -0
- package/dist/transport-selector.d.ts +202 -0
- package/dist/transport-selector.d.ts.map +1 -0
- package/dist/transport-selector.js +196 -0
- package/dist/transport-selector.js.map +1 -0
- package/dist/trust-signal-pickup-listener.d.ts +43 -0
- package/dist/trust-signal-pickup-listener.d.ts.map +1 -0
- package/dist/trust-signal-pickup-listener.js +48 -0
- package/dist/trust-signal-pickup-listener.js.map +1 -0
- package/dist/trust-signal-store.d.ts +406 -0
- package/dist/trust-signal-store.d.ts.map +1 -0
- package/dist/trust-signal-store.js +939 -0
- package/dist/trust-signal-store.js.map +1 -0
- package/dist/trust-signal-sweep-tick.d.ts +60 -0
- package/dist/trust-signal-sweep-tick.d.ts.map +1 -0
- package/dist/trust-signal-sweep-tick.js +101 -0
- package/dist/trust-signal-sweep-tick.js.map +1 -0
- package/dist/trust-signal-sweep.d.ts +94 -0
- package/dist/trust-signal-sweep.d.ts.map +1 -0
- package/dist/trust-signal-sweep.js +147 -0
- package/dist/trust-signal-sweep.js.map +1 -0
- package/dist/type-registry.d.ts +42 -0
- package/dist/type-registry.d.ts.map +1 -0
- package/dist/type-registry.js +37 -0
- package/dist/type-registry.js.map +1 -0
- package/dist/types.d.ts +746 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/dist/types.js.map +1 -0
- package/dist/unresolved-nodes-report.d.ts +14 -0
- package/dist/unresolved-nodes-report.d.ts.map +1 -0
- package/dist/unresolved-nodes-report.js +96 -0
- package/dist/unresolved-nodes-report.js.map +1 -0
- package/dist/vocabulary.d.ts +150 -0
- package/dist/vocabulary.d.ts.map +1 -0
- package/dist/vocabulary.js +386 -0
- package/dist/vocabulary.js.map +1 -0
- package/dist/who-label.d.ts +28 -0
- package/dist/who-label.d.ts.map +1 -0
- package/dist/who-label.js +31 -0
- package/dist/who-label.js.map +1 -0
- package/dist/who-resolver.d.ts +15 -0
- package/dist/who-resolver.d.ts.map +1 -0
- package/dist/who-resolver.js +47 -0
- package/dist/who-resolver.js.map +1 -0
- package/dist/wire-content-hash.d.ts +93 -0
- package/dist/wire-content-hash.d.ts.map +1 -0
- package/dist/wire-content-hash.js +116 -0
- package/dist/wire-content-hash.js.map +1 -0
- package/dist/withheld-content.d.ts +13 -0
- package/dist/withheld-content.d.ts.map +1 -0
- package/dist/withheld-content.js +46 -0
- package/dist/withheld-content.js.map +1 -0
- package/dist/witness-alerts.d.ts +40 -0
- package/dist/witness-alerts.d.ts.map +1 -0
- package/dist/witness-alerts.js +102 -0
- package/dist/witness-alerts.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,939 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M10 / DOD-STORE-CLIENT-1 — the daemon's two trust-signal tables.
|
|
3
|
+
*
|
|
4
|
+
* TWO tables, never one with a role flag (M10-D4). They answer different questions and obey
|
|
5
|
+
* different scoping rules, and a single table with a `role` column is how one set of rules ends up
|
|
6
|
+
* applied to the other's rows.
|
|
7
|
+
*
|
|
8
|
+
* `wallet_trust_signals` — signals ABOUT this daemon's agents, held so they can be PRESENTED.
|
|
9
|
+
* `contact_trust_signals` — signals OTHER agents PRESENTED TO one of my agents.
|
|
10
|
+
*
|
|
11
|
+
* THE WALLET CARRIES NO AGENT ASSOCIATION (M10-D14). PK = `signal_hash`; one row per signal per
|
|
12
|
+
* daemon, and nothing more. It is the envelope's own HASHED `subject_kind`/`subject` that decides
|
|
13
|
+
* who may present it, evaluated at presentation time — not a local attribution decided at delivery
|
|
14
|
+
* time. That is the whole point: an account-subject signal (phone, email) serves every agent under
|
|
15
|
+
* the account, so **adding an agent to an existing daemon is ZERO signal work** — no assignment
|
|
16
|
+
* sweep, no re-attribution at renewal, no copies to keep in step at expiry. A per-agent column
|
|
17
|
+
* would quietly reintroduce every one of those chores.
|
|
18
|
+
*
|
|
19
|
+
* THE RECEIVED STORE IS PER-AGENT, AND THE DATABASE ENFORCES IT (INV-AGENT-SCOPED). Consent is
|
|
20
|
+
* genuinely per-agent here: a signal Bob showed to my agent `alice` must be invisible to my agent
|
|
21
|
+
* `bob` on the same daemon. `agent_id` is NOT NULL and the row hangs off a contact row by composite
|
|
22
|
+
* FK, so an unscoped row cannot be written at all — as opposed to being merely discouraged by a
|
|
23
|
+
* query convention that every future caller must remember. (This requires `PRAGMA foreign_keys = ON`,
|
|
24
|
+
* set at open in sqlcipher-db.ts — M10-D19. Without it the FK is decorative.) This is where the M8
|
|
25
|
+
* scaffold's `agent_id = null` defect dies.
|
|
26
|
+
*
|
|
27
|
+
* EVIDENCE, NOT AN INPUT (M10-D4 / INV-STATELESS-RECIPIENT). Received rows are re-checkable evidence
|
|
28
|
+
* of what was presented and when we verified it. They are NEVER an input to policy evaluation, which
|
|
29
|
+
* consumes only the currently-presented set, and they are never trusted for freshness (that is
|
|
30
|
+
* re-checked on use). This module therefore exposes no "is this contact trusted?" read — the absence
|
|
31
|
+
* is deliberate and structural. Do not add one.
|
|
32
|
+
*
|
|
33
|
+
* OPAQUE THROUGHOUT (INV-ZERO-BUMP / INV-TYPE-CARRY). `type` is a TEXT column with no CHECK, no
|
|
34
|
+
* enum, and no index predicated on a type value; `payload` is a BLOB that is never parsed and whose
|
|
35
|
+
* fields are never hoisted into columns. A type string this code has never seen stores, reads, and
|
|
36
|
+
* presents exactly like a known one. Adding a signal type must require no change to this file.
|
|
37
|
+
*/
|
|
38
|
+
import { verifyTrustSignalHash } from "@cello-protocol/protocol-types";
|
|
39
|
+
import { migrateWalletAddConsentState, CONSENT_ACCEPTED } from "./consent-migration.js";
|
|
40
|
+
import { extractErrorMessage } from "./error-message.js";
|
|
41
|
+
export class SignalDeliveryRejected extends Error {
|
|
42
|
+
reason;
|
|
43
|
+
constructor(reason, detail) {
|
|
44
|
+
super(`signal_delivery_${reason}: ${detail}`);
|
|
45
|
+
this.reason = reason;
|
|
46
|
+
this.name = "SignalDeliveryRejected";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* ⚠️ TWO TIME UNITS LIVE IN THESE TABLES, AND MIXING THEM SILENTLY PRESENTS EXPIRED SIGNALS.
|
|
51
|
+
*
|
|
52
|
+
* issued_at / expires_at — epoch **SECONDS**. These are ENVELOPE fields: they are HASHED, so the
|
|
53
|
+
* protocol fixed the unit and we do not get to choose it.
|
|
54
|
+
* received_at / verified_at / consent_notified_at
|
|
55
|
+
* — epoch **MILLISECONDS** (`Date.now()`). Local bookkeeping only, never
|
|
56
|
+
* hashed, and matching the house convention of every other daemon table
|
|
57
|
+
* (`contacts.added_at`, `sessions.updated_at`). A review read
|
|
58
|
+
* `consent_notified_at` as an outlier among "seconds" siblings and
|
|
59
|
+
* proposed converting it; that is backwards — it is not hashed and not
|
|
60
|
+
* compared against `expires_at`, so it belongs with this group. Named
|
|
61
|
+
* here so the next reader does not have to re-derive it.
|
|
62
|
+
*
|
|
63
|
+
* A factor-of-1000 error between them does not throw. Compared against a 1970 timestamp, every
|
|
64
|
+
* expiry is still in the future — so the failure mode is an expired signal being cheerfully
|
|
65
|
+
* presented. Anything that compares against `expires_at` must be in SECONDS; see `listPresentable`.
|
|
66
|
+
*/
|
|
67
|
+
const ENVELOPE_COLUMNS = `
|
|
68
|
+
signal_hash TEXT NOT NULL,
|
|
69
|
+
subject_kind TEXT NOT NULL,
|
|
70
|
+
subject TEXT NOT NULL,
|
|
71
|
+
issuer_kind TEXT NOT NULL,
|
|
72
|
+
issuer_pubkey TEXT NOT NULL,
|
|
73
|
+
type TEXT NOT NULL,
|
|
74
|
+
schema_version INTEGER NOT NULL,
|
|
75
|
+
payload BLOB NOT NULL,
|
|
76
|
+
issued_at INTEGER NOT NULL,
|
|
77
|
+
expires_at INTEGER,
|
|
78
|
+
supersedes_hash TEXT,
|
|
79
|
+
status TEXT NOT NULL`;
|
|
80
|
+
/** Content-addressed: the row IS its hash (spec §14.11 — this is what makes wallet rows portable
|
|
81
|
+
* between a user's daemons, and duplicate delivery a no-op). */
|
|
82
|
+
const CREATE_WALLET_SQL = `
|
|
83
|
+
CREATE TABLE IF NOT EXISTS wallet_trust_signals (
|
|
84
|
+
${ENVELOPE_COLUMNS},
|
|
85
|
+
received_at INTEGER NOT NULL,
|
|
86
|
+
default_present INTEGER NOT NULL DEFAULT 1,
|
|
87
|
+
-- M10B-D14r2 — NULLABLE, and that is forced rather than chosen: SQLite cannot ADD COLUMN with
|
|
88
|
+
-- NOT NULL and no DEFAULT, so a MIGRATED database can only ever have a nullable column. Making
|
|
89
|
+
-- the fresh DDL stricter would give fresh installs a different schema from migrated ones, and
|
|
90
|
+
-- the divergence would surface only on fresh installs — i.e. on every new operator, which is the
|
|
91
|
+
-- worst possible audience for it. The repo's "fresh == migrated" convention wins.
|
|
92
|
+
--
|
|
93
|
+
-- Nullability costs nothing here because presentability is enforced by the PREDICATE, which tests
|
|
94
|
+
-- for exactly 'accepted' rather than for the absence of a bad value. NULL, '', 'ACCEPTED' and any
|
|
95
|
+
-- future state all fail closed by construction (§5a), so the column constraint was never what was
|
|
96
|
+
-- protecting the invariant.
|
|
97
|
+
consent_state TEXT,
|
|
98
|
+
-- DOD-END-PENDING-1 — when the operator was TOLD about this pending decision. NULL = not yet
|
|
99
|
+
-- told. Separate from consent_state because the item and the notification have different
|
|
100
|
+
-- lifetimes: the decision persists until made, the nag stops once seen.
|
|
101
|
+
consent_notified_at INTEGER,
|
|
102
|
+
-- M10B / DOD-END-COUNT-1. Stored because the PRESENTER must re-encode the envelope byte-identically
|
|
103
|
+
-- to what was notarized: re-encoding with the wrong value changes the hash and the recipient's
|
|
104
|
+
-- verification fails. It is also what a recipient's floor predicate reads to exclude co-ownership
|
|
105
|
+
-- endorsements from a min_count.
|
|
106
|
+
same_operator INTEGER NOT NULL DEFAULT 0,
|
|
107
|
+
PRIMARY KEY (signal_hash)
|
|
108
|
+
);
|
|
109
|
+
`;
|
|
110
|
+
const CREATE_RECEIVED_SQL = `
|
|
111
|
+
CREATE TABLE IF NOT EXISTS contact_trust_signals (
|
|
112
|
+
agent_id TEXT NOT NULL,
|
|
113
|
+
contact_pubkey TEXT NOT NULL,
|
|
114
|
+
${ENVELOPE_COLUMNS},
|
|
115
|
+
-- M10B / DOD-END-COUNT-1 — what the recipient's floor predicate reads to exclude co-ownership
|
|
116
|
+
-- from a min_count. It lives on BOTH tables and is NOT in ENVELOPE_COLUMNS, which is a wart worth
|
|
117
|
+
-- naming: the wallet needs it to re-encode the envelope byte-identically at presentation, and
|
|
118
|
+
-- this table needs it for the predicate. Same envelope field, two different reasons.
|
|
119
|
+
same_operator INTEGER NOT NULL DEFAULT 0,
|
|
120
|
+
verified_at INTEGER NOT NULL,
|
|
121
|
+
received_at INTEGER NOT NULL,
|
|
122
|
+
PRIMARY KEY (agent_id, contact_pubkey, signal_hash),
|
|
123
|
+
FOREIGN KEY (agent_id, contact_pubkey) REFERENCES contacts(agent_id, pubkey) ON DELETE CASCADE
|
|
124
|
+
);
|
|
125
|
+
`;
|
|
126
|
+
/**
|
|
127
|
+
* Idempotent schema. Must run AFTER `contacts` exists — the composite FK's parent. SQLite resolves
|
|
128
|
+
* an FK's parent at DML time, not at DDL time, so creating this first would not fail here; it would
|
|
129
|
+
* fail later, on the first insert, which is a far worse place to find out.
|
|
130
|
+
*/
|
|
131
|
+
/**
|
|
132
|
+
* What THIS daemon has SUBMITTED about other agents — the third table, and the one that was missing.
|
|
133
|
+
*
|
|
134
|
+
* The wallet holds signals ABOUT me; `contact_trust_signals` holds signals PRESENTED to me. Neither
|
|
135
|
+
* records what I SAID ABOUT SOMEONE ELSE, so an operator who endorsed a counterparty had no way to
|
|
136
|
+
* see it afterwards and — the part that matters — `DOD-END-WITHDRAW-1` had nothing to NAME: you
|
|
137
|
+
* cannot withdraw a submission whose id you never kept. The submission id is content-derived, so it
|
|
138
|
+
* is reproducible in principle, but only by re-composing the exact original body, which the operator
|
|
139
|
+
* no longer has.
|
|
140
|
+
*
|
|
141
|
+
* NO BODY IS STORED. The text was the operator's own words about a third party; keeping it here
|
|
142
|
+
* would put in the clear, on disk, the one thing the whole sealed-submission path exists to keep
|
|
143
|
+
* from being readable by anyone but the portal. The id, the subject and the verb are enough to name
|
|
144
|
+
* a submission for withdrawal, which is what this table is for.
|
|
145
|
+
*/
|
|
146
|
+
const CREATE_ISSUED_SQL = `
|
|
147
|
+
CREATE TABLE IF NOT EXISTS issued_submissions (
|
|
148
|
+
submission_id TEXT NOT NULL,
|
|
149
|
+
agent_id TEXT NOT NULL,
|
|
150
|
+
subject_pubkey TEXT NOT NULL,
|
|
151
|
+
op TEXT NOT NULL,
|
|
152
|
+
intake_key_id TEXT NOT NULL,
|
|
153
|
+
-- Whether the accepting node reported it as newly stored. FALSE means a node already held this
|
|
154
|
+
-- id: a benign retry, or single-node censorship, and they are indistinguishable from here.
|
|
155
|
+
stored INTEGER NOT NULL,
|
|
156
|
+
submitted_at INTEGER NOT NULL,
|
|
157
|
+
-- Content-derived, so the same body re-submitted is the SAME row rather than a second one. Keyed
|
|
158
|
+
-- with agent_id because two agents on one daemon can each submit about the same subject, and the
|
|
159
|
+
-- rows are per-agent facts.
|
|
160
|
+
PRIMARY KEY (agent_id, submission_id)
|
|
161
|
+
);
|
|
162
|
+
`;
|
|
163
|
+
export function ensureTrustSignalSchema(db, _logger) {
|
|
164
|
+
db.exec(CREATE_WALLET_SQL);
|
|
165
|
+
db.exec(CREATE_RECEIVED_SQL);
|
|
166
|
+
db.exec(CREATE_ISSUED_SQL);
|
|
167
|
+
// Presentation reads by subject; nothing reads by `type`, and nothing may (INV-ZERO-BUMP — an
|
|
168
|
+
// index predicated on a type VALUE is a per-type construct in the schema).
|
|
169
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_wallet_signals_subject ON wallet_trust_signals (subject_kind, subject)");
|
|
170
|
+
// Additive migration: add default_present if the table already exists without it.
|
|
171
|
+
try {
|
|
172
|
+
db.exec("ALTER TABLE wallet_trust_signals ADD COLUMN default_present INTEGER NOT NULL DEFAULT 1");
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Column already exists — safe to ignore.
|
|
176
|
+
}
|
|
177
|
+
// M10B / DOD-END-COUNT-1 — additive on BOTH tables, for databases created before the slot existed.
|
|
178
|
+
//
|
|
179
|
+
// WITHOUT THESE THE UPGRADE PATH IS BROKEN, not merely incomplete: the fresh DDL above gained the
|
|
180
|
+
// column, so a NEW operator works while an EXISTING one — anyone whose wallet predates it — hits
|
|
181
|
+
// "table has no column named same_operator" on the first insert and cannot receive or present any
|
|
182
|
+
// signal at all. Adding a column to the CREATE and stopping there is the classic client-side
|
|
183
|
+
// migration miss, and it is invisible in CI because every test database is fresh.
|
|
184
|
+
//
|
|
185
|
+
// `NOT NULL DEFAULT 0` is legal for ALTER (SQLite only refuses NOT NULL with NO default), so the
|
|
186
|
+
// migrated schema is identical to the fresh one — the repo's "fresh == migrated" rule holds here,
|
|
187
|
+
// unlike `consent_state` below where it could not.
|
|
188
|
+
for (const table of ["wallet_trust_signals", "contact_trust_signals"]) {
|
|
189
|
+
try {
|
|
190
|
+
db.exec(`ALTER TABLE ${table} ADD COLUMN same_operator INTEGER NOT NULL DEFAULT 0`);
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
// VERIFY, DO NOT ASSUME, THE FAILURE WAS "already exists".
|
|
194
|
+
//
|
|
195
|
+
// A bare swallow here rests on the assumption that duplicate-column is the ONLY way this can
|
|
196
|
+
// fail. It is not: `sqlcipher-db.ts` sets no `busy_timeout`, so SQLITE_BUSY returns immediately
|
|
197
|
+
// — and "two daemons on one DB" is a named real condition in this project, not a hypothetical.
|
|
198
|
+
// SQLITE_READONLY and SQLITE_FULL swallow identically.
|
|
199
|
+
//
|
|
200
|
+
// What that costs: the ALTER silently does not run, then `putReceivedSignal` throws "table has
|
|
201
|
+
// no column named same_operator", which is caught upstream as a WARN — so the session forms
|
|
202
|
+
// normally and NO presented signal is ever stored. On the wallet side it surfaces as a delivery
|
|
203
|
+
// rejection with no ACK, and the directory re-delivers forever. A migration that fails silently
|
|
204
|
+
// is indistinguishable from one that worked until something much later looks wrong.
|
|
205
|
+
//
|
|
206
|
+
// So re-read the schema and rethrow if the column is genuinely absent. The idempotent case
|
|
207
|
+
// stays silent; every other cause becomes loud. This mirrors `migrateWalletAddConsentState`
|
|
208
|
+
// below, which checks `PRAGMA table_info` for exactly this reason.
|
|
209
|
+
const cols = db.prepare(`PRAGMA table_info(${table})`).all()
|
|
210
|
+
.map((c) => c.name);
|
|
211
|
+
if (!cols.includes("same_operator")) {
|
|
212
|
+
throw new Error(`failed to add same_operator to ${table} and the column is still absent — the daemon cannot ` +
|
|
213
|
+
`store or present trust signals in this state: ${extractErrorMessage(err)}`);
|
|
214
|
+
}
|
|
215
|
+
// Present: the ALTER was a genuine no-op. No backfill is needed either — 0 (not co-owned) is
|
|
216
|
+
// correct for every pre-existing row, because no signal minted before the slot existed could
|
|
217
|
+
// have carried the flag.
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// M10B-D14r2 — DELIBERATELY OUTSIDE the try/catch above. That swallow is safe for an idempotent
|
|
221
|
+
// ALTER whose only expected failure is "already exists"; it is NOT safe for a migration with a
|
|
222
|
+
// one-time backfill, where a swallowed failure leaves the daemon running against a schema it
|
|
223
|
+
// believes gates consent and does not. This one is birth-gated and rethrows.
|
|
224
|
+
migrateWalletAddConsentState(db, _logger);
|
|
225
|
+
}
|
|
226
|
+
const toBuf = (b) => Buffer.from(b);
|
|
227
|
+
/**
|
|
228
|
+
* The payload column is `BLOB NOT NULL`, so an unrecognized shape coming back from the driver means
|
|
229
|
+
* something is wrong — NOT that the payload is empty.
|
|
230
|
+
*
|
|
231
|
+
* Returning `new Uint8Array(0)` here (the previous behavior) is the silent-fallback pattern: a signal
|
|
232
|
+
* whose payload failed to materialise would flow on to presentation and verification looking like a
|
|
233
|
+
* perfectly valid signal that simply has no content. Its hash would then not match, and the operator
|
|
234
|
+
* would be sent to hunt a canonicalization bug that does not exist. ABSENT IS NOT FINE — refuse, and
|
|
235
|
+
* name the actual cause.
|
|
236
|
+
*/
|
|
237
|
+
const toBytes = (v) => {
|
|
238
|
+
if (v instanceof Uint8Array)
|
|
239
|
+
return new Uint8Array(v);
|
|
240
|
+
if (Buffer.isBuffer(v))
|
|
241
|
+
return new Uint8Array(v);
|
|
242
|
+
throw new Error(`signal_payload_not_bytes: the payload column returned ${v === null ? "null" : typeof v}` +
|
|
243
|
+
`${v && typeof v === "object" ? ` (${v.constructor?.name})` : ""}, but the column is BLOB NOT NULL. ` +
|
|
244
|
+
"This is a storage-layer fault, not an empty payload — an empty payload would be a zero-length BLOB.");
|
|
245
|
+
};
|
|
246
|
+
/**
|
|
247
|
+
* Refuse anything that is not a 32-byte K_local pubkey as lowercase hex.
|
|
248
|
+
*
|
|
249
|
+
* SHARED, because it was written once for `listAllActive` and then DROPPED by three methods that
|
|
250
|
+
* copied its SQL predicate without it (review F3). The predicate alone fails closed, but silently:
|
|
251
|
+
* a device-local `agent_id` UUID — the natural thing to have in hand in an IPC handler — matches
|
|
252
|
+
* zero rows, which is indistinguishable from "this operator has nothing pending". For the consent
|
|
253
|
+
* queue that silence IS the bug the queue exists to prevent, and `markConsentNotified` would still
|
|
254
|
+
* match account rows and log success, so the surface would look like it was working.
|
|
255
|
+
*/
|
|
256
|
+
function requireAgentPubkeyHex(value, caller) {
|
|
257
|
+
if (!/^[0-9a-f]{64}$/.test(value ?? "")) {
|
|
258
|
+
throw new Error(`${caller} requires the agent's 32-byte K_local pubkey as lowercase hex — ` +
|
|
259
|
+
`refusing rather than returning an empty result that reads as "nothing to show"`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function toWalletRow(r) {
|
|
263
|
+
return {
|
|
264
|
+
signalHash: r.signal_hash,
|
|
265
|
+
consentState: r.consent_state,
|
|
266
|
+
sameOperator: r.same_operator === 1,
|
|
267
|
+
subjectKind: r.subject_kind,
|
|
268
|
+
subject: r.subject,
|
|
269
|
+
issuerKind: r.issuer_kind,
|
|
270
|
+
issuerPubkey: r.issuer_pubkey,
|
|
271
|
+
type: r.type,
|
|
272
|
+
schemaVersion: r.schema_version,
|
|
273
|
+
payload: toBytes(r.payload),
|
|
274
|
+
issuedAt: r.issued_at,
|
|
275
|
+
expiresAt: r.expires_at,
|
|
276
|
+
supersedesHash: r.supersedes_hash,
|
|
277
|
+
status: r.status,
|
|
278
|
+
receivedAt: r.received_at,
|
|
279
|
+
// Rows written before this column existed have null here; treat as true (default-on).
|
|
280
|
+
defaultPresent: r.default_present !== 0,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
export class TrustSignalStore {
|
|
284
|
+
#db;
|
|
285
|
+
#logger;
|
|
286
|
+
/**
|
|
287
|
+
* Does NOT create the schema. `SessionNodeManager.initialize()` owns it, and must — the received
|
|
288
|
+
* table's FK parent is `contacts`, which that init creates. A store that created its own schema
|
|
289
|
+
* would happily build `contact_trust_signals` on any handle lacking `contacts`, producing a
|
|
290
|
+
* dangling FK that then fails on the first INSERT with `no such table: main.contacts` — an error
|
|
291
|
+
* that names the wrong subsystem, at the wrong time, far from the cause.
|
|
292
|
+
*/
|
|
293
|
+
constructor(db, logger) {
|
|
294
|
+
this.#db = db;
|
|
295
|
+
this.#logger = logger;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Store a signal this daemon holds about one of its agents.
|
|
299
|
+
*
|
|
300
|
+
* `INSERT OR IGNORE`, and that is a correctness property, not a convenience: the row is keyed by
|
|
301
|
+
* its own content hash, so a second delivery of the same hash is by definition the same signal.
|
|
302
|
+
* If the bytes really differed, the hash would differ. A differing payload under an identical hash
|
|
303
|
+
* is therefore a liar, and it must not overwrite the truth. This is also what makes duplicate
|
|
304
|
+
* delivery a no-op and wallet rows safely mergeable across a user's daemons (spec §14.11).
|
|
305
|
+
*/
|
|
306
|
+
/** Returns true iff a NEW row was inserted (false = the content-addressed row already existed, a
|
|
307
|
+
* benign duplicate). */
|
|
308
|
+
putWalletSignal(s) {
|
|
309
|
+
// _id suffix signals default to excluded; everything else defaults to included.
|
|
310
|
+
const defaultPresent = s.defaultPresent !== undefined ? s.defaultPresent : !s.type.endsWith("_id");
|
|
311
|
+
const res = this.#db
|
|
312
|
+
.prepare(`INSERT OR IGNORE INTO wallet_trust_signals
|
|
313
|
+
(signal_hash, subject_kind, subject, issuer_kind, issuer_pubkey, type, schema_version,
|
|
314
|
+
payload, issued_at, expires_at, supersedes_hash, status, received_at, default_present,
|
|
315
|
+
consent_state, same_operator)
|
|
316
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
317
|
+
.run(s.signalHash, s.subjectKind, s.subject, s.issuerKind, s.issuerPubkey, s.type, s.schemaVersion, toBuf(s.payload), s.issuedAt, s.expiresAt, s.supersedesHash, s.status, Date.now(), defaultPresent ? 1 : 0,
|
|
318
|
+
// M10B-D14r2 / INV-CONSENT. Keys on ISSUER_KIND, never on the type string, so every future
|
|
319
|
+
// client-sourced type inherits consent for free (M10B-D1). An `agent`-issued signal was
|
|
320
|
+
// authored by somebody else ABOUT the operator and is unpresentable until they say so; a
|
|
321
|
+
// `portal`-issued one was minted for them, at their own action, and has no third party to
|
|
322
|
+
// wait for. Written at the one insert path, and the SQL predicate fails closed regardless.
|
|
323
|
+
s.issuerKind === "agent" ? "pending" : CONSENT_ACCEPTED, s.sameOperator === true ? 1 : 0);
|
|
324
|
+
if (res.changes > 0) {
|
|
325
|
+
this.#logger.info("signal.wallet.stored", {
|
|
326
|
+
signalHash: s.signalHash, type: s.type, subjectKind: s.subjectKind, issuerKind: s.issuerKind,
|
|
327
|
+
});
|
|
328
|
+
if (s.issuerKind === "agent") {
|
|
329
|
+
// DOD-END-PENDING-1 named event. Emitted where the decision is CREATED, so the log shows a
|
|
330
|
+
// decision being owed even if the operator never selects the agent again.
|
|
331
|
+
this.#logger.info("signal.consent.pending", {
|
|
332
|
+
signalHash: s.signalHash, subject: s.subject.slice(0, 16), issuerPubkey: s.issuerPubkey.slice(0, 16),
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return res.changes > 0;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Accept a trust-signal envelope delivered to this holder: RE-VERIFY its hash, then store it.
|
|
340
|
+
*
|
|
341
|
+
* This is the holder's own chokepoint (INV-CANONICAL / M10-D4): the daemon does not trust the
|
|
342
|
+
* `claimedHash` the delivery frame carried — it re-derives the hash from the envelope with the SAME
|
|
343
|
+
* canonical component every party uses, and REFUSES a mismatch. A delivered envelope whose bytes do
|
|
344
|
+
* not hash to the claim is a corrupted or tampered delivery; storing it would let the wallet present
|
|
345
|
+
* a signal the directory never notarized.
|
|
346
|
+
*
|
|
347
|
+
* Storage is idempotent (content-addressed PK) — a re-delivery is a no-op (§14.11). Returns whether
|
|
348
|
+
* a new row was stored, so the caller can ACK only a genuinely-accepted delivery.
|
|
349
|
+
*/
|
|
350
|
+
deliverWalletSignal(envelope, claimedHash) {
|
|
351
|
+
// A malformed claim STRING and a genuine byte-tamper are two different causes — name them apart
|
|
352
|
+
// (a directory version-skew emitting uppercase hex must not read as universal tamper and send the
|
|
353
|
+
// operator to the wrong subsystem). Both refuse-and-don't-store; only the message differs.
|
|
354
|
+
if (!/^[0-9a-f]{64}$/.test(claimedHash)) {
|
|
355
|
+
this.#logger.warn("signal.delivery.claimed_hash_malformed", { claimedHash, type: envelope.type });
|
|
356
|
+
throw new SignalDeliveryRejected("claimed_hash_malformed", `claimed hash is not 64-char lowercase hex: ${claimedHash}`);
|
|
357
|
+
}
|
|
358
|
+
if (!verifyTrustSignalHash(envelope, new Uint8Array(Buffer.from(claimedHash, "hex")))) {
|
|
359
|
+
this.#logger.warn("signal.delivery.hash_mismatch", {
|
|
360
|
+
claimedHash, type: envelope.type, subjectKind: envelope.subject_kind,
|
|
361
|
+
});
|
|
362
|
+
throw new SignalDeliveryRejected("hash_mismatch", `delivered envelope does not hash to the claimed ${claimedHash}`);
|
|
363
|
+
}
|
|
364
|
+
const supersedesHash = envelope.supersedes_hash === null ? null : Buffer.from(envelope.supersedes_hash).toString("hex");
|
|
365
|
+
// putWalletSignal is idempotent (content-addressed PK) and reports whether it inserted — use that
|
|
366
|
+
// directly rather than a second SELECT (no read-then-write, no theoretical race).
|
|
367
|
+
const inserted = this.putWalletSignal({
|
|
368
|
+
signalHash: claimedHash,
|
|
369
|
+
subjectKind: envelope.subject_kind,
|
|
370
|
+
subject: envelope.subject,
|
|
371
|
+
issuerKind: envelope.issuer_kind,
|
|
372
|
+
issuerPubkey: envelope.issuer_pubkey,
|
|
373
|
+
type: envelope.type,
|
|
374
|
+
schemaVersion: envelope.schema_version,
|
|
375
|
+
payload: envelope.payload,
|
|
376
|
+
issuedAt: envelope.issued_at,
|
|
377
|
+
expiresAt: envelope.expires_at,
|
|
378
|
+
supersedesHash,
|
|
379
|
+
// THE DELIVERED FLAG, not the column default. Omitting this stored `false` for a co-owned
|
|
380
|
+
// endorsement, and the damage was not the wrong flag — it was that PRESENTATION re-encodes from
|
|
381
|
+
// this row, so the envelope bytes no longer hashed to the notarized hash and the RECIPIENT
|
|
382
|
+
// rejected a perfectly valid signal. A field dropped on the way into the wallet is silent until
|
|
383
|
+
// it surfaces one hop away as somebody else's `hash_mismatch`.
|
|
384
|
+
sameOperator: envelope.same_operator,
|
|
385
|
+
status: "active",
|
|
386
|
+
});
|
|
387
|
+
if (inserted) {
|
|
388
|
+
// ⚠️ SUPERSESSION IS A DESTRUCTIVE WRITE BY A THIRD PARTY, so it is gated twice.
|
|
389
|
+
//
|
|
390
|
+
// GATE 1 — CONSENT (M10B / DOD-END-ACCEPT-1 review F1). An `issuer_kind: agent` delivery lands
|
|
391
|
+
// `pending` and is unpresentable, which stops a rogue endorsement being DISPLAYED. It does not
|
|
392
|
+
// stop it ERASING: without this gate the rogue's insert superseded the subject's own ACCEPTED
|
|
393
|
+
// endorsement of the same type, and Alice presented NOTHING. Consent that blocks display but
|
|
394
|
+
// not deletion closes half the threat Andre named. An unconsented signal supersedes nothing;
|
|
395
|
+
// `setConsentState` re-runs these effects if and when the subject accepts it.
|
|
396
|
+
//
|
|
397
|
+
// GATE 2 — AUTHORITY (review F2, pre-existing since M10). `supersedes_hash` was honoured
|
|
398
|
+
// without asking whether the new issuer is entitled to supersede the target, so any third
|
|
399
|
+
// party who could get one signal delivered could knock out ANY row in the wallet — including
|
|
400
|
+
// phone and email — just by naming its hash. Supersession now requires the SAME ISSUER: for an
|
|
401
|
+
// agent the key IS the identity, and for the portal it is the one logical issuer. This mirrors
|
|
402
|
+
// what the directory does in V54, where an unauthorised write must not change what a third
|
|
403
|
+
// party can present.
|
|
404
|
+
const consented = this.getWalletSignal(claimedHash)?.consentState === CONSENT_ACCEPTED;
|
|
405
|
+
if (consented) {
|
|
406
|
+
this.#applySupersession(envelope, claimedHash, supersedesHash);
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
this.#logger.info("signal.supersede.deferred", {
|
|
410
|
+
signalHash: claimedHash,
|
|
411
|
+
issuerKind: envelope.issuer_kind,
|
|
412
|
+
reason: "not consented — supersession is re-evaluated on acceptance",
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return { stored: inserted };
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Apply a newly-consented signal's supersession effects, with the ISSUER-AUTHORITY check.
|
|
420
|
+
*
|
|
421
|
+
* Extracted so acceptance can re-run it: a signal that arrived `pending` supersedes nothing until
|
|
422
|
+
* the subject accepts it, and at that moment the same rules must apply as if it had arrived
|
|
423
|
+
* accepted. One implementation, so the two entry points cannot drift.
|
|
424
|
+
*/
|
|
425
|
+
#applySupersession(envelope, claimedHash, supersedesHash) {
|
|
426
|
+
if (supersedesHash) {
|
|
427
|
+
const target = this.getWalletSignal(supersedesHash);
|
|
428
|
+
// SAME ISSUER, or refuse. A missing target is NOT an invitation to proceed (§5a): if we cannot
|
|
429
|
+
// see what is being superseded we cannot judge the authority, so we do not act.
|
|
430
|
+
const authorized = target !== null && target.issuerPubkey === envelope.issuer_pubkey;
|
|
431
|
+
if (authorized) {
|
|
432
|
+
this.setWalletStatus(supersedesHash, "superseded");
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
this.#logger.warn("signal.supersede.refused", {
|
|
436
|
+
signalHash: claimedHash,
|
|
437
|
+
supersedesHash,
|
|
438
|
+
reason: target === null ? "target_not_held" : "issuer_mismatch",
|
|
439
|
+
newIssuer: envelope.issuer_pubkey.slice(0, 16),
|
|
440
|
+
targetIssuer: target === null ? null : target.issuerPubkey.slice(0, 16),
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
// Type-dedup: another active signal of the same (subject_kind, subject, type) is superseded by
|
|
445
|
+
// the new one — duplicates delivered without supersedes_hash (e.g. a type re-minted on a fresh
|
|
446
|
+
// portal login with no prior-hash lookup). SCOPED TO THE SAME ISSUER for the same reason: a
|
|
447
|
+
// stranger's endorsement is not a newer version of yours just because it shares a type string.
|
|
448
|
+
this.#db
|
|
449
|
+
.prepare(`UPDATE wallet_trust_signals
|
|
450
|
+
SET status = 'superseded'
|
|
451
|
+
WHERE subject_kind = ? AND subject = ? AND type = ?
|
|
452
|
+
AND signal_hash != ?
|
|
453
|
+
AND issuer_pubkey = ?
|
|
454
|
+
AND status = 'active'`)
|
|
455
|
+
.run(envelope.subject_kind, envelope.subject, envelope.type, claimedHash, envelope.issuer_pubkey);
|
|
456
|
+
}
|
|
457
|
+
getWalletSignal(signalHash) {
|
|
458
|
+
const row = this.#db
|
|
459
|
+
.prepare("SELECT * FROM wallet_trust_signals WHERE signal_hash = ?")
|
|
460
|
+
.get(signalHash);
|
|
461
|
+
return row ? toWalletRow(row) : null;
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Status is the ONE mutable field — it lives outside the hash precisely so this is possible.
|
|
465
|
+
*
|
|
466
|
+
* REVOCATION IS TERMINAL. A revoked signal can never go back to `active`. Without that guard this
|
|
467
|
+
* is a blind UPDATE, and a stale or replayed directory read reporting `active` for a hash we
|
|
468
|
+
* already revoked would resurrect it — and `listPresentable` would start offering it again. The
|
|
469
|
+
* directory is the authority on revocation, but a LATE answer from it is not a NEW answer; the
|
|
470
|
+
* monotonic rule makes out-of-order responses harmless instead of dangerous.
|
|
471
|
+
*
|
|
472
|
+
* `superseded` may still be overtaken by `revoked` (a superseded signal can also be revoked), but
|
|
473
|
+
* never the reverse, and never back to `active`.
|
|
474
|
+
*/
|
|
475
|
+
setWalletStatus(signalHash, status) {
|
|
476
|
+
const res = this.#db
|
|
477
|
+
.prepare(`UPDATE wallet_trust_signals SET status = ?
|
|
478
|
+
WHERE signal_hash = ?
|
|
479
|
+
AND status != 'revoked'
|
|
480
|
+
AND NOT (status = 'superseded' AND ? = 'active')`)
|
|
481
|
+
.run(status, signalHash, status);
|
|
482
|
+
if (res.changes > 0) {
|
|
483
|
+
this.#logger.info("signal.wallet.status.changed", { signalHash, status });
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
// No change is not necessarily an error (the row may already hold this status), but a REFUSED
|
|
487
|
+
// downgrade is worth surfacing — it means something tried to resurrect a dead signal.
|
|
488
|
+
const current = this.#db
|
|
489
|
+
.prepare("SELECT status FROM wallet_trust_signals WHERE signal_hash = ?")
|
|
490
|
+
.get(signalHash);
|
|
491
|
+
if (current && current.status !== status) {
|
|
492
|
+
this.#logger.warn("signal.wallet.status.change_refused", {
|
|
493
|
+
signalHash, current: current.status, attempted: status,
|
|
494
|
+
reason: "revocation is terminal — a revoked or superseded signal is never returned to active",
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* The signals an agent may present, resolved from the ENVELOPE, not from a stored attribution:
|
|
500
|
+
* an `account`-subject row is presentable by every agent under `accountId`; an `agent`-subject row
|
|
501
|
+
* only by its own subject (M10-D5/M10-D14).
|
|
502
|
+
*
|
|
503
|
+
* **`agentPubkeyHex` is the K_local pubkey hex, NOT the daemon's device-local `agent_id`.** An
|
|
504
|
+
* agent-subject envelope's `subject` holds the pubkey — that is the value the directory joins on
|
|
505
|
+
* (`ap.k_local_pubkey = sr.subject`) — and a UUID compared against it matches nothing at all.
|
|
506
|
+
*
|
|
507
|
+
* NOTE (`DOD-END-SCOPE-FIX-1`): this method has no production callers; the live wire path is
|
|
508
|
+
* `listAllActive`, which now carries the agent-subject half of this scoping. Kept because it is
|
|
509
|
+
* the only implementation of the ACCOUNT-subject half, which is deferred behind a named
|
|
510
|
+
* prerequisite — the daemon holds no `accountId` anywhere in production code.
|
|
511
|
+
*
|
|
512
|
+
* Excludes expired and non-active rows. Selective disclosure (all / some / none) is the CALLER's
|
|
513
|
+
* choice on top of this — DOD-PRESENT-1; this returns what is *eligible*, never what to send.
|
|
514
|
+
*/
|
|
515
|
+
listPresentable(opts) {
|
|
516
|
+
// `nowSec` is epoch SECONDS, and it is named for its unit deliberately. The envelope's
|
|
517
|
+
// `issued_at`/`expires_at` are seconds (they are HASHED, and the protocol fixed the unit);
|
|
518
|
+
// `Date.now()` is milliseconds. An unnamed `now` here invites a caller to pass one where the
|
|
519
|
+
// other is meant, and a factor-of-1000 error in an expiry check does not throw — it silently
|
|
520
|
+
// presents an EXPIRED signal (compared against a 1970 timestamp, every expiry is still in the
|
|
521
|
+
// future). The first version of this method took `now` and its own test passed seconds into a
|
|
522
|
+
// parameter that was divided by 1000; it only went green because the fixture's expiry was 1.
|
|
523
|
+
const nowSec = opts.nowSec ?? Math.floor(Date.now() / 1000);
|
|
524
|
+
const rows = this.#db
|
|
525
|
+
.prepare(`SELECT * FROM wallet_trust_signals
|
|
526
|
+
WHERE status = 'active'
|
|
527
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
528
|
+
AND ( (subject_kind = 'account' AND subject = ?)
|
|
529
|
+
OR (subject_kind = 'agent' AND subject = ?) )
|
|
530
|
+
AND consent_state = '${CONSENT_ACCEPTED}'`)
|
|
531
|
+
.all(nowSec, opts.accountId, opts.agentPubkeyHex);
|
|
532
|
+
return rows.map(toWalletRow);
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* All wallet signals regardless of status — for operator inspection via `cello trust-signals list`.
|
|
536
|
+
* Ordered by issued_at DESC so the most recent signal of each type appears first.
|
|
537
|
+
*/
|
|
538
|
+
listAllWalletSignals() {
|
|
539
|
+
const rows = this.#db
|
|
540
|
+
.prepare("SELECT * FROM wallet_trust_signals ORDER BY issued_at DESC, received_at DESC")
|
|
541
|
+
.all();
|
|
542
|
+
return rows.map(toWalletRow);
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Look up a wallet signal by hash prefix (minimum 8 chars). Returns the unique matching signal,
|
|
546
|
+
* or null if no match, or throws if the prefix is ambiguous (multiple matches).
|
|
547
|
+
*/
|
|
548
|
+
getWalletSignalByPrefix(prefix) {
|
|
549
|
+
if (prefix.length < 8) {
|
|
550
|
+
throw new Error("hash prefix too short — supply at least 8 characters");
|
|
551
|
+
}
|
|
552
|
+
const rows = this.#db
|
|
553
|
+
.prepare("SELECT * FROM wallet_trust_signals WHERE signal_hash LIKE ?")
|
|
554
|
+
.all(prefix + "%");
|
|
555
|
+
if (rows.length === 0)
|
|
556
|
+
return null;
|
|
557
|
+
if (rows.length > 1)
|
|
558
|
+
throw new Error(`ambiguous hash prefix '${prefix}' matches ${rows.length} signals — supply more characters`);
|
|
559
|
+
return toWalletRow(rows[0]);
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Hard-delete a wallet signal by hash (GDPR removal). Returns true if a row was deleted.
|
|
563
|
+
*
|
|
564
|
+
* This is a permanent DELETE, not a status transition. Revocation is directory-driven and leaves
|
|
565
|
+
* the row for audit; this is the operator exercising their own right to remove a signal from their
|
|
566
|
+
* own device with no directory involvement.
|
|
567
|
+
*/
|
|
568
|
+
removeWalletSignal(signalHash) {
|
|
569
|
+
const res = this.#db
|
|
570
|
+
.prepare("DELETE FROM wallet_trust_signals WHERE signal_hash = ?")
|
|
571
|
+
.run(signalHash);
|
|
572
|
+
if (Number(res.changes) > 0) {
|
|
573
|
+
this.#logger.info("signal.wallet.removed", { signalHash });
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Active, non-expired wallet signals THIS agent is eligible to present — the live wire path
|
|
580
|
+
* (`outbound-sessions.ts`).
|
|
581
|
+
*
|
|
582
|
+
* `presentingAgentPubkeyHex` is the presenting agent's K_local pubkey hex, and it is REQUIRED.
|
|
583
|
+
* An `agent`-subject row is presentable only by its own subject (M10-D5/M10-D14); the wallet is
|
|
584
|
+
* daemon-wide and shared by every agent on the device, so without this predicate each agent
|
|
585
|
+
* offers every co-resident agent's agent-subject signals to its own counterparties —
|
|
586
|
+
* `INV-AGENT-SCOPED`, which is what `DOD-END-SCOPE-FIX-1` closes. The scoping is in the SQL, not
|
|
587
|
+
* a JS filter, because `include` already routes around `default_present` and a JS branch would
|
|
588
|
+
* route around this the same way.
|
|
589
|
+
*
|
|
590
|
+
* **`lower(subject)`, because hex has a case and this comparison is byte-exact.** SQLite `TEXT`
|
|
591
|
+
* uses BINARY collation, so `AABB…` and `aabb…` — the same key — do not match, and the row would
|
|
592
|
+
* be silently un-presented with no error. The daemon's own `k_local_pubkey` is always lowercase
|
|
593
|
+
* (`agent-loader.ts` derives it with `.toString("hex")`), so only the STORED side can vary, and it
|
|
594
|
+
* can: `putWalletSignal` already names "a directory version-skew emitting uppercase hex" as a real
|
|
595
|
+
* condition. Comparing case-insensitively is the correct equality for hex, not a fallback that
|
|
596
|
+
* papers over a mismatch.
|
|
597
|
+
*
|
|
598
|
+
* Note the residual, because it is NOT closed here — it is `DOD-M15-HEXCASE-MINT-1`: the directory's
|
|
599
|
+
* `JOIN agent_profiles ap ON ap.k_local_pubkey = sr.subject` is case-sensitive too, so an
|
|
600
|
+
* uppercase-hex subject that ever got minted would still be invisible THERE. Closing that means
|
|
601
|
+
* constraining the value where it is produced (the portal's mint) — which spans three components
|
|
602
|
+
* and is its own decision, not something to smuggle into a presentation-scoping unit.
|
|
603
|
+
*
|
|
604
|
+
* **ACCOUNT-subject rows are deliberately NOT scoped here, and that half is deferred, not done.**
|
|
605
|
+
* `listPresentable` scopes them on `accountId` — but the daemon holds no `accountId` anywhere in
|
|
606
|
+
* production code, so there is nothing to compare against and inventing one is a separate
|
|
607
|
+
* decision (M10B fourth review F5). Today's behavior for account rows is therefore unchanged:
|
|
608
|
+
* every agent on the daemon may present them, which is also what M10-D5 says for agents under the
|
|
609
|
+
* same account. It becomes wrong only when one daemon holds agents of two different accounts,
|
|
610
|
+
* and that trigger is the whole of `DOD-M15-ACCOUNT-SCOPE-1` — which is where this gets closed,
|
|
611
|
+
* not by inventing a daemon-side `accountId` to satisfy the predicate.
|
|
612
|
+
*
|
|
613
|
+
* Default behavior: returns only signals where `default_present = 1`.
|
|
614
|
+
* `include` overrides the default — only the listed types are returned regardless of `default_present`.
|
|
615
|
+
* `exclude` removes types from the default set.
|
|
616
|
+
* Both `include` and `exclude` are type strings. Unknown types cause a validation error at the
|
|
617
|
+
* IPC layer (the caller must pre-validate against listAllWalletSignals before calling this).
|
|
618
|
+
*/
|
|
619
|
+
listAllActive(opts) {
|
|
620
|
+
// ABSENT IS NOT FINE (§5a), AND SO IS MALFORMED. A caller that cannot say who is presenting gets
|
|
621
|
+
// a refusal, never the whole wallet: the fail-open direction here IS the defect this method was
|
|
622
|
+
// fixed for, and it would hand a counterparty another agent's signals with no error and no log.
|
|
623
|
+
//
|
|
624
|
+
// The SHAPE check is the half that is easy to omit and expensive to omit. An empty string is
|
|
625
|
+
// caught by any guard; a device-local `agent_id` UUID, an agent NAME, or uppercase hex all sail
|
|
626
|
+
// through a truthiness check and then match zero rows — which is indistinguishable, to every
|
|
627
|
+
// caller, from "this operator holds no signals". That silence is precisely the trap
|
|
628
|
+
// `DOD-END-SCOPE-FIX-1` exists to close, so it is closed by construction here rather than by
|
|
629
|
+
// remembering to pass the right thing. 32-byte Ed25519 key, lowercase hex, as `agent-loader.ts`
|
|
630
|
+
// produces it.
|
|
631
|
+
requireAgentPubkeyHex(opts.presentingAgentPubkeyHex, "listAllActive");
|
|
632
|
+
const nowSec = opts.nowSec ?? Math.floor(Date.now() / 1000);
|
|
633
|
+
const rows = this.#db
|
|
634
|
+
.prepare(`SELECT * FROM wallet_trust_signals
|
|
635
|
+
WHERE status = 'active'
|
|
636
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
637
|
+
AND (subject_kind <> 'agent' OR lower(subject) = ?)
|
|
638
|
+
AND consent_state = '${CONSENT_ACCEPTED}'`)
|
|
639
|
+
.all(nowSec, opts.presentingAgentPubkeyHex);
|
|
640
|
+
const all = rows.map(toWalletRow);
|
|
641
|
+
if (opts.include) {
|
|
642
|
+
const set = new Set(opts.include);
|
|
643
|
+
return all.filter((s) => set.has(s.type));
|
|
644
|
+
}
|
|
645
|
+
const excluded = new Set(opts.exclude ?? []);
|
|
646
|
+
return all.filter((s) => s.defaultPresent && !excluded.has(s.type));
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* The distinct signal TYPES this agent could present — active, unexpired, and scoped to the
|
|
650
|
+
* presenting agent exactly as `listAllActive` scopes rows.
|
|
651
|
+
*
|
|
652
|
+
* Deliberately ignores `default_present`, because this answers "may this type be named in a
|
|
653
|
+
* filter", and `include` exists precisely to override the default. Validating a filter against
|
|
654
|
+
* `listAllActive`'s output would reject a type the operator holds but has defaulted off — the
|
|
655
|
+
* filter rejecting the thing it was built to select.
|
|
656
|
+
*
|
|
657
|
+
* The scoping is the point: the wallet is daemon-wide, so validating a filter against the whole
|
|
658
|
+
* wallet accepts a type only a CO-RESIDENT agent holds, and the session then presents nothing with
|
|
659
|
+
* no error (review MEDIUM-4).
|
|
660
|
+
*/
|
|
661
|
+
listPresentableTypes(presentingAgentPubkeyHex, nowSec) {
|
|
662
|
+
const now = nowSec ?? Math.floor(Date.now() / 1000);
|
|
663
|
+
const rows = this.#db
|
|
664
|
+
.prepare(`SELECT DISTINCT type FROM wallet_trust_signals
|
|
665
|
+
WHERE status = 'active'
|
|
666
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
667
|
+
AND (subject_kind <> 'agent' OR lower(subject) = ?)
|
|
668
|
+
AND consent_state = '${CONSENT_ACCEPTED}'`)
|
|
669
|
+
.all(now, presentingAgentPubkeyHex);
|
|
670
|
+
return rows.map((r) => r.type);
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Record the subject's consent decision (D-23). The ONLY writer of this column after insert.
|
|
674
|
+
*
|
|
675
|
+
* `refused` is terminal in spirit but not enforced as one-way here: `M10B-D4` allows Bob to issue a
|
|
676
|
+
* CORRECTED endorsement after a refusal, and that is a NEW signal with its own hash — it does not
|
|
677
|
+
* reuse this row. What must never happen is a refusal being silently undone, which is why the
|
|
678
|
+
* migration is birth-gated rather than NULL-driven.
|
|
679
|
+
*/
|
|
680
|
+
setConsentState(signalHash, state) {
|
|
681
|
+
const res = this.#db
|
|
682
|
+
.prepare("UPDATE wallet_trust_signals SET consent_state = ? WHERE signal_hash = ?")
|
|
683
|
+
.run(state, signalHash);
|
|
684
|
+
if (Number(res.changes) === 0)
|
|
685
|
+
return false;
|
|
686
|
+
this.#logger.info("signal.consent.changed", { signalHash, consentState: state });
|
|
687
|
+
// ACCEPTANCE IS WHEN SUPERSESSION BECOMES LEGITIMATE (review F1). Delivery deliberately defers
|
|
688
|
+
// it — an unconsented signal must not erase a consented one — so the effects are applied here
|
|
689
|
+
// instead, through the SAME authority-checked path, at the moment the subject says yes. Without
|
|
690
|
+
// this an accepted re-issue would sit alongside the endorsement it replaces rather than
|
|
691
|
+
// superseding it, and the operator would present both.
|
|
692
|
+
if (state === CONSENT_ACCEPTED) {
|
|
693
|
+
const row = this.getWalletSignal(signalHash);
|
|
694
|
+
if (row) {
|
|
695
|
+
this.#applySupersession({
|
|
696
|
+
subject_kind: row.subjectKind,
|
|
697
|
+
subject: row.subject,
|
|
698
|
+
type: row.type,
|
|
699
|
+
issuer_kind: row.issuerKind,
|
|
700
|
+
issuer_pubkey: row.issuerPubkey,
|
|
701
|
+
}, signalHash, row.supersedesHash);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
return true;
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* DOD-END-PENDING-1 — the decisions this agent still owes (`M10B-D5`).
|
|
708
|
+
*
|
|
709
|
+
* Its OWN surface, deliberately not the transcript inbox: an inbox item is cleared by reading or
|
|
710
|
+
* dismissing a transcript, and an endorsement awaiting consent has no transcript, so it would be an
|
|
711
|
+
* item the operator could never clear the normal way.
|
|
712
|
+
*
|
|
713
|
+
* Keyed by CONSENT STATE, never by type — that is what makes a whole new queue legal under
|
|
714
|
+
* INV-ZEROBUMP, and it is why a future client-sourced type appears here with no code change.
|
|
715
|
+
*
|
|
716
|
+
* SCOPING, STATED HONESTLY. Agent-subject items are scoped to their subject, on the same axis as
|
|
717
|
+
* presentation (DOD-END-SCOPE-FIX-1). ACCOUNT-subject items are visible to every agent on the
|
|
718
|
+
* daemon — the same deferred residual `listAllActive` carries, because the daemon holds no
|
|
719
|
+
* `accountId` anywhere in production code and per M10-D5 account signals serve every agent under
|
|
720
|
+
* the account.
|
|
721
|
+
*
|
|
722
|
+
* ⚠️ BUT THE RESIDUAL CHANGES CHARACTER HERE, and that is worth naming rather than inheriting
|
|
723
|
+
* silently: in `listAllActive` the consequence is SHOWING the wrong signal; here it is DECIDING.
|
|
724
|
+
* Any agent on the daemon can accept an account-subject endorsement on another's behalf, and
|
|
725
|
+
* acceptance runs a destructive supersession. Nobody has ruled on whether account-subject consent
|
|
726
|
+
* should be per-agent or per-account — M10B-D9 says acceptance is recorded once per account-subject
|
|
727
|
+
* SIGNAL, which points at "any agent may decide", but it was written about the operator surface,
|
|
728
|
+
* not about authority. Recorded as an open question on `DOD-END-SURFACE-1` rather than settled by
|
|
729
|
+
* whichever predicate got copied first.
|
|
730
|
+
*/
|
|
731
|
+
/**
|
|
732
|
+
* Find a consent item this agent may DECIDE ON — pending, or ALREADY ACCEPTED.
|
|
733
|
+
*
|
|
734
|
+
* Refusal used to be reachable only while an item was `pending`, so "I accepted this endorsement
|
|
735
|
+
* and now I want it gone" had no path at all. This widens it, and the widening is the whole point:
|
|
736
|
+
* a refused signal is inert everywhere it is checked, which is the mechanism for taking back
|
|
737
|
+
* something you previously agreed to show.
|
|
738
|
+
*
|
|
739
|
+
* ── `issuer_kind <> 'portal'` IS THE LOAD-BEARING CLAUSE, NOT A TIDY-UP ────────────────────────
|
|
740
|
+
* Refusal makes a signal inert. So widening refusal without this filter would hand every operator
|
|
741
|
+
* a back door to suppressing their own MANDATORY signals — refuse your `track_record` and it stops
|
|
742
|
+
* being presented, achieving by consent exactly what revocation is forbidden from doing. The
|
|
743
|
+
* behavioural record is portal-issued; peer-claimed attestations are not. That is the axis, and it
|
|
744
|
+
* is the same one the DIRECTORY uses (`issuer_kind`), rather than a list of type names the client
|
|
745
|
+
* would have to keep in step.
|
|
746
|
+
*
|
|
747
|
+
* Deliberately NOT filtered by type: a hostile peer can issue a signal it CALLS `track_record`, and
|
|
748
|
+
* refusing a stranger's claim about you is precisely what this is for. The mandatory rule protects
|
|
749
|
+
* the portal's behavioural record, never a third party's assertion.
|
|
750
|
+
*
|
|
751
|
+
* Same agent-scoping predicate as `listPendingConsent` — including its unresolved question about
|
|
752
|
+
* who may decide for an account-subject item. Copied rather than diverged: two different answers to
|
|
753
|
+
* "may this agent decide" would be worse than one unresolved answer.
|
|
754
|
+
*/
|
|
755
|
+
findDecidableConsent(agentPubkeyHex, prefix) {
|
|
756
|
+
requireAgentPubkeyHex(agentPubkeyHex, "findDecidableConsent");
|
|
757
|
+
const rows = this.#db
|
|
758
|
+
.prepare(`SELECT * FROM wallet_trust_signals
|
|
759
|
+
WHERE consent_state IN ('pending', 'accepted')
|
|
760
|
+
AND status = 'active'
|
|
761
|
+
AND issuer_kind <> 'portal'
|
|
762
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
763
|
+
AND (subject_kind <> 'agent' OR lower(subject) = ?)
|
|
764
|
+
AND signal_hash LIKE ? || '%'
|
|
765
|
+
ORDER BY received_at ASC`)
|
|
766
|
+
.all(Math.floor(Date.now() / 1000), agentPubkeyHex, prefix);
|
|
767
|
+
return rows.length > 0 ? toWalletRow(rows[0]) : null;
|
|
768
|
+
}
|
|
769
|
+
listPendingConsent(agentPubkeyHex) {
|
|
770
|
+
requireAgentPubkeyHex(agentPubkeyHex, "listPendingConsent");
|
|
771
|
+
const rows = this.#db
|
|
772
|
+
.prepare(`SELECT * FROM wallet_trust_signals
|
|
773
|
+
WHERE consent_state = 'pending'
|
|
774
|
+
AND status = 'active'
|
|
775
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
776
|
+
AND (subject_kind <> 'agent' OR lower(subject) = ?)
|
|
777
|
+
ORDER BY received_at ASC`)
|
|
778
|
+
.all(Math.floor(Date.now() / 1000), agentPubkeyHex);
|
|
779
|
+
return rows.map(toWalletRow);
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* How many pending decisions this agent has NOT yet been told about.
|
|
783
|
+
*
|
|
784
|
+
* Asked on every agent selection, so it must go quiet once the operator has been told — while the
|
|
785
|
+
* ITEM stays in `listPendingConsent` until they actually decide. A new arrival raises it again,
|
|
786
|
+
* because the silence is per-item and not a permanent "already notified" flag on the agent.
|
|
787
|
+
*/
|
|
788
|
+
countUnnotifiedConsent(agentPubkeyHex) {
|
|
789
|
+
requireAgentPubkeyHex(agentPubkeyHex, "countUnnotifiedConsent");
|
|
790
|
+
const row = this.#db
|
|
791
|
+
.prepare(`SELECT COUNT(*) AS n FROM wallet_trust_signals
|
|
792
|
+
WHERE consent_state = 'pending'
|
|
793
|
+
AND consent_notified_at IS NULL
|
|
794
|
+
AND status = 'active'
|
|
795
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
796
|
+
AND (subject_kind <> 'agent' OR lower(subject) = ?)`)
|
|
797
|
+
.get(Math.floor(Date.now() / 1000), agentPubkeyHex);
|
|
798
|
+
return Number(row.n);
|
|
799
|
+
}
|
|
800
|
+
/** Record that the operator has been told about this agent's currently-pending decisions. */
|
|
801
|
+
markConsentNotified(agentPubkeyHex) {
|
|
802
|
+
requireAgentPubkeyHex(agentPubkeyHex, "markConsentNotified");
|
|
803
|
+
const res = this.#db
|
|
804
|
+
.prepare(
|
|
805
|
+
// The predicate MUST match countUnnotifiedConsent's exactly. It did not: this omitted the
|
|
806
|
+
// status and expiry clauses, so it marked rows the counter never counted — the mark and the
|
|
807
|
+
// count drifting apart is precisely how an item goes quiet without ever being shown.
|
|
808
|
+
`UPDATE wallet_trust_signals
|
|
809
|
+
SET consent_notified_at = ?
|
|
810
|
+
WHERE consent_state = 'pending'
|
|
811
|
+
AND consent_notified_at IS NULL
|
|
812
|
+
AND status = 'active'
|
|
813
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
814
|
+
AND (subject_kind <> 'agent' OR lower(subject) = ?)`)
|
|
815
|
+
.run(Date.now(), Math.floor(Date.now() / 1000), agentPubkeyHex);
|
|
816
|
+
const n = Number(res.changes);
|
|
817
|
+
if (n > 0)
|
|
818
|
+
this.#logger.info("signal.consent.notified", { agentPubkey: agentPubkeyHex.slice(0, 16), count: n });
|
|
819
|
+
return n;
|
|
820
|
+
}
|
|
821
|
+
/** Set the persistent default-presentation flag for a wallet signal. */
|
|
822
|
+
setDefaultPresent(signalHash, value) {
|
|
823
|
+
const res = this.#db
|
|
824
|
+
.prepare("UPDATE wallet_trust_signals SET default_present = ? WHERE signal_hash = ?")
|
|
825
|
+
.run(value ? 1 : 0, signalHash);
|
|
826
|
+
if (Number(res.changes) > 0) {
|
|
827
|
+
this.#logger.info("signal.wallet.default_present.changed", { signalHash, defaultPresent: value });
|
|
828
|
+
return true;
|
|
829
|
+
}
|
|
830
|
+
return false;
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Store a signal a contact PRESENTED to one of my agents, after it was verified.
|
|
834
|
+
*
|
|
835
|
+
* The FK refuses a row for a contact that does not exist — an unscoped received signal is not
|
|
836
|
+
* merely discouraged, it is unwritable. `verified_at` is RE-STAMPED on re-presentation: it records
|
|
837
|
+
* when WE last re-verified, and a stale value that looked fresh would be worse than no value at
|
|
838
|
+
* all (freshness is re-checked on use — M10-D4).
|
|
839
|
+
*/
|
|
840
|
+
/**
|
|
841
|
+
* Record a submission THIS daemon sent. Idempotent on (agent_id, submission_id): the id is
|
|
842
|
+
* content-derived, so a safe re-submit is the SAME row rather than a second one — which is what
|
|
843
|
+
* makes "re-sending is safe" true at this layer too, not just at the directory's.
|
|
844
|
+
*
|
|
845
|
+
* `stored` is UPDATED on conflict, and that direction is deliberate: a retry that finally lands as
|
|
846
|
+
* newly-stored should not keep reporting the earlier duplicate answer.
|
|
847
|
+
*/
|
|
848
|
+
recordIssuedSubmission(s) {
|
|
849
|
+
this.#db
|
|
850
|
+
.prepare(`INSERT INTO issued_submissions
|
|
851
|
+
(agent_id, submission_id, subject_pubkey, op, intake_key_id, stored, submitted_at)
|
|
852
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
853
|
+
ON CONFLICT (agent_id, submission_id) DO UPDATE SET stored = excluded.stored`)
|
|
854
|
+
.run(s.agentId, s.submissionId, s.subjectPubkey, s.op, s.intakeKeyId, s.stored ? 1 : 0, Date.now());
|
|
855
|
+
this.#logger.info("signal.submission.recorded", {
|
|
856
|
+
agentId: s.agentId, submissionId: s.submissionId, op: s.op, stored: s.stored,
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
/** What this agent has submitted, newest first. No body — see the table comment. */
|
|
860
|
+
listIssuedSubmissions(agentId) {
|
|
861
|
+
const rows = this.#db
|
|
862
|
+
.prepare(`SELECT agent_id, submission_id, subject_pubkey, op, intake_key_id, stored, submitted_at
|
|
863
|
+
FROM issued_submissions WHERE agent_id = ? ORDER BY submitted_at DESC`)
|
|
864
|
+
.all(agentId);
|
|
865
|
+
return rows.map((r) => ({
|
|
866
|
+
agentId: String(r["agent_id"]),
|
|
867
|
+
submissionId: String(r["submission_id"]),
|
|
868
|
+
subjectPubkey: String(r["subject_pubkey"]),
|
|
869
|
+
op: String(r["op"]),
|
|
870
|
+
intakeKeyId: String(r["intake_key_id"]),
|
|
871
|
+
stored: r["stored"] === 1,
|
|
872
|
+
submittedAt: Number(r["submitted_at"]),
|
|
873
|
+
}));
|
|
874
|
+
}
|
|
875
|
+
putReceivedSignal(s) {
|
|
876
|
+
this.#db
|
|
877
|
+
.prepare(`INSERT INTO contact_trust_signals
|
|
878
|
+
(agent_id, contact_pubkey, signal_hash, subject_kind, subject, issuer_kind, issuer_pubkey,
|
|
879
|
+
type, schema_version, payload, issued_at, expires_at, supersedes_hash, same_operator,
|
|
880
|
+
status, verified_at, received_at)
|
|
881
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
882
|
+
ON CONFLICT (agent_id, contact_pubkey, signal_hash)
|
|
883
|
+
DO UPDATE SET
|
|
884
|
+
verified_at = excluded.verified_at,
|
|
885
|
+
-- OUR verdict may only ever get WORSE, never better. A re-presentation cannot launder a
|
|
886
|
+
-- signal we already caught as revoked/superseded back to active: the party a revocation
|
|
887
|
+
-- indicts does not get to erase the indictment. (The envelope fields are not updated at
|
|
888
|
+
-- all — they are hashed, so an identical signal_hash means identical envelope bytes; a
|
|
889
|
+
-- differing value under the same hash is a liar and must not win.)
|
|
890
|
+
status = CASE WHEN contact_trust_signals.status = 'active' THEN excluded.status
|
|
891
|
+
ELSE contact_trust_signals.status END`)
|
|
892
|
+
.run(s.agentId, s.contactPubkey, s.signalHash, s.subjectKind, s.subject, s.issuerKind, s.issuerPubkey, s.type, s.schemaVersion, toBuf(s.payload), s.issuedAt, s.expiresAt,
|
|
893
|
+
// WITHOUT THIS THE COUNT EXCLUSION IS INERT. `evaluateSignalPolicy` filters on `sameOperator`,
|
|
894
|
+
// and this insert is the ONLY way a received signal ever gets one — omitting it meant the column
|
|
895
|
+
// always took its `0` default, every received endorsement read as not-co-owned, and
|
|
896
|
+
// DOD-END-COUNT-1's ten-agents-under-one-operator defence silently did nothing in production.
|
|
897
|
+
// The unit tests did not catch it because they construct rows directly rather than arriving
|
|
898
|
+
// through this path, which is exactly the gap a store-level default hides.
|
|
899
|
+
s.supersedesHash, s.sameOperator === true ? 1 : 0, s.verdict, s.verifiedAt, Date.now());
|
|
900
|
+
this.#logger.info("signal.received.stored", {
|
|
901
|
+
agentId: s.agentId, signalHash: s.signalHash, type: s.type, issuerKind: s.issuerKind,
|
|
902
|
+
verdict: s.verdict,
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Mark a received signal as superseded. Same monotonic rules as setWalletStatus: revoked wins,
|
|
907
|
+
* and a superseded signal never goes back to active.
|
|
908
|
+
*/
|
|
909
|
+
setReceivedStatus(opts) {
|
|
910
|
+
const res = this.#db
|
|
911
|
+
.prepare(`UPDATE contact_trust_signals SET status = ?
|
|
912
|
+
WHERE agent_id = ? AND contact_pubkey = ? AND signal_hash = ?
|
|
913
|
+
AND status != 'revoked'
|
|
914
|
+
AND NOT (status = 'superseded' AND ? = 'active')`)
|
|
915
|
+
.run(opts.status, opts.agentId, opts.contactPubkey, opts.signalHash, opts.status);
|
|
916
|
+
if (res.changes > 0) {
|
|
917
|
+
this.#logger.info("signal.received.status.changed", {
|
|
918
|
+
agentId: opts.agentId, signalHash: opts.signalHash, status: opts.status,
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
/** Evidence only. Never an input to policy — see the header. */
|
|
923
|
+
listReceived(opts) {
|
|
924
|
+
const rows = this.#db
|
|
925
|
+
.prepare(`SELECT * FROM contact_trust_signals WHERE agent_id = ? AND contact_pubkey = ?`)
|
|
926
|
+
.all(opts.agentId, opts.contactPubkey);
|
|
927
|
+
return rows.map((r) => {
|
|
928
|
+
const { status, ...envelope } = toWalletRow(r);
|
|
929
|
+
return {
|
|
930
|
+
...envelope,
|
|
931
|
+
agentId: opts.agentId,
|
|
932
|
+
contactPubkey: opts.contactPubkey,
|
|
933
|
+
verifiedAt: r.verified_at,
|
|
934
|
+
verdict: status,
|
|
935
|
+
};
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
//# sourceMappingURL=trust-signal-store.js.map
|