@vellumai/assistant 0.10.0 → 0.10.1-dev.202606240317.ea25efe
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/ARCHITECTURE.md +36 -37
- package/bun.lock +3 -0
- package/docs/workflows.md +12 -7
- package/eslint-rules/cli-no-daemon-internals.js +12 -0
- package/node_modules/@slack/types/LICENSE +23 -0
- package/node_modules/@slack/types/README.md +32 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts +953 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.js +4 -0
- package/node_modules/@slack/types/dist/block-kit/block-elements.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts +474 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.js +3 -0
- package/node_modules/@slack/types/dist/block-kit/blocks.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts +237 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.js +4 -0
- package/node_modules/@slack/types/dist/block-kit/composition-objects.js.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.d.ts +88 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.js +3 -0
- package/node_modules/@slack/types/dist/block-kit/extensions.js.map +1 -0
- package/node_modules/@slack/types/dist/calls.d.ts +26 -0
- package/node_modules/@slack/types/dist/calls.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/calls.js +6 -0
- package/node_modules/@slack/types/dist/calls.js.map +1 -0
- package/node_modules/@slack/types/dist/chunk.d.ts +52 -0
- package/node_modules/@slack/types/dist/chunk.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/chunk.js +3 -0
- package/node_modules/@slack/types/dist/chunk.js.map +1 -0
- package/node_modules/@slack/types/dist/common/bot-profile.d.ts +12 -0
- package/node_modules/@slack/types/dist/common/bot-profile.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/common/bot-profile.js +3 -0
- package/node_modules/@slack/types/dist/common/bot-profile.js.map +1 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts +6 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.js +3 -0
- package/node_modules/@slack/types/dist/common/status-emoji-display-info.js.map +1 -0
- package/node_modules/@slack/types/dist/dialog.d.ts +36 -0
- package/node_modules/@slack/types/dist/dialog.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/dialog.js +3 -0
- package/node_modules/@slack/types/dist/dialog.js.map +1 -0
- package/node_modules/@slack/types/dist/events/app.d.ts +204 -0
- package/node_modules/@slack/types/dist/events/app.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/app.js +3 -0
- package/node_modules/@slack/types/dist/events/app.js.map +1 -0
- package/node_modules/@slack/types/dist/events/assistant.d.ts +29 -0
- package/node_modules/@slack/types/dist/events/assistant.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/assistant.js +3 -0
- package/node_modules/@slack/types/dist/events/assistant.js.map +1 -0
- package/node_modules/@slack/types/dist/events/call.d.ts +8 -0
- package/node_modules/@slack/types/dist/events/call.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/call.js +3 -0
- package/node_modules/@slack/types/dist/events/call.js.map +1 -0
- package/node_modules/@slack/types/dist/events/channel.d.ts +85 -0
- package/node_modules/@slack/types/dist/events/channel.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/channel.js +3 -0
- package/node_modules/@slack/types/dist/events/channel.js.map +1 -0
- package/node_modules/@slack/types/dist/events/dnd.d.ts +24 -0
- package/node_modules/@slack/types/dist/events/dnd.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/dnd.js +3 -0
- package/node_modules/@slack/types/dist/events/dnd.js.map +1 -0
- package/node_modules/@slack/types/dist/events/email.d.ts +6 -0
- package/node_modules/@slack/types/dist/events/email.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/email.js +3 -0
- package/node_modules/@slack/types/dist/events/email.js.map +1 -0
- package/node_modules/@slack/types/dist/events/emoji.d.ts +11 -0
- package/node_modules/@slack/types/dist/events/emoji.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/emoji.js +3 -0
- package/node_modules/@slack/types/dist/events/emoji.js.map +1 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts +21 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.js +3 -0
- package/node_modules/@slack/types/dist/events/entity-details-requested.js.map +1 -0
- package/node_modules/@slack/types/dist/events/file.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/file.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/file.js +4 -0
- package/node_modules/@slack/types/dist/events/file.js.map +1 -0
- package/node_modules/@slack/types/dist/events/function.d.ts +33 -0
- package/node_modules/@slack/types/dist/events/function.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/function.js +3 -0
- package/node_modules/@slack/types/dist/events/function.js.map +1 -0
- package/node_modules/@slack/types/dist/events/grid-migration.d.ts +9 -0
- package/node_modules/@slack/types/dist/events/grid-migration.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/grid-migration.js +3 -0
- package/node_modules/@slack/types/dist/events/grid-migration.js.map +1 -0
- package/node_modules/@slack/types/dist/events/group.d.ts +55 -0
- package/node_modules/@slack/types/dist/events/group.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/group.js +3 -0
- package/node_modules/@slack/types/dist/events/group.js.map +1 -0
- package/node_modules/@slack/types/dist/events/im.d.ts +26 -0
- package/node_modules/@slack/types/dist/events/im.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/im.js +3 -0
- package/node_modules/@slack/types/dist/events/im.js.map +1 -0
- package/node_modules/@slack/types/dist/events/index.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/index.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/index.js +43 -0
- package/node_modules/@slack/types/dist/events/index.js.map +1 -0
- package/node_modules/@slack/types/dist/events/invite.d.ts +20 -0
- package/node_modules/@slack/types/dist/events/invite.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/invite.js +3 -0
- package/node_modules/@slack/types/dist/events/invite.js.map +1 -0
- package/node_modules/@slack/types/dist/events/link-shared.d.ts +16 -0
- package/node_modules/@slack/types/dist/events/link-shared.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/link-shared.js +3 -0
- package/node_modules/@slack/types/dist/events/link-shared.js.map +1 -0
- package/node_modules/@slack/types/dist/events/member.d.ts +19 -0
- package/node_modules/@slack/types/dist/events/member.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/member.js +3 -0
- package/node_modules/@slack/types/dist/events/member.js.map +1 -0
- package/node_modules/@slack/types/dist/events/message-metadata.d.ts +38 -0
- package/node_modules/@slack/types/dist/events/message-metadata.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/message-metadata.js +3 -0
- package/node_modules/@slack/types/dist/events/message-metadata.js.map +1 -0
- package/node_modules/@slack/types/dist/events/message.d.ts +306 -0
- package/node_modules/@slack/types/dist/events/message.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/message.js +3 -0
- package/node_modules/@slack/types/dist/events/message.js.map +1 -0
- package/node_modules/@slack/types/dist/events/pin.d.ts +60 -0
- package/node_modules/@slack/types/dist/events/pin.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/pin.js +3 -0
- package/node_modules/@slack/types/dist/events/pin.js.map +1 -0
- package/node_modules/@slack/types/dist/events/reaction.d.ts +23 -0
- package/node_modules/@slack/types/dist/events/reaction.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/reaction.js +3 -0
- package/node_modules/@slack/types/dist/events/reaction.js.map +1 -0
- package/node_modules/@slack/types/dist/events/shared-channel.d.ts +134 -0
- package/node_modules/@slack/types/dist/events/shared-channel.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/shared-channel.js +3 -0
- package/node_modules/@slack/types/dist/events/shared-channel.js.map +1 -0
- package/node_modules/@slack/types/dist/events/star.d.ts +13 -0
- package/node_modules/@slack/types/dist/events/star.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/star.js +3 -0
- package/node_modules/@slack/types/dist/events/star.js.map +1 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts +82 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.js +3 -0
- package/node_modules/@slack/types/dist/events/steps-from-apps.js.map +1 -0
- package/node_modules/@slack/types/dist/events/subteam.d.ts +66 -0
- package/node_modules/@slack/types/dist/events/subteam.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/subteam.js +3 -0
- package/node_modules/@slack/types/dist/events/subteam.js.map +1 -0
- package/node_modules/@slack/types/dist/events/team.d.ts +99 -0
- package/node_modules/@slack/types/dist/events/team.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/team.js +3 -0
- package/node_modules/@slack/types/dist/events/team.js.map +1 -0
- package/node_modules/@slack/types/dist/events/token.d.ts +8 -0
- package/node_modules/@slack/types/dist/events/token.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/token.js +3 -0
- package/node_modules/@slack/types/dist/events/token.js.map +1 -0
- package/node_modules/@slack/types/dist/events/user.d.ts +313 -0
- package/node_modules/@slack/types/dist/events/user.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/events/user.js +3 -0
- package/node_modules/@slack/types/dist/events/user.js.map +1 -0
- package/node_modules/@slack/types/dist/index.d.ts +12 -0
- package/node_modules/@slack/types/dist/index.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/index.js +28 -0
- package/node_modules/@slack/types/dist/index.js.map +1 -0
- package/node_modules/@slack/types/dist/message-attachments.d.ts +171 -0
- package/node_modules/@slack/types/dist/message-attachments.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/message-attachments.js +3 -0
- package/node_modules/@slack/types/dist/message-attachments.js.map +1 -0
- package/node_modules/@slack/types/dist/message-metadata.d.ts +281 -0
- package/node_modules/@slack/types/dist/message-metadata.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/message-metadata.js +27 -0
- package/node_modules/@slack/types/dist/message-metadata.js.map +1 -0
- package/node_modules/@slack/types/dist/views.d.ts +71 -0
- package/node_modules/@slack/types/dist/views.d.ts.map +1 -0
- package/node_modules/@slack/types/dist/views.js +3 -0
- package/node_modules/@slack/types/dist/views.js.map +1 -0
- package/node_modules/@slack/types/package.json +47 -0
- package/node_modules/@vellumai/gateway-client/bun.lock +3 -0
- package/node_modules/@vellumai/gateway-client/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/contact-read-contracts.test.ts +69 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +91 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +96 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +162 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +28 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +4 -2
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +3 -2
- package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +95 -0
- package/openapi.yaml +458 -18
- package/package.json +2 -1
- package/scripts/memory-inspect.ts +24 -14
- package/scripts/test.sh +36 -15
- package/src/__tests__/access-request-seed-content-blocks.test.ts +83 -103
- package/src/__tests__/activation-early-marking.test.ts +1 -1
- package/src/__tests__/actor-token-service.test.ts +39 -17
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +1 -40
- package/src/__tests__/agent-loop-compaction-events.test.ts +0 -1
- package/src/__tests__/agent-loop-compaction-strip.test.ts +0 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +0 -1
- package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
- package/src/__tests__/agent-loop-regrowth-guard.test.ts +0 -1
- package/src/__tests__/agent-loop.test.ts +3 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
- package/src/__tests__/anthropic-provider.test.ts +210 -9
- package/src/__tests__/app-builder-skill-instructions.test.ts +47 -5
- package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -1
- package/src/__tests__/app-source-watcher.test.ts +30 -10
- package/src/__tests__/approval-cascade.test.ts +6 -0
- package/src/__tests__/approval-interception-trust-gates.test.ts +151 -0
- package/src/__tests__/approval-primitive.test.ts +1 -1
- package/src/__tests__/approval-routes-http.test.ts +1 -1
- package/src/__tests__/assistant-attachments.test.ts +155 -0
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +2 -4
- package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
- package/src/__tests__/assistant-events-sse-shed.test.ts +1 -1
- package/src/__tests__/attachment-upload-trusted-source.test.ts +13 -8
- package/src/__tests__/attachments-store.test.ts +1 -1
- package/src/__tests__/audit-log-rotation.test.ts +50 -54
- package/src/__tests__/auth-fallback-events-store.test.ts +1 -1
- package/src/__tests__/auto-analysis-end-to-end.test.ts +9 -14
- package/src/__tests__/background-shell-bash.test.ts +4 -1
- package/src/__tests__/background-shell-host-bash.test.ts +17 -3
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
- package/src/__tests__/call-controller.test.ts +20 -1
- package/src/__tests__/call-conversation-messages.test.ts +1 -1
- package/src/__tests__/call-domain.test.ts +1 -1
- package/src/__tests__/call-pointer-messages.test.ts +3 -4
- package/src/__tests__/call-recovery.test.ts +1 -1
- package/src/__tests__/call-routes-http.test.ts +1 -1
- package/src/__tests__/call-store.test.ts +1 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/canonical-guardian-store.test.ts +24 -1
- package/src/__tests__/card-surface-data.test.ts +60 -0
- package/src/__tests__/channel-approval-routes.test.ts +73 -1119
- package/src/__tests__/channel-delivery-store.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +291 -641
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +1 -2
- package/src/__tests__/channel-retry-sweep.test.ts +1 -1
- package/src/__tests__/compaction-events.test.ts +6 -0
- package/src/__tests__/compaction-trail-store.test.ts +6 -5
- package/src/__tests__/compaction.benchmark.test.ts +0 -1
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
- package/src/__tests__/config-loader-backfill.test.ts +188 -52
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -2
- package/src/__tests__/contact-store-user-file.test.ts +2 -2
- package/src/__tests__/contacts-relay-reads.test.ts +409 -0
- package/src/__tests__/contacts-tools.test.ts +4 -4
- package/src/__tests__/contacts-write.test.ts +1 -2
- package/src/__tests__/context-search-conversations-source.test.ts +1 -1
- package/src/__tests__/context-window-manager-compact-retry.test.ts +6 -2
- package/src/__tests__/context-window-manager-overflow-rung.test.ts +6 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +3 -0
- package/src/__tests__/conversation-agent-loop.test.ts +7 -0
- package/src/__tests__/conversation-attachments.test.ts +2 -5
- package/src/__tests__/conversation-attention-store.test.ts +1 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +1 -2
- package/src/__tests__/conversation-clear-safety.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
- package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +12 -19
- package/src/__tests__/conversation-disk-view-integration.test.ts +1 -1
- package/src/__tests__/conversation-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +10 -8
- package/src/__tests__/conversation-fork-retrospective.test.ts +250 -0
- package/src/__tests__/conversation-fork-route.test.ts +1 -1
- package/src/__tests__/conversation-inference-profile-list.test.ts +1 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +1 -1
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-lifecycle.test.ts +117 -0
- package/src/__tests__/conversation-list-source.test.ts +3 -3
- package/src/__tests__/conversation-process-callsite.test.ts +6 -14
- package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/conversation-queue.test.ts +95 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +12 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +12 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +115 -12
- package/src/__tests__/conversation-slash-queue.test.ts +6 -0
- package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
- package/src/__tests__/conversation-speed-override.test.ts +6 -0
- package/src/__tests__/conversation-starter-routes.test.ts +5 -5
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +4 -4
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +352 -0
- package/src/__tests__/conversation-sync-tags.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
- package/src/__tests__/conversation-usage.test.ts +1 -1
- package/src/__tests__/conversation-wipe.test.ts +9 -8
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/conversations-import-system-filter.test.ts +1 -1
- package/src/__tests__/copy-composer-tc-templates.test.ts +17 -0
- package/src/__tests__/credential-security-invariants.test.ts +0 -1
- package/src/__tests__/db-acp-history.test.ts +2 -2
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +5 -7
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +6 -7
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +5 -10
- package/src/__tests__/db-migration-rollback.test.ts +129 -39
- package/src/__tests__/db-proxy-transaction.test.ts +1 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +0 -11
- package/src/__tests__/db-test-helpers.ts +36 -19
- package/src/__tests__/delete-propagation.test.ts +1 -1
- package/src/__tests__/deterministic-verification-control-plane.test.ts +28 -8
- package/src/__tests__/disk-pressure-guard.test.ts +41 -0
- package/src/__tests__/disk-pressure-tools.test.ts +41 -1
- package/src/__tests__/dm-backfill.test.ts +1 -1
- package/src/__tests__/drop-capability-card-state-migration.test.ts +0 -8
- package/src/__tests__/dynamic-page-surface.test.ts +0 -94
- package/src/__tests__/edit-propagation.test.ts +1 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +93 -5
- package/src/__tests__/empty-response-hook.test.ts +42 -0
- package/src/__tests__/events-client-registration.test.ts +1 -1
- package/src/__tests__/events-dev-bypass-actor.test.ts +7 -1
- package/src/__tests__/followup-tools.test.ts +1 -1
- package/src/__tests__/gemini-count-tokens.test.ts +70 -0
- package/src/__tests__/guardian-action-sweep.test.ts +9 -2
- package/src/__tests__/guardian-binding-drift-heal.test.ts +76 -11
- package/src/__tests__/guardian-card-withdrawal.test.ts +1 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +96 -2
- package/src/__tests__/guardian-outbound-http.test.ts +20 -12
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +1 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
- package/src/__tests__/guardian-routing-state.test.ts +1 -2
- package/src/__tests__/guardian-verification-voice-binding.test.ts +1 -1
- package/src/__tests__/headless-browser-mode.test.ts +2 -2
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +6 -0
- package/src/__tests__/helpers/channel-test-adapter.ts +92 -0
- package/src/__tests__/host-app-control-routes.test.ts +24 -30
- package/src/__tests__/host-bash-routes.test.ts +31 -41
- package/src/__tests__/host-browser-routes.test.ts +26 -32
- package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
- package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
- package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
- package/src/__tests__/http-conversation-lineage.test.ts +1 -1
- package/src/__tests__/http-user-message-parity.test.ts +165 -8
- package/src/__tests__/image-recovery-hook.test.ts +1 -1
- package/src/__tests__/inbound-invite-redemption.test.ts +1 -2
- package/src/__tests__/inbound-trust-verdict.test.ts +254 -0
- package/src/__tests__/inference-profile-reaper.test.ts +1 -1
- package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
- package/src/__tests__/inference-profile-session-ipc.test.ts +1 -1
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-disk-pressure.test.ts +11 -6
- package/src/__tests__/internal-telemetry-routes.test.ts +1 -1
- package/src/__tests__/invite-redemption-service.test.ts +244 -43
- package/src/__tests__/invite-routes-http.test.ts +35 -186
- package/src/__tests__/invite-service-ipc.test.ts +287 -0
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +5 -5
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +9 -12
- package/src/__tests__/list-messages-attachments.test.ts +42 -1
- package/src/__tests__/list-messages-client-message-id.test.ts +1 -1
- package/src/__tests__/list-messages-hidden-metadata.test.ts +1 -1
- package/src/__tests__/list-messages-page-latest.test.ts +1 -1
- package/src/__tests__/list-messages-tool-merge.test.ts +1 -1
- package/src/__tests__/llm-context-normalization.test.ts +105 -0
- package/src/__tests__/llm-context-route-provider.test.ts +69 -4
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +9 -5
- package/src/__tests__/llm-request-log-call-site.test.ts +6 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +27 -13
- package/src/__tests__/llm-resolver.test.ts +205 -5
- package/src/__tests__/llm-usage-store.test.ts +65 -1
- package/src/__tests__/log-export-routes.test.ts +1 -1
- package/src/__tests__/log-export-workspace.test.ts +3 -3
- package/src/__tests__/media-stream-server-integration.test.ts +127 -0
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +5 -5
- package/src/__tests__/memory-recall-log-store.test.ts +1 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +3 -4
- package/src/__tests__/messages-after-tiebreaker.test.ts +1 -1
- package/src/__tests__/migration-import-from-url.test.ts +2 -2
- package/src/__tests__/mtime-cache.test.ts +375 -0
- package/src/__tests__/non-member-access-request.test.ts +190 -19
- package/src/__tests__/notification-broadcaster.test.ts +4 -0
- package/src/__tests__/notification-candidate-guardian-context.test.ts +203 -0
- package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
- package/src/__tests__/notification-deep-link.test.ts +4 -0
- package/src/__tests__/notification-guardian-path.test.ts +20 -1
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
- package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
- package/src/__tests__/oauth-provider-visibility.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +1 -1
- package/src/__tests__/pending-interactions-resolved-event.test.ts +7 -4
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +1 -1
- package/src/__tests__/persist-unsendable-image.test.ts +1 -1
- package/src/__tests__/persona-resolver.test.ts +39 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/playbook-execution.test.ts +1 -1
- package/src/__tests__/playbook-tools.test.ts +1 -1
- package/src/__tests__/plugin-api-model-profiles.test.ts +74 -21
- package/src/__tests__/plugin-bootstrap.test.ts +78 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +25 -5
- package/src/__tests__/provider-usage-tracking.test.ts +40 -1
- package/src/__tests__/prune-old-conversations-job.test.ts +1 -1
- package/src/__tests__/reaction-persistence.test.ts +1 -1
- package/src/__tests__/registry.test.ts +3 -0
- package/src/__tests__/relay-server.test.ts +1026 -73
- package/src/__tests__/runtime-attachment-metadata.test.ts +9 -1
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +7 -9
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -1
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/schedule-retry.test.ts +1 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +1 -1
- package/src/__tests__/schedule-store.test.ts +1 -1
- package/src/__tests__/schedule-tools.test.ts +1 -1
- package/src/__tests__/scheduler-disk-pressure.test.ts +1 -1
- package/src/__tests__/scheduler-recurrence.test.ts +1 -1
- package/src/__tests__/scheduler-reuse-conversation.test.ts +1 -1
- package/src/__tests__/scheduler-wake.test.ts +2 -1
- package/src/__tests__/scoped-approval-grants.test.ts +1 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +5 -5
- package/src/__tests__/scrub-corrupted-image-attachments.test.ts +0 -8
- package/src/__tests__/secret-ingress-http.test.ts +12 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +31 -9
- package/src/__tests__/sequence-store.test.ts +1 -1
- package/src/__tests__/server-history-render.test.ts +40 -1
- package/src/__tests__/settings-routes.test.ts +11 -10
- package/src/__tests__/skill-load-tool.test.ts +72 -0
- package/src/__tests__/skills.test.ts +44 -0
- package/src/__tests__/slack-inbound-verification.test.ts +48 -5
- package/src/__tests__/slack-messaging-token-resolution.test.ts +13 -2
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +1 -1
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +102 -0
- package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
- package/src/__tests__/stt-hints.test.ts +44 -13
- package/src/__tests__/subagent-detail.test.ts +27 -0
- package/src/__tests__/subagent-disposal.test.ts +65 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +2 -73
- package/src/__tests__/subagent-tools.test.ts +1 -31
- package/src/__tests__/system-prompt.test.ts +1 -1
- package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
- package/src/__tests__/task-compiler.test.ts +1 -1
- package/src/__tests__/task-management-tools.test.ts +1 -1
- package/src/__tests__/task-memory-cleanup.test.ts +9 -6
- package/src/__tests__/task-scheduler.test.ts +1 -1
- package/src/__tests__/thread-backfill.test.ts +1 -1
- package/src/__tests__/tool-approval-handler.test.ts +1 -1
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +2 -0
- package/src/__tests__/tool-executor.test.ts +37 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +73 -1
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +34 -34
- package/src/__tests__/trusted-contact-multichannel.test.ts +1 -2
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/turn-boundary-resolution.test.ts +3 -3
- package/src/__tests__/turn-events-store.test.ts +1 -1
- package/src/__tests__/twilio-routes.test.ts +98 -3
- package/src/__tests__/usage-cache-backfill-migration.test.ts +20 -10
- package/src/__tests__/usage-routes.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +34 -29
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/voice-invite-redemption.test.ts +134 -36
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +1 -1
- package/src/__tests__/voice-session-bridge.test.ts +1 -1
- package/src/__tests__/workspace-git-service.test.ts +114 -1
- package/src/__tests__/workspace-heartbeat-service.test.ts +45 -0
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -1
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +88 -18
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +6 -6
- package/src/__tests__/workspace-migration-109-swap-quality-profile-to-glm-5p2.test.ts +281 -0
- package/src/__tests__/workspace-migration-110-flip-balanced-profile-to-together.test.ts +167 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +55 -0
- package/src/__tests__/workspace-tool-loader.test.ts +3 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -1
- package/src/a2a/__tests__/task-store.test.ts +1 -1
- package/src/acp/__tests__/session-manager-persistence.test.ts +1 -1
- package/src/acp/__tests__/session-manager-resume.test.ts +22 -11
- package/src/acp/__tests__/session-manager-startup.test.ts +1 -1
- package/src/acp/__tests__/session-manager.test.ts +72 -1
- package/src/acp/index.ts +10 -0
- package/src/acp/session-manager.ts +35 -0
- package/src/agent/loop-exclusive-tool.test.ts +150 -0
- package/src/agent/loop.ts +101 -27
- package/src/api/constants/sse-replay.ts +41 -0
- package/src/api/events/ui-surface-show.ts +8 -3
- package/src/api/index.ts +7 -6
- package/src/api/responses/conversation-message.ts +4 -0
- package/src/api/responses/llm-request-log-entry.ts +25 -0
- package/src/api/responses/subagent-detail.ts +17 -0
- package/src/api/surfaces.ts +33 -0
- package/src/approvals/AGENTS.md +1 -2
- package/src/approvals/guardian-decision-primitive.ts +13 -210
- package/src/approvals/guardian-request-resolvers.ts +104 -58
- package/src/background-wake/wake-intent-hooks.test.ts +1 -1
- package/src/calls/__tests__/inbound-trust-reader.test.ts +110 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +349 -65
- package/src/calls/guardian-dispatch.ts +10 -8
- package/src/calls/inbound-trust-reader.ts +56 -0
- package/src/calls/media-stream-server.ts +21 -0
- package/src/calls/relay-server.ts +231 -72
- package/src/calls/relay-setup-router.ts +57 -13
- package/src/calls/relay-verification.ts +7 -7
- package/src/calls/stt-hints.ts +9 -12
- package/src/calls/twilio-routes.ts +13 -3
- package/src/cli/commands/__tests__/cache.test.ts +8 -1
- package/src/cli/commands/cache.ts +194 -181
- package/src/cli/commands/contacts.ts +6 -24
- package/src/cli/commands/db/__tests__/repair.test.ts +15 -6
- package/src/cli/commands/db/__tests__/status.test.ts +7 -3
- package/src/cli/commands/db/status.ts +212 -33
- package/src/cli/commands/mcp.ts +252 -218
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +6 -1
- package/src/cli/commands/memory/__tests__/worker.test.ts +302 -0
- package/src/cli/commands/memory/index.ts +4 -0
- package/src/cli/commands/memory/memory-retrospective.ts +129 -0
- package/src/cli/commands/memory/memory-v3.ts +176 -4
- package/src/cli/commands/memory/worker.ts +175 -0
- package/src/cli/commands/plugins.ts +343 -14
- package/src/cli/lib/__tests__/install-from-github.test.ts +40 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
- package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
- package/src/cli/lib/__tests__/toggle-plugin.test.ts +158 -0
- package/src/cli/lib/install-from-github.ts +47 -6
- package/src/cli/lib/list-installed-plugins.ts +179 -1
- package/src/cli/lib/plugin-marketplace.ts +11 -0
- package/src/cli/lib/plugin-pin-history.ts +257 -0
- package/src/cli/lib/toggle-plugin.ts +146 -0
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +143 -0
- package/src/config/__tests__/sync-gated-profiles.test.ts +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +15 -33
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +3 -8
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +64 -37
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +1 -1
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +14 -72
- package/src/config/bundled-skills/app-builder/references/examples/README.md +1 -2
- package/src/config/bundled-skills/contacts/SKILL.md +7 -12
- package/src/config/bundled-skills/messaging/tools/shared.ts +4 -1
- package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
- package/src/config/bundled-skills/workflows/SKILL.md +4 -3
- package/src/config/call-site-defaults.ts +11 -2
- package/src/config/feature-flag-registry.json +0 -8
- package/src/config/llm-resolver.ts +151 -14
- package/src/config/loader.ts +36 -5
- package/src/config/profile-dispatchability.ts +11 -0
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/llm.ts +2 -0
- package/src/config/schemas/memory-lifecycle.ts +17 -3
- package/src/config/schemas/memory-v3.ts +7 -0
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/timeouts.ts +32 -0
- package/src/config/seed-inference-profiles.ts +147 -50
- package/src/config/skills.ts +27 -5
- package/src/config/sync-gated-profiles.ts +13 -1
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
- package/src/contacts/contact-store.ts +21 -0
- package/src/contacts/contacts-write.ts +3 -0
- package/src/contacts/guardian-delivery-reader.ts +223 -0
- package/src/contacts/member-status.ts +9 -0
- package/src/credential-health/credential-health-service.ts +1 -5
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
- package/src/daemon/app-source-watcher.ts +31 -18
- package/src/daemon/assistant-attachments.ts +94 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +3 -0
- package/src/daemon/conversation-agent-loop.ts +18 -36
- package/src/daemon/conversation-process.ts +35 -16
- package/src/daemon/conversation-runtime-assembly.ts +91 -66
- package/src/daemon/conversation-surfaces.ts +273 -18
- package/src/daemon/conversation-tool-setup.ts +24 -64
- package/src/daemon/conversation.ts +149 -53
- package/src/daemon/disk-pressure-guard.ts +12 -2
- package/src/daemon/event-loop-watchdog.test.ts +85 -0
- package/src/daemon/event-loop-watchdog.ts +133 -0
- package/src/daemon/external-plugins-bootstrap.ts +26 -80
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -1
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -1
- package/src/daemon/handlers/config-channels.ts +41 -27
- package/src/daemon/handlers/conversations.ts +84 -0
- package/src/daemon/handlers/shared.ts +7 -0
- package/src/daemon/lifecycle.ts +44 -5
- package/src/daemon/memory-v2-startup.test.ts +72 -0
- package/src/daemon/memory-v2-startup.ts +87 -19
- package/src/daemon/message-types/inbox.ts +0 -6
- package/src/daemon/message-types/messages.ts +0 -4
- package/src/daemon/message-types/surfaces.ts +12 -11
- package/src/daemon/server.ts +0 -4
- package/src/daemon/shutdown-handlers.ts +20 -0
- package/src/daemon/tool-setup-types.ts +7 -5
- package/src/daemon/trust-context.ts +6 -0
- package/src/daemon/wake-conversation-ops.ts +70 -0
- package/src/daemon/workspace-tools-watcher.ts +7 -3
- package/src/documents/document-comments-store.test.ts +1 -1
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +1 -1
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -0
- package/src/heartbeat/heartbeat-service.ts +3 -4
- package/src/ipc/__tests__/attachment-ipc.test.ts +1 -1
- package/src/ipc/__tests__/browser-ipc.test.ts +73 -2
- package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
- package/src/ipc/__tests__/watcher-ipc.test.ts +59 -39
- package/src/ipc/assistant-server.ts +10 -2
- package/src/ipc/gateway-client.ts +2 -1
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +58 -0
- package/src/ipc/routes/invite-ipc-routes.ts +66 -0
- package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -1
- package/src/memory/__tests__/activation-session-store.test.ts +1 -1
- package/src/memory/__tests__/auto-analysis-guard.test.ts +1 -1
- package/src/memory/__tests__/conversation-group-migration.test.ts +1 -1
- package/src/memory/__tests__/conversation-queries.test.ts +1 -1
- package/src/memory/__tests__/db-async-query.test.ts +1 -1
- package/src/memory/__tests__/db-logs-attach.test.ts +110 -0
- package/src/memory/__tests__/db-maintenance.test.ts +28 -36
- package/src/memory/__tests__/db-memory-attach.test.ts +113 -0
- package/src/memory/__tests__/find-analysis-conversation.test.ts +1 -1
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -1
- package/src/memory/__tests__/fork-message-copy.test.ts +232 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +3 -0
- package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +5 -5
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +8 -6
- package/src/memory/__tests__/memory-retrospective-job.test.ts +30 -37
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +69 -66
- package/src/memory/__tests__/memory-retrospective-state.test.ts +1 -1
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +1 -1
- package/src/memory/__tests__/onboarding-events-store.test.ts +1 -1
- package/src/memory/__tests__/prompt-override.test.ts +192 -0
- package/src/memory/__tests__/table-relocation.test.ts +129 -0
- package/src/memory/conversation-crud.ts +461 -152
- package/src/memory/db-async-query.ts +89 -5
- package/src/memory/db-connection.ts +101 -18
- package/src/memory/db-init.ts +409 -234
- package/src/memory/db-maintenance.ts +43 -38
- package/src/memory/db-singleton.ts +45 -19
- package/src/memory/embedding-gemini.test.ts +3 -1
- package/src/memory/embedding-gemini.ts +18 -2
- package/src/memory/fork-message-copy.ts +170 -0
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +92 -0
- package/src/memory/graph/bootstrap.test.ts +6 -3
- package/src/memory/graph/retriever.test.ts +12 -12
- package/src/memory/graph/store.test.ts +15 -25
- package/src/memory/graph/store.ts +23 -14
- package/src/memory/graph/tool-handlers.ts +34 -5
- package/src/memory/graph/tools.ts +5 -2
- package/src/memory/indexer.ts +21 -9
- package/src/memory/job-handlers/cleanup.ts +10 -3
- package/src/memory/job-handlers/embedding.test.ts +4 -4
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +4 -4
- package/src/memory/jobs/embed-pkb-file.test.ts +7 -7
- package/src/memory/jobs-store.ts +36 -24
- package/src/memory/llm-request-log-store.ts +51 -19
- package/src/memory/llm-usage-store.ts +79 -21
- package/src/memory/memory-retrospective-job.ts +27 -19
- package/src/memory/memory-retrospective-startup-cleanup.ts +10 -2
- package/src/memory/migrations/{100-core-tables.ts → 000-core-tables.ts} +6 -10
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +13 -3
- package/src/memory/migrations/104-core-indexes.ts +1 -1
- package/src/memory/migrations/126-backfill-guardian-principal-id.ts +189 -196
- package/src/memory/migrations/127-guardian-principal-id-not-null.ts +98 -105
- package/src/memory/migrations/134-contacts-notes-column.ts +66 -69
- package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +19 -22
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +241 -219
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +204 -209
- package/src/memory/migrations/141-rename-verification-table.ts +45 -48
- package/src/memory/migrations/142-rename-verification-session-id-column.ts +16 -23
- package/src/memory/migrations/143-rename-guardian-verification-values.ts +23 -30
- package/src/memory/migrations/144-rename-voice-to-phone.ts +133 -136
- package/src/memory/migrations/145-drop-accounts-table.ts +4 -7
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +79 -82
- package/src/memory/migrations/148-drop-reminders-table.ts +3 -6
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +71 -78
- package/src/memory/migrations/157-invite-contact-id.ts +73 -76
- package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +44 -58
- package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +36 -43
- package/src/memory/migrations/174-rename-thread-starters-table.ts +30 -37
- package/src/memory/migrations/176-drop-capability-card-state.ts +17 -22
- package/src/memory/migrations/177-create-trace-events-table.ts +23 -28
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +36 -43
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +14 -21
- package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +17 -24
- package/src/memory/migrations/192-contacts-user-file-column.ts +6 -9
- package/src/memory/migrations/193-add-source-type-columns.ts +33 -36
- package/src/memory/migrations/194-memory-recall-logs.ts +34 -39
- package/src/memory/migrations/196-strip-integration-prefix-from-provider-keys.ts +59 -66
- package/src/memory/migrations/199-guardian-request-enrichment-columns.ts +41 -48
- package/src/memory/migrations/204-rename-memory-graph-type-values.ts +11 -18
- package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +76 -83
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +135 -68
- package/src/memory/migrations/211-memory-recall-logs-query-context.ts +6 -11
- package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +4 -9
- package/src/memory/migrations/217-conversation-host-access.ts +13 -18
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +86 -93
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +41 -48
- package/src/memory/migrations/230-acp-session-history.ts +23 -28
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +58 -62
- package/src/memory/migrations/232-activation-state.ts +11 -16
- package/src/memory/migrations/233-document-conversations.ts +20 -25
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +26 -31
- package/src/memory/migrations/235-slack-compaction-watermark.ts +5 -10
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +6 -11
- package/src/memory/migrations/237-heartbeat-runs.ts +22 -27
- package/src/memory/migrations/239-trace-events-created-at-index.ts +4 -9
- package/src/memory/migrations/242-message-bookmarks.ts +17 -22
- package/src/memory/migrations/245-memory-retrospective-state.ts +8 -13
- package/src/memory/migrations/249-normalize-slack-external-content.ts +37 -41
- package/src/memory/migrations/251-a2a-tasks.ts +27 -32
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +12 -17
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +10 -15
- package/src/memory/migrations/256-memory-v2-injection-events.ts +70 -74
- package/src/memory/migrations/259-conversation-cleaned-at.ts +4 -9
- package/src/memory/migrations/260-rename-cleaned-at.ts +11 -16
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +3 -8
- package/src/memory/migrations/262-memory-v3-coactivation.ts +21 -26
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +14 -19
- package/src/memory/migrations/270-schedule-description.ts +7 -12
- package/src/memory/migrations/272-acp-session-history-cwd.ts +8 -13
- package/src/memory/migrations/281-memory-retrospective-remembered-log.ts +8 -13
- package/src/memory/migrations/297-move-llm-request-logs-to-logs-db.ts +111 -0
- package/src/memory/migrations/298-move-memory-jobs-to-memory-db.ts +128 -0
- package/src/memory/migrations/299-canonical-guardian-deliveries-conversation-index.ts +19 -0
- package/src/memory/migrations/__tests__/014-backfill-inbox-thread-state.test.ts +108 -0
- package/src/memory/migrations/__tests__/136-drop-assistant-id-columns.test.ts +82 -0
- package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +224 -0
- package/src/memory/migrations/__tests__/297-move-llm-request-logs.test.ts +180 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +333 -7
- package/src/memory/migrations/helpers/relocation.ts +227 -0
- package/src/memory/migrations/registry.ts +63 -0
- package/src/memory/migrations/run-migrations.ts +187 -16
- package/src/memory/migrations/schema-introspection.ts +14 -0
- package/src/memory/migrations/validate-migration-state.ts +50 -145
- package/src/memory/prompt-override.ts +129 -0
- package/src/memory/raw-query.ts +47 -2
- package/src/memory/skill-loaded-events-store.test.ts +1 -1
- package/src/memory/task-memory-cleanup.ts +62 -41
- package/src/memory/tool-executed-events-store.test.ts +1 -1
- package/src/memory/turn-trace-store.test.ts +1 -1
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +16 -15
- package/src/memory/v2/__tests__/cli-command-store.test.ts +25 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +1 -1
- package/src/memory/v2/__tests__/harness-oracle.test.ts +1 -1
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
- package/src/memory/v2/__tests__/skill-store.test.ts +80 -0
- package/src/memory/v2/__tests__/sweep-job.test.ts +2 -2
- package/src/memory/v2/cli-command-store.ts +75 -38
- package/src/memory/v2/prompts/consolidation.ts +13 -82
- package/src/memory/v2/prompts/router.ts +21 -93
- package/src/memory/v2/skill-store.ts +68 -31
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +38 -0
- package/src/memory/v3-eval/__tests__/eval-tally.test.ts +139 -0
- package/src/memory/v3-eval/eval-packets.ts +197 -12
- package/src/memory/v3-eval/eval-tally.ts +234 -0
- package/src/memory/worker-control.ts +118 -0
- package/src/memory/worker-process.ts +72 -0
- package/src/messaging/provider.ts +10 -0
- package/src/messaging/providers/gmail/adapter.ts +1 -0
- package/src/messaging/providers/gmail/client.ts +13 -0
- package/src/messaging/providers/index.ts +1 -1
- package/src/messaging/providers/slack/send.test.ts +87 -39
- package/src/messaging/providers/slack/send.ts +84 -105
- package/src/notifications/README.md +9 -5
- package/src/notifications/__tests__/broadcaster.test.ts +16 -8
- package/src/notifications/__tests__/connected-channels.test.ts +114 -0
- package/src/notifications/__tests__/decision-engine.test.ts +78 -9
- package/src/notifications/__tests__/destination-resolver.test.ts +256 -0
- package/src/notifications/__tests__/deterministic-checks.test.ts +43 -1
- package/src/notifications/adapters/slack.ts +12 -10
- package/src/notifications/approval-card-builder.ts +81 -20
- package/src/notifications/approval-card-data.ts +8 -5
- package/src/notifications/broadcaster.ts +8 -1
- package/src/notifications/canonical-delivery-recorder.ts +7 -5
- package/src/notifications/conversation-candidates.ts +24 -59
- package/src/notifications/copy-composer.ts +48 -68
- package/src/notifications/decision-engine.ts +15 -7
- package/src/notifications/destination-resolver.ts +68 -24
- package/src/notifications/deterministic-checks.ts +19 -16
- package/src/notifications/emit-signal.ts +68 -15
- package/src/notifications/trusted-contact-payloads.ts +70 -0
- package/src/oauth/byo-connection.test.ts +9 -0
- package/src/oauth/connection-resolver.test.ts +174 -6
- package/src/oauth/connection-resolver.ts +132 -5
- package/src/oauth/oauth-store.ts +16 -3
- package/src/oauth/scope-utils.ts +39 -0
- package/src/permissions/question-prompter.test.ts +1 -1
- package/src/permissions/question-prompter.ts +7 -4
- package/src/plugin-api/index.ts +9 -4
- package/src/plugin-api/model-profiles.test.ts +123 -0
- package/src/plugin-api/model-profiles.ts +5 -1
- package/src/plugin-api/vision-support.test.ts +173 -0
- package/src/plugin-api/vision-support.ts +113 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +90 -0
- package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +106 -0
- package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +60 -0
- package/src/plugins/defaults/advisor/consult.ts +65 -6
- package/src/plugins/defaults/advisor/context-pack.ts +288 -0
- package/src/plugins/defaults/advisor/steering.ts +14 -2
- package/src/plugins/defaults/advisor/tools/advisor.ts +32 -5
- package/src/plugins/defaults/compaction/window-manager.ts +45 -64
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +13 -4
- package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +441 -0
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +57 -0
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +61 -0
- package/src/plugins/defaults/image-fallback/package.json +14 -0
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +108 -0
- package/src/plugins/defaults/image-fallback/src/caption-cache.ts +49 -0
- package/src/plugins/defaults/image-fallback/src/image-persist.ts +56 -0
- package/src/plugins/defaults/image-fallback/src/vision-caption.ts +120 -0
- package/src/plugins/defaults/index.ts +27 -0
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +14 -1
- package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +134 -5
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
- package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
- package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +246 -19
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +8 -1
- package/src/plugins/external-plugin-loader.ts +47 -6
- package/src/plugins/mtime-cache.ts +772 -0
- package/src/plugins/pipeline.ts +7 -2
- package/src/plugins/registry.ts +16 -5
- package/src/plugins/user-loader.ts +22 -76
- package/src/prompts/persona-resolver.ts +29 -11
- package/src/prompts/system-prompt.ts +1 -1
- package/src/prompts/templates/system-sections.ts +4 -4
- package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
- package/src/providers/anthropic/client.ts +290 -185
- package/src/providers/call-site-routing.ts +14 -0
- package/src/providers/gemini/client.ts +43 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/connections.ts +6 -1
- package/src/providers/model-catalog.ts +53 -0
- package/src/providers/openai/responses-provider.ts +5 -0
- package/src/providers/openrouter/client.ts +5 -0
- package/src/providers/platform-proxy/constants.ts +5 -0
- package/src/providers/provider-send-message.ts +4 -0
- package/src/providers/ratelimit.ts +13 -0
- package/src/providers/retry.ts +14 -0
- package/src/providers/together/client.ts +35 -0
- package/src/providers/types.ts +25 -0
- package/src/providers/usage-tracking.ts +11 -0
- package/src/runtime/AGENTS.md +9 -1
- package/src/runtime/__tests__/agent-wake.test.ts +259 -4
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +181 -0
- package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +64 -0
- package/src/runtime/__tests__/local-principal-trust.test.ts +164 -0
- package/src/runtime/__tests__/slack-block-formatting.test.ts +39 -10
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +670 -0
- package/src/runtime/access-request-helper.ts +19 -39
- package/src/runtime/actor-trust-resolver.ts +8 -16
- package/src/runtime/agent-wake.ts +183 -60
- package/src/runtime/anchored-guardian.test.ts +156 -0
- package/src/runtime/anchored-guardian.ts +135 -0
- package/src/runtime/assistant-stream-state.ts +9 -2
- package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
- package/src/runtime/auth/require-bound-guardian.ts +21 -11
- package/src/runtime/channel-reply-delivery.ts +6 -3
- package/src/runtime/channel-verification-service.ts +24 -0
- package/src/runtime/guardian-decision-types.ts +3 -22
- package/src/runtime/guardian-vellum-migration.ts +66 -7
- package/src/runtime/http-server.ts +1 -15
- package/src/runtime/invite-redemption-service.ts +155 -6
- package/src/runtime/invite-service.ts +113 -62
- package/src/runtime/local-actor-identity.ts +76 -11
- package/src/runtime/local-principal-trust.ts +52 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +3 -0
- package/src/runtime/pending-interactions.ts +11 -1
- package/src/runtime/routes/__tests__/acp-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +277 -0
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +140 -0
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +26 -7
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +14 -10
- package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +164 -0
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +8 -8
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +1 -3
- package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +240 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +4 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +143 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +163 -0
- package/src/runtime/routes/acp-routes-list.test.ts +4 -0
- package/src/runtime/routes/acp-routes.test.ts +5 -6
- package/src/runtime/routes/attachment-routes.ts +21 -17
- package/src/runtime/routes/browser-routes.ts +19 -1
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -9
- package/src/runtime/routes/channel-verification-routes.ts +13 -2
- package/src/runtime/routes/contact-routes.ts +275 -164
- package/src/runtime/routes/conversation-query-routes.ts +15 -5
- package/src/runtime/routes/conversation-routes.ts +80 -66
- package/src/runtime/routes/conversation-starter-routes.ts +7 -8
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/guardian-approval-interception.ts +13 -274
- package/src/runtime/routes/host-app-control-routes.ts +5 -4
- package/src/runtime/routes/host-bash-routes.ts +5 -4
- package/src/runtime/routes/host-browser-routes.ts +9 -11
- package/src/runtime/routes/host-cu-routes.ts +5 -4
- package/src/runtime/routes/host-file-routes.ts +5 -4
- package/src/runtime/routes/host-transfer-routes.ts +6 -6
- package/src/runtime/routes/http-adapter.ts +1 -1
- package/src/runtime/routes/inbound-message-handler.ts +21 -16
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +376 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +86 -64
- package/src/runtime/routes/inbound-stages/admission-policy.ts +20 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +16 -4
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
- package/src/runtime/routes/llm-context-normalization.ts +71 -0
- package/src/runtime/routes/log-export-routes.ts +2 -2
- package/src/runtime/routes/mcp-auth-routes.ts +38 -15
- package/src/runtime/routes/memory-eval-routes.ts +92 -0
- package/src/runtime/routes/memory-item-routes.test.ts +12 -11
- package/src/runtime/routes/migration-routes.ts +51 -40
- package/src/runtime/routes/plugins-routes.ts +164 -8
- package/src/runtime/routes/schedule-routes.ts +1 -0
- package/src/runtime/routes/subagents-routes.ts +5 -0
- package/src/runtime/routes/surface-action-routes.ts +39 -51
- package/src/runtime/routes/usage-routes.ts +3 -0
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/slack-block-formatting.ts +46 -48
- package/src/runtime/trust-verdict-consumer.ts +210 -0
- package/src/schedule/scheduler.ts +6 -9
- package/src/signals/user-message.ts +16 -0
- package/src/subagent/manager.ts +9 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +89 -52
- package/src/tools/ask-question/ask-question-tool.ts +27 -73
- package/src/tools/browser/__tests__/browser-status.test.ts +20 -0
- package/src/tools/browser/browser-execution.ts +16 -4
- package/src/tools/document/document-comment-tool.test.ts +1 -1
- package/src/tools/executor.ts +15 -3
- package/src/tools/host-terminal/host-shell.ts +28 -9
- package/src/tools/memory/register.test.ts +32 -0
- package/src/tools/skills/load.ts +43 -2
- package/src/tools/subagent/spawn.ts +4 -10
- package/src/tools/terminal/shell.ts +16 -5
- package/src/tools/tool-defaults.ts +2 -0
- package/src/tools/types.ts +18 -2
- package/src/tools/ui-surface/definitions.ts +0 -43
- package/src/util/fs-watcher-error.ts +36 -0
- package/src/util/log-redact.ts +2 -4
- package/src/util/logs-db-path.ts +22 -0
- package/src/util/memory-db-path.ts +23 -0
- package/src/util/platform.ts +5 -0
- package/src/watcher/providers/gmail.ts +7 -2
- package/src/workflows/engine-integration.test.ts +1 -1
- package/src/workflows/engine.test.ts +1 -1
- package/src/workflows/engine.ts +22 -0
- package/src/workflows/fanout-load.test.ts +1 -1
- package/src/workflows/journal-store.test.ts +1 -1
- package/src/workflows/leaf-runner.test.ts +40 -1
- package/src/workflows/leaf-runner.ts +26 -1
- package/src/workspace/git-service.ts +144 -29
- package/src/workspace/migrations/109-swap-quality-profile-to-glm-5p2.ts +121 -0
- package/src/workspace/migrations/110-flip-balanced-profile-to-together.ts +82 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/workspace/migrations/runner.ts +32 -2
- package/src/__tests__/access-request-decision.test.ts +0 -375
- package/src/__tests__/guardian-grant-minting.test.ts +0 -607
- package/src/__tests__/plugin-source-watcher.test.ts +0 -302
- package/src/api/events/turn-profile-auto-routed.ts +0 -28
- package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +0 -107
- package/src/daemon/plugin-source-watcher.ts +0 -278
- package/src/daemon/switch-inference-profile-tool.ts +0 -62
- package/src/memory/guardian-approvals.ts +0 -361
- package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +0 -66
- package/src/memory/migrations/038-actor-token-records.ts +0 -45
- package/src/memory/migrations/039-actor-refresh-token-records.ts +0 -57
- package/src/memory/migrations/103-complex-migrations.ts +0 -23
- package/src/memory/migrations/113-late-migrations.ts +0 -30
- package/src/memory/migrations/index.ts +0 -301
- package/src/runtime/routes/access-request-decision.ts +0 -297
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +0 -963
- package/src/runtime/routes/channel-guardian-routes.ts +0 -19
- package/src/runtime/routes/guardian-expiry-sweep.ts +0 -132
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
import type { ChannelId } from "../channels/types.js";
|
|
15
15
|
import { isHttpAuthDisabled } from "../config/env.js";
|
|
16
16
|
import { findGuardianForChannel } from "../contacts/contact-store.js";
|
|
17
|
+
import {
|
|
18
|
+
getGuardianDelivery,
|
|
19
|
+
guardianForChannel,
|
|
20
|
+
peekCachedGuardianDelivery,
|
|
21
|
+
} from "../contacts/guardian-delivery-reader.js";
|
|
17
22
|
import type { TrustContext } from "../daemon/trust-context.js";
|
|
18
23
|
import { getLogger } from "../util/logger.js";
|
|
19
24
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "./assistant-scope.js";
|
|
@@ -45,13 +50,48 @@ export function buildLocalAuthContext(conversationId: string): AuthContext {
|
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
/**
|
|
48
|
-
*
|
|
53
|
+
* Resolve the local vellum guardian's principalId from the gateway.
|
|
49
54
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
55
|
+
* The gateway owns guardian binding; this reads it through the cached
|
|
56
|
+
* `getGuardianDelivery` reader (PR-3 TTL + single-flight) so hot paths don't
|
|
57
|
+
* storm the IPC. Falls back to the local contacts table for the bootstrap /
|
|
58
|
+
* first-run window where the gateway has no guardian yet or is unreachable
|
|
59
|
+
* (the reader returns `null`).
|
|
60
|
+
*
|
|
61
|
+
* Returns `undefined` when no vellum guardian binding exists in either source
|
|
62
|
+
* (e.g. fresh install before bootstrap). Callers should treat that case as
|
|
52
63
|
* "not yet available" and either fall back or proceed without a principalId.
|
|
53
64
|
*/
|
|
54
|
-
export function findLocalGuardianPrincipalId():
|
|
65
|
+
export async function findLocalGuardianPrincipalId(): Promise<
|
|
66
|
+
string | undefined
|
|
67
|
+
> {
|
|
68
|
+
const list = await getGuardianDelivery({ channelTypes: ["vellum"] });
|
|
69
|
+
if (list) {
|
|
70
|
+
const principalId = guardianForChannel(list, "vellum")?.principalId;
|
|
71
|
+
if (principalId) return principalId;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return findLocalGuardianPrincipalIdFromStore();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Synchronous read of the vellum guardian's principalId for paths that cannot
|
|
79
|
+
* await {@link findLocalGuardianPrincipalId} — namely the SSE eager-subscribe
|
|
80
|
+
* path (`events-routes`), which registers before the stream is created.
|
|
81
|
+
*
|
|
82
|
+
* Reads the same gateway-owned binding as the async path via a sync, IO-free
|
|
83
|
+
* snapshot of the guardian-delivery cache (kept fresh by the async hot paths
|
|
84
|
+
* and event-driven invalidation), so SSE registers the SAME principal the
|
|
85
|
+
* send/result routes resolve. Falls back to the local store when the cache is
|
|
86
|
+
* cold — the same fallback the async path lands on during bootstrap.
|
|
87
|
+
*/
|
|
88
|
+
export function findLocalGuardianPrincipalIdFromStore(): string | undefined {
|
|
89
|
+
const cached = peekCachedGuardianDelivery({ channelTypes: ["vellum"] });
|
|
90
|
+
if (cached) {
|
|
91
|
+
const principalId = guardianForChannel(cached, "vellum")?.principalId;
|
|
92
|
+
if (principalId) return principalId;
|
|
93
|
+
}
|
|
94
|
+
|
|
55
95
|
return findGuardianForChannel("vellum")?.contact.principalId ?? undefined;
|
|
56
96
|
}
|
|
57
97
|
|
|
@@ -76,12 +116,35 @@ export function findLocalGuardianPrincipalId(): string | undefined {
|
|
|
76
116
|
* yet (e.g. fresh install before bootstrap); callers must treat this the
|
|
77
117
|
* same as a missing principal.
|
|
78
118
|
*/
|
|
79
|
-
export function resolveActorPrincipalIdForLocalGuardian(
|
|
119
|
+
export async function resolveActorPrincipalIdForLocalGuardian(
|
|
120
|
+
rawHeader: string | undefined,
|
|
121
|
+
): Promise<string | undefined> {
|
|
122
|
+
if (rawHeader !== "dev-bypass" || !isHttpAuthDisabled()) return rawHeader;
|
|
123
|
+
|
|
124
|
+
const guardianPrincipalId = await findLocalGuardianPrincipalId();
|
|
125
|
+
if (guardianPrincipalId) return guardianPrincipalId;
|
|
126
|
+
|
|
127
|
+
log.warn(
|
|
128
|
+
"dev-bypass actor principal received but no vellum guardian binding found; returning undefined",
|
|
129
|
+
);
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Synchronous variant of {@link resolveActorPrincipalIdForLocalGuardian} for
|
|
135
|
+
* the SSE eager-subscribe path, which registers before the response stream is
|
|
136
|
+
* created and cannot await. Resolves the guardian from the IO-free gateway
|
|
137
|
+
* cache snapshot first (same source the async path reads), falling back to the
|
|
138
|
+
* local store when the cache is cold — so SSE registers the SAME principal the
|
|
139
|
+
* send/result routes resolve and host-proxy targeting matches the same-user
|
|
140
|
+
* client even when the local contact row is stale.
|
|
141
|
+
*/
|
|
142
|
+
export function resolveActorPrincipalIdForLocalGuardianSync(
|
|
80
143
|
rawHeader: string | undefined,
|
|
81
144
|
): string | undefined {
|
|
82
145
|
if (rawHeader !== "dev-bypass" || !isHttpAuthDisabled()) return rawHeader;
|
|
83
146
|
|
|
84
|
-
const guardianPrincipalId =
|
|
147
|
+
const guardianPrincipalId = findLocalGuardianPrincipalIdFromStore();
|
|
85
148
|
if (guardianPrincipalId) return guardianPrincipalId;
|
|
86
149
|
|
|
87
150
|
log.warn(
|
|
@@ -102,12 +165,12 @@ export function resolveActorPrincipalIdForLocalGuardian(
|
|
|
102
165
|
* bootstrap), falls back to a minimal guardian context so the local
|
|
103
166
|
* user is not incorrectly denied.
|
|
104
167
|
*/
|
|
105
|
-
export function resolveLocalTrustContext(
|
|
168
|
+
export async function resolveLocalTrustContext(
|
|
106
169
|
sourceChannel: ChannelId = "vellum",
|
|
107
|
-
): TrustContext {
|
|
170
|
+
): Promise<TrustContext> {
|
|
108
171
|
const assistantId = DAEMON_INTERNAL_ASSISTANT_ID;
|
|
109
172
|
|
|
110
|
-
const guardianPrincipalId = findLocalGuardianPrincipalId();
|
|
173
|
+
const guardianPrincipalId = await findLocalGuardianPrincipalId();
|
|
111
174
|
if (guardianPrincipalId) {
|
|
112
175
|
const trustCtx = resolveTrustContext({
|
|
113
176
|
assistantId,
|
|
@@ -139,10 +202,12 @@ export function resolveLocalTrustContext(
|
|
|
139
202
|
* downstream code to resolve guardian context using the same
|
|
140
203
|
* `authContext.actorPrincipalId` path as HTTP sessions.
|
|
141
204
|
*/
|
|
142
|
-
export function resolveLocalAuthContext(
|
|
205
|
+
export async function resolveLocalAuthContext(
|
|
206
|
+
conversationId: string,
|
|
207
|
+
): Promise<AuthContext> {
|
|
143
208
|
const authContext = buildLocalAuthContext(conversationId);
|
|
144
209
|
|
|
145
|
-
const guardianPrincipalId = findLocalGuardianPrincipalId();
|
|
210
|
+
const guardianPrincipalId = await findLocalGuardianPrincipalId();
|
|
146
211
|
if (guardianPrincipalId) {
|
|
147
212
|
return { ...authContext, actorPrincipalId: guardianPrincipalId };
|
|
148
213
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derives a local principal's {@link TrustContext} from the gateway guardian
|
|
3
|
+
* binding. Fails closed to unknown on a missing or null read.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ChannelId } from "../channels/types.js";
|
|
7
|
+
import { getGuardianDelivery } from "../contacts/guardian-delivery-reader.js";
|
|
8
|
+
import type { TrustContext } from "../daemon/trust-context.js";
|
|
9
|
+
import { canonicalizeInboundIdentity } from "../util/canonicalize-identity.js";
|
|
10
|
+
|
|
11
|
+
export interface ResolveLocalPrincipalTrustInput {
|
|
12
|
+
actorPrincipalId: string;
|
|
13
|
+
sourceChannel: ChannelId;
|
|
14
|
+
conversationExternalId: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Guardian match → guardian ctx; miss or null read → unknown (fail closed). */
|
|
18
|
+
export async function resolveLocalPrincipalTrustContext(
|
|
19
|
+
input: ResolveLocalPrincipalTrustInput,
|
|
20
|
+
): Promise<TrustContext> {
|
|
21
|
+
const unknownContext: TrustContext = {
|
|
22
|
+
sourceChannel: input.sourceChannel,
|
|
23
|
+
trustClass: "unknown",
|
|
24
|
+
requesterExternalUserId: input.actorPrincipalId,
|
|
25
|
+
requesterChatId: input.conversationExternalId,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Fail closed: a null read means the gateway is unreachable — never grant
|
|
29
|
+
// guardian on a miss.
|
|
30
|
+
const guardians = await getGuardianDelivery({ channelTypes: ["vellum"] });
|
|
31
|
+
if (!guardians) return unknownContext;
|
|
32
|
+
|
|
33
|
+
const guardian = guardians.find(
|
|
34
|
+
(g) => g.principalId === input.actorPrincipalId,
|
|
35
|
+
);
|
|
36
|
+
if (!guardian) return unknownContext;
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
sourceChannel: input.sourceChannel,
|
|
40
|
+
trustClass: "guardian",
|
|
41
|
+
guardianChatId: guardian.externalChatId ?? input.conversationExternalId,
|
|
42
|
+
guardianExternalUserId:
|
|
43
|
+
canonicalizeInboundIdentity(input.sourceChannel, guardian.address) ??
|
|
44
|
+
undefined,
|
|
45
|
+
guardianPrincipalId: guardian.principalId ?? undefined,
|
|
46
|
+
// Mirror toTrustContext: with no username the requester identifier is the
|
|
47
|
+
// canonical sender id, which for a vellum principal is actorPrincipalId.
|
|
48
|
+
requesterIdentifier: input.actorPrincipalId,
|
|
49
|
+
requesterExternalUserId: input.actorPrincipalId,
|
|
50
|
+
requesterChatId: input.conversationExternalId,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -119,5 +119,8 @@ describe("streamExportVBundle — descriptor lifecycle", () => {
|
|
|
119
119
|
// incidental descriptors (temp output file already cleaned up, jitter).
|
|
120
120
|
expect(delta).toBeLessThan(8);
|
|
121
121
|
},
|
|
122
|
+
// Two full exports of a multi-megabyte workspace (hash pass + tar pass each)
|
|
123
|
+
// do real disk I/O; the default 5s budget is tight under loaded CI runners.
|
|
124
|
+
30_000,
|
|
122
125
|
);
|
|
123
126
|
});
|
|
@@ -229,6 +229,15 @@ export function getByConversation(
|
|
|
229
229
|
* /v1/host-browser-result, /v1/host-app-control-result, or
|
|
230
230
|
* /v1/host-transfer-result after completing the operation, get a 404, and the
|
|
231
231
|
* proxy timer would fire with a spurious timeout error.
|
|
232
|
+
*
|
|
233
|
+
* `question` interactions are also skipped: a new message supersedes an open
|
|
234
|
+
* ask_question by steering to it (see the enqueue path in
|
|
235
|
+
* conversation-routes.ts), which aborts the parked turn and settles the
|
|
236
|
+
* question via its abort signal. Clearing the entry here instead would drop it
|
|
237
|
+
* without settling the prompt's Promise (questions carry no `rpcResolve`
|
|
238
|
+
* fallback like secrets do) and would strip the steer of the entry it needs to
|
|
239
|
+
* fire — which can co-occur with a confirmation, since one model response can
|
|
240
|
+
* open both tools concurrently.
|
|
232
241
|
*/
|
|
233
242
|
export function removeByConversation(
|
|
234
243
|
conversationId: string,
|
|
@@ -244,7 +253,8 @@ export function removeByConversation(
|
|
|
244
253
|
interaction.kind !== "host_browser" &&
|
|
245
254
|
interaction.kind !== "host_app_control" &&
|
|
246
255
|
interaction.kind !== "host_transfer" &&
|
|
247
|
-
interaction.kind !== "acp_confirmation"
|
|
256
|
+
interaction.kind !== "acp_confirmation" &&
|
|
257
|
+
interaction.kind !== "question"
|
|
248
258
|
) {
|
|
249
259
|
// resolve() clears the stored timer and detaches abort listeners.
|
|
250
260
|
resolve(requestId, state);
|
|
@@ -39,7 +39,7 @@ import type { RouteDefinition, RouteHandlerArgs } from "../types.js";
|
|
|
39
39
|
// DB bootstrap
|
|
40
40
|
// ---------------------------------------------------------------------------
|
|
41
41
|
|
|
42
|
-
initializeDb();
|
|
42
|
+
await initializeDb();
|
|
43
43
|
|
|
44
44
|
// ---------------------------------------------------------------------------
|
|
45
45
|
// Helpers
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the verification-revoke route relay.
|
|
3
|
+
*
|
|
4
|
+
* The revoke route downgrades the channel's ACL status through the gateway
|
|
5
|
+
* (source of truth) via `ipcCallPersistent("mark_channel_revoked", ...)` while
|
|
6
|
+
* keeping session teardown (`cancelOutbound`, `revokePendingSessions`)
|
|
7
|
+
* assistant-side. The gateway enforces the guardian guard; a rejected guardian
|
|
8
|
+
* downgrade surfaces here as a relayed IpcCallError.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
|
+
|
|
13
|
+
import { IpcCallError } from "@vellumai/gateway-client/ipc-client";
|
|
14
|
+
|
|
15
|
+
type IpcCall = { method: string; params?: Record<string, unknown> };
|
|
16
|
+
|
|
17
|
+
let ipcCalls: IpcCall[] = [];
|
|
18
|
+
let ipcError: Error | undefined;
|
|
19
|
+
|
|
20
|
+
const ipcCallPersistentMock = mock(
|
|
21
|
+
async (method: string, params?: Record<string, unknown>) => {
|
|
22
|
+
ipcCalls.push({ method, params });
|
|
23
|
+
if (ipcError) throw ipcError;
|
|
24
|
+
return {
|
|
25
|
+
ok: true,
|
|
26
|
+
didWrite: true,
|
|
27
|
+
channel: {
|
|
28
|
+
id: (params?.contactChannelId as string) ?? "ch1",
|
|
29
|
+
contactId: "c1",
|
|
30
|
+
type: "telegram",
|
|
31
|
+
address: "addr",
|
|
32
|
+
status: "revoked",
|
|
33
|
+
revokedReason: (params?.reason as string) ?? null,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const actualGatewayClient = await import("../../../ipc/gateway-client.js");
|
|
40
|
+
mock.module("../../../ipc/gateway-client.js", () => ({
|
|
41
|
+
...actualGatewayClient,
|
|
42
|
+
ipcCallPersistent: ipcCallPersistentMock,
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
// Session teardown — assert these still run locally on every revoke.
|
|
46
|
+
const cancelOutboundMock = mock((_args: { channel: string }) => {});
|
|
47
|
+
const actualOutboundActions = await import(
|
|
48
|
+
"../../verification-outbound-actions.js"
|
|
49
|
+
);
|
|
50
|
+
mock.module("../../verification-outbound-actions.js", () => ({
|
|
51
|
+
...actualOutboundActions,
|
|
52
|
+
cancelOutbound: cancelOutboundMock,
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
const revokePendingSessionsMock = mock((_channel: string) => {});
|
|
56
|
+
const revokeBindingMock = mock((_assistantId: string, _channel: string) => {
|
|
57
|
+
revokeGuardianBindingMock();
|
|
58
|
+
return true;
|
|
59
|
+
});
|
|
60
|
+
let guardianBinding:
|
|
61
|
+
| {
|
|
62
|
+
guardianExternalUserId: string;
|
|
63
|
+
guardianDeliveryChatId?: string;
|
|
64
|
+
}
|
|
65
|
+
| null = null;
|
|
66
|
+
const actualVerificationService = await import(
|
|
67
|
+
"../../channel-verification-service.js"
|
|
68
|
+
);
|
|
69
|
+
mock.module("../../channel-verification-service.js", () => ({
|
|
70
|
+
...actualVerificationService,
|
|
71
|
+
revokePendingSessions: revokePendingSessionsMock,
|
|
72
|
+
revokeBinding: revokeBindingMock,
|
|
73
|
+
getGuardianBinding: mock(() => guardianBinding),
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
// Contact-store lookup that resolves the guardian's channel to downgrade.
|
|
77
|
+
let contactChannel: { id: string; status: string } | null = null;
|
|
78
|
+
const actualContactStore = await import("../../../contacts/contact-store.js");
|
|
79
|
+
mock.module("../../../contacts/contact-store.js", () => ({
|
|
80
|
+
...actualContactStore,
|
|
81
|
+
findContactChannel: mock(() =>
|
|
82
|
+
contactChannel ? { channel: contactChannel, contact: { id: "c1" } } : null,
|
|
83
|
+
),
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
// Guard: the contact-channel ACL write moves to the gateway relay and must
|
|
87
|
+
// never run locally. The assistant-owned guardian-binding teardown
|
|
88
|
+
// (revokeGuardianBinding) still runs locally — assert it is invoked.
|
|
89
|
+
const localAclWrite = mock(() => {
|
|
90
|
+
throw new Error("local ACL write must not happen on relayed revoke");
|
|
91
|
+
});
|
|
92
|
+
const revokeGuardianBindingMock = mock(() => true);
|
|
93
|
+
const actualContactsWrite = await import("../../../contacts/contacts-write.js");
|
|
94
|
+
mock.module("../../../contacts/contacts-write.js", () => ({
|
|
95
|
+
...actualContactsWrite,
|
|
96
|
+
revokeMember: localAclWrite,
|
|
97
|
+
revokeGuardianBinding: revokeGuardianBindingMock,
|
|
98
|
+
}));
|
|
99
|
+
|
|
100
|
+
// Contact-change invalidation — emitted explicitly on relay success so open
|
|
101
|
+
// client views stop showing the channel as active (the gateway dual-write to
|
|
102
|
+
// "revoked" precedes binding teardown, so revokeGuardianBinding no longer
|
|
103
|
+
// fires it).
|
|
104
|
+
const emitContactChangeMock = mock(() => {});
|
|
105
|
+
const actualContactEvents = await import("../../../contacts/contact-events.js");
|
|
106
|
+
mock.module("../../../contacts/contact-events.js", () => ({
|
|
107
|
+
...actualContactEvents,
|
|
108
|
+
emitContactChange: emitContactChangeMock,
|
|
109
|
+
}));
|
|
110
|
+
|
|
111
|
+
const { ROUTES } = await import("../channel-verification-routes.js");
|
|
112
|
+
|
|
113
|
+
const revokeHandler = ROUTES.find(
|
|
114
|
+
(r) => r.operationId === "channel_verification_sessions_revoke",
|
|
115
|
+
)!.handler;
|
|
116
|
+
|
|
117
|
+
describe("verification revoke relay", () => {
|
|
118
|
+
beforeEach(() => {
|
|
119
|
+
ipcCalls = [];
|
|
120
|
+
ipcError = undefined;
|
|
121
|
+
guardianBinding = {
|
|
122
|
+
guardianExternalUserId: "guardian-user",
|
|
123
|
+
guardianDeliveryChatId: "chat-1",
|
|
124
|
+
};
|
|
125
|
+
contactChannel = { id: "ch1", status: "active" };
|
|
126
|
+
ipcCallPersistentMock.mockClear();
|
|
127
|
+
cancelOutboundMock.mockClear();
|
|
128
|
+
revokePendingSessionsMock.mockClear();
|
|
129
|
+
revokeBindingMock.mockClear();
|
|
130
|
+
revokeGuardianBindingMock.mockClear();
|
|
131
|
+
localAclWrite.mockClear();
|
|
132
|
+
emitContactChangeMock.mockClear();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("relays the downgrade outcome to the gateway and tears down sessions locally", async () => {
|
|
136
|
+
const result = (await revokeHandler({
|
|
137
|
+
body: { channel: "telegram" },
|
|
138
|
+
})) as { success: boolean; bound: boolean; channel: string };
|
|
139
|
+
|
|
140
|
+
// ACL downgrade relayed to the gateway (source of truth).
|
|
141
|
+
expect(ipcCalls).toEqual([
|
|
142
|
+
{
|
|
143
|
+
method: "mark_channel_revoked",
|
|
144
|
+
params: {
|
|
145
|
+
contactChannelId: "ch1",
|
|
146
|
+
reason: "guardian_binding_revoked",
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
]);
|
|
150
|
+
|
|
151
|
+
// Session teardown stays assistant-side.
|
|
152
|
+
expect(cancelOutboundMock).toHaveBeenCalledTimes(1);
|
|
153
|
+
expect(revokePendingSessionsMock).toHaveBeenCalledTimes(1);
|
|
154
|
+
|
|
155
|
+
// Assistant-owned guardian binding torn down locally.
|
|
156
|
+
expect(revokeBindingMock).toHaveBeenCalledTimes(1);
|
|
157
|
+
expect(revokeGuardianBindingMock).toHaveBeenCalledTimes(1);
|
|
158
|
+
|
|
159
|
+
// The contact-channel ACL write does not fall back to the assistant.
|
|
160
|
+
expect(localAclWrite).not.toHaveBeenCalled();
|
|
161
|
+
|
|
162
|
+
// Invalidation emitted explicitly on relay success: the gateway dual-write
|
|
163
|
+
// to "revoked" precedes binding teardown, so revokeGuardianBinding's own
|
|
164
|
+
// emit no longer fires.
|
|
165
|
+
expect(emitContactChangeMock).toHaveBeenCalledTimes(1);
|
|
166
|
+
|
|
167
|
+
expect(result.success).toBe(true);
|
|
168
|
+
expect(result.bound).toBe(false);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test("emits the invalidation even when the gateway dual-write already revoked the channel", async () => {
|
|
172
|
+
// Simulate the gateway having dual-written the assistant row to "revoked"
|
|
173
|
+
// before binding teardown: findGuardianForChannel (active-only) now finds
|
|
174
|
+
// nothing, so revokeGuardianBinding is a no-op and never emits.
|
|
175
|
+
revokeGuardianBindingMock.mockImplementationOnce(() => false);
|
|
176
|
+
|
|
177
|
+
await revokeHandler({ body: { channel: "telegram" } });
|
|
178
|
+
|
|
179
|
+
expect(ipcCalls).toHaveLength(1);
|
|
180
|
+
expect(emitContactChangeMock).toHaveBeenCalledTimes(1);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test("malformed gateway response surfaces as an error", async () => {
|
|
184
|
+
// Deliberately malformed shape: must fail schema validation, not pass.
|
|
185
|
+
ipcCallPersistentMock.mockImplementationOnce(
|
|
186
|
+
async () => ({ ok: "nope" }) as never,
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
let thrown: Error | undefined;
|
|
190
|
+
try {
|
|
191
|
+
await revokeHandler({ body: { channel: "telegram" } });
|
|
192
|
+
} catch (err) {
|
|
193
|
+
thrown = err as Error;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
expect(thrown).toBeDefined();
|
|
197
|
+
// Invalidation must not fire when the relay response is invalid.
|
|
198
|
+
expect(emitContactChangeMock).not.toHaveBeenCalled();
|
|
199
|
+
expect(revokeBindingMock).not.toHaveBeenCalled();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test("ok: false gateway response surfaces as an error", async () => {
|
|
203
|
+
ipcCallPersistentMock.mockImplementationOnce(async (_m, params) => ({
|
|
204
|
+
ok: false,
|
|
205
|
+
didWrite: false,
|
|
206
|
+
channel: {
|
|
207
|
+
id: (params?.contactChannelId as string) ?? "ch1",
|
|
208
|
+
contactId: "c1",
|
|
209
|
+
type: "telegram",
|
|
210
|
+
address: "addr",
|
|
211
|
+
status: "active",
|
|
212
|
+
revokedReason: "still_active",
|
|
213
|
+
},
|
|
214
|
+
}));
|
|
215
|
+
|
|
216
|
+
let thrown: Error | undefined;
|
|
217
|
+
try {
|
|
218
|
+
await revokeHandler({ body: { channel: "telegram" } });
|
|
219
|
+
} catch (err) {
|
|
220
|
+
thrown = err as Error;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
expect(thrown).toBeDefined();
|
|
224
|
+
expect(emitContactChangeMock).not.toHaveBeenCalled();
|
|
225
|
+
expect(revokeBindingMock).not.toHaveBeenCalled();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test("guardian guard rejection from the gateway surfaces as an error", async () => {
|
|
229
|
+
ipcError = new IpcCallError("Cannot downgrade a guardian channel.", {
|
|
230
|
+
statusCode: 409,
|
|
231
|
+
errorCode: "CONFLICT",
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
let thrown: { statusCode?: number; message: string } | undefined;
|
|
235
|
+
try {
|
|
236
|
+
await revokeHandler({ body: { channel: "telegram" } });
|
|
237
|
+
} catch (err) {
|
|
238
|
+
thrown = err as { statusCode?: number; message: string };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
expect(thrown).toBeDefined();
|
|
242
|
+
expect(thrown!.statusCode).toBe(409);
|
|
243
|
+
// Session teardown ran before the relay rejected; the binding teardown
|
|
244
|
+
// does not run when the gateway refuses the downgrade.
|
|
245
|
+
expect(cancelOutboundMock).toHaveBeenCalledTimes(1);
|
|
246
|
+
expect(revokePendingSessionsMock).toHaveBeenCalledTimes(1);
|
|
247
|
+
expect(revokeBindingMock).not.toHaveBeenCalled();
|
|
248
|
+
expect(localAclWrite).not.toHaveBeenCalled();
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test("no binding present: tears down sessions and skips the relay", async () => {
|
|
252
|
+
guardianBinding = null;
|
|
253
|
+
|
|
254
|
+
const result = (await revokeHandler({
|
|
255
|
+
body: { channel: "telegram" },
|
|
256
|
+
})) as { success: boolean; bound: boolean };
|
|
257
|
+
|
|
258
|
+
expect(ipcCalls).toEqual([]);
|
|
259
|
+
expect(cancelOutboundMock).toHaveBeenCalledTimes(1);
|
|
260
|
+
expect(revokePendingSessionsMock).toHaveBeenCalledTimes(1);
|
|
261
|
+
expect(revokeBindingMock).not.toHaveBeenCalled();
|
|
262
|
+
expect(result.success).toBe(true);
|
|
263
|
+
expect(result.bound).toBe(false);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
test("skips the relay when the resolved channel is already revoked", async () => {
|
|
267
|
+
contactChannel = { id: "ch1", status: "revoked" };
|
|
268
|
+
|
|
269
|
+
await revokeHandler({ body: { channel: "telegram" } });
|
|
270
|
+
|
|
271
|
+
expect(ipcCalls).toEqual([]);
|
|
272
|
+
expect(cancelOutboundMock).toHaveBeenCalledTimes(1);
|
|
273
|
+
expect(revokePendingSessionsMock).toHaveBeenCalledTimes(1);
|
|
274
|
+
// Binding teardown still runs even when the channel is already revoked.
|
|
275
|
+
expect(revokeBindingMock).toHaveBeenCalledTimes(1);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the trusted-contact branch of the channel-verification create
|
|
3
|
+
* route.
|
|
4
|
+
*
|
|
5
|
+
* Pins the invariant that the trusted-contact create path performs no
|
|
6
|
+
* assistant-side activation write (no `updateChannelStatus`): it only creates an
|
|
7
|
+
* outbound session and sends a code. The verified outcome flows exclusively
|
|
8
|
+
* through the inbound gateway code-match path, so it is never double-written.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
|
+
|
|
13
|
+
const verifyTrustedContactCalls: Array<[string, string]> = [];
|
|
14
|
+
let verifyTrustedContactImpl: (
|
|
15
|
+
contactChannelId: string,
|
|
16
|
+
assistantId: string,
|
|
17
|
+
) => Promise<Record<string, unknown>> = async () => ({ success: true });
|
|
18
|
+
|
|
19
|
+
const updateChannelStatusCalls: unknown[] = [];
|
|
20
|
+
const ipcCalls: Array<[string, unknown]> = [];
|
|
21
|
+
|
|
22
|
+
mock.module("../../../daemon/handlers/config-channels.js", () => ({
|
|
23
|
+
verifyTrustedContact: async (contactChannelId: string, assistantId: string) => {
|
|
24
|
+
verifyTrustedContactCalls.push([contactChannelId, assistantId]);
|
|
25
|
+
return verifyTrustedContactImpl(contactChannelId, assistantId);
|
|
26
|
+
},
|
|
27
|
+
createInboundChallenge: async () => ({ success: true }),
|
|
28
|
+
getVerificationStatus: () => ({ success: true }),
|
|
29
|
+
revokeVerificationForChannel: () => ({ success: true }),
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
mock.module("../../../contacts/contact-store.js", () => ({
|
|
33
|
+
updateChannelStatus: (...args: unknown[]) => {
|
|
34
|
+
updateChannelStatusCalls.push(args);
|
|
35
|
+
return null;
|
|
36
|
+
},
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
mock.module("../../ipc/gateway-client.js", () => ({
|
|
40
|
+
ipcCallPersistent: async (method: string, params: unknown) => {
|
|
41
|
+
ipcCalls.push([method, params]);
|
|
42
|
+
return { ok: true, didWrite: true, channel: {} };
|
|
43
|
+
},
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
import { handleCreateVerificationSession } from "../channel-verification-routes.js";
|
|
47
|
+
import { ConflictError, TooManyRequestsError } from "../errors.js";
|
|
48
|
+
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
verifyTrustedContactCalls.length = 0;
|
|
51
|
+
updateChannelStatusCalls.length = 0;
|
|
52
|
+
ipcCalls.length = 0;
|
|
53
|
+
verifyTrustedContactImpl = async () => ({ success: true });
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe("handleCreateVerificationSession — trusted_contact", () => {
|
|
57
|
+
test("sends the verification session without writing the activation outcome assistant-side", async () => {
|
|
58
|
+
verifyTrustedContactImpl = async () => ({
|
|
59
|
+
success: true,
|
|
60
|
+
verificationSessionId: "sess-1",
|
|
61
|
+
expiresAt: Date.now() + 600_000,
|
|
62
|
+
sendCount: 1,
|
|
63
|
+
channel: "phone",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const result = (await handleCreateVerificationSession({
|
|
67
|
+
body: { purpose: "trusted_contact", contactChannelId: "cc-1" },
|
|
68
|
+
})) as Record<string, unknown>;
|
|
69
|
+
|
|
70
|
+
expect(result.success).toBe(true);
|
|
71
|
+
expect(result.verificationSessionId).toBe("sess-1");
|
|
72
|
+
expect(verifyTrustedContactCalls).toEqual([["cc-1", expect.any(String)]]);
|
|
73
|
+
|
|
74
|
+
// No assistant-side activation outcome write on the create path — the
|
|
75
|
+
// outcome flows through the inbound gateway code-match path instead.
|
|
76
|
+
expect(updateChannelStatusCalls).toEqual([]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("does not double-write the outcome via the gateway relay on the create path", async () => {
|
|
80
|
+
verifyTrustedContactImpl = async () => ({
|
|
81
|
+
success: true,
|
|
82
|
+
verificationSessionId: "sess-2",
|
|
83
|
+
channel: "telegram",
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
await handleCreateVerificationSession({
|
|
87
|
+
body: { purpose: "trusted_contact", contactChannelId: "cc-2" },
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// The activation outcome is owned by the inbound gateway path; the create
|
|
91
|
+
// path must not relay a `mark_channel_verified` write (no double-write).
|
|
92
|
+
expect(
|
|
93
|
+
ipcCalls.filter(([method]) => method === "mark_channel_verified"),
|
|
94
|
+
).toEqual([]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("propagates an already-verified short-circuit as a ConflictError (no silent success)", async () => {
|
|
98
|
+
verifyTrustedContactImpl = async () => ({
|
|
99
|
+
success: false,
|
|
100
|
+
error: "already_verified",
|
|
101
|
+
message: "Channel is already verified",
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
await expect(
|
|
105
|
+
handleCreateVerificationSession({
|
|
106
|
+
body: { purpose: "trusted_contact", contactChannelId: "cc-3" },
|
|
107
|
+
}),
|
|
108
|
+
).rejects.toBeInstanceOf(ConflictError);
|
|
109
|
+
|
|
110
|
+
expect(updateChannelStatusCalls).toEqual([]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("propagates a rate-limit failure rather than silently succeeding", async () => {
|
|
114
|
+
verifyTrustedContactImpl = async () => ({
|
|
115
|
+
success: false,
|
|
116
|
+
error: "rate_limited",
|
|
117
|
+
message: "Too many attempts",
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
await expect(
|
|
121
|
+
handleCreateVerificationSession({
|
|
122
|
+
body: { purpose: "trusted_contact", contactChannelId: "cc-4" },
|
|
123
|
+
}),
|
|
124
|
+
).rejects.toBeInstanceOf(TooManyRequestsError);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("a failure in the trusted-contact path propagates, never a silent success", async () => {
|
|
128
|
+
verifyTrustedContactImpl = async () => {
|
|
129
|
+
throw new Error("gateway relay failed");
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
await expect(
|
|
133
|
+
handleCreateVerificationSession({
|
|
134
|
+
body: { purpose: "trusted_contact", contactChannelId: "cc-5" },
|
|
135
|
+
}),
|
|
136
|
+
).rejects.toThrow("gateway relay failed");
|
|
137
|
+
|
|
138
|
+
expect(updateChannelStatusCalls).toEqual([]);
|
|
139
|
+
});
|
|
140
|
+
});
|