@vellumai/assistant 0.4.16 → 0.4.18
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/Dockerfile +6 -6
- package/README.md +1 -2
- package/eslint.config.mjs +2 -2
- package/package.json +1 -1
- package/src/__tests__/access-request-decision.test.ts +128 -120
- package/src/__tests__/account-registry.test.ts +121 -110
- package/src/__tests__/active-skill-tools.test.ts +200 -172
- package/src/__tests__/actor-token-service.test.ts +341 -274
- package/src/__tests__/agent-loop-thinking.test.ts +28 -19
- package/src/__tests__/agent-loop.test.ts +798 -378
- package/src/__tests__/anthropic-provider.test.ts +405 -247
- package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
- package/src/__tests__/app-bundler.test.ts +112 -79
- package/src/__tests__/app-executors.test.ts +205 -178
- package/src/__tests__/app-git-history.test.ts +90 -73
- package/src/__tests__/app-git-service.test.ts +67 -53
- package/src/__tests__/app-open-proxy.test.ts +29 -25
- package/src/__tests__/approval-conversation-turn.test.ts +100 -81
- package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
- package/src/__tests__/approval-message-composer.test.ts +119 -119
- package/src/__tests__/approval-primitive.test.ts +264 -233
- package/src/__tests__/approval-routes-http.test.ts +4 -3
- package/src/__tests__/asset-materialize-tool.test.ts +250 -178
- package/src/__tests__/asset-search-tool.test.ts +251 -191
- package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
- package/src/__tests__/assistant-attachments.test.ts +254 -186
- package/src/__tests__/assistant-event-hub.test.ts +105 -63
- package/src/__tests__/assistant-event.test.ts +66 -58
- package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
- package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
- package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
- package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
- package/src/__tests__/attachments-store.test.ts +240 -183
- package/src/__tests__/attachments.test.ts +70 -62
- package/src/__tests__/audit-log-rotation.test.ts +50 -35
- package/src/__tests__/browser-fill-credential.test.ts +169 -101
- package/src/__tests__/browser-manager.test.ts +97 -75
- package/src/__tests__/browser-runtime-check.test.ts +16 -15
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
- package/src/__tests__/browser-skill-endstate.test.ts +97 -72
- package/src/__tests__/bundle-scanner.test.ts +47 -22
- package/src/__tests__/bundled-asset.test.ts +74 -47
- package/src/__tests__/call-constants.test.ts +19 -19
- package/src/__tests__/call-controller.test.ts +1073 -751
- package/src/__tests__/call-conversation-messages.test.ts +90 -65
- package/src/__tests__/call-domain.test.ts +149 -121
- package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
- package/src/__tests__/call-pointer-messages.test.ts +213 -154
- package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
- package/src/__tests__/call-recovery.test.ts +232 -212
- package/src/__tests__/call-routes-http.test.ts +328 -279
- package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
- package/src/__tests__/call-state-machine.test.ts +62 -51
- package/src/__tests__/call-state.test.ts +89 -75
- package/src/__tests__/call-store.test.ts +387 -316
- package/src/__tests__/callback-handoff-copy.test.ts +84 -82
- package/src/__tests__/canonical-guardian-store.test.ts +331 -280
- package/src/__tests__/channel-approval-routes.test.ts +1643 -1126
- package/src/__tests__/channel-approval.test.ts +139 -137
- package/src/__tests__/channel-approvals.test.ts +226 -182
- package/src/__tests__/channel-delivery-store.test.ts +232 -194
- package/src/__tests__/channel-guardian.test.ts +6 -3
- package/src/__tests__/channel-invite-transport.test.ts +107 -92
- package/src/__tests__/channel-policy.test.ts +42 -38
- package/src/__tests__/channel-readiness-service.test.ts +119 -102
- package/src/__tests__/channel-reply-delivery.test.ts +147 -118
- package/src/__tests__/channel-retry-sweep.test.ts +153 -110
- package/src/__tests__/checker.test.ts +3309 -1850
- package/src/__tests__/clarification-resolver.test.ts +91 -79
- package/src/__tests__/classifier.test.ts +64 -54
- package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
- package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
- package/src/__tests__/clawhub.test.ts +92 -82
- package/src/__tests__/cli.test.ts +30 -30
- package/src/__tests__/clipboard.test.ts +53 -46
- package/src/__tests__/commit-guarantee.test.ts +59 -52
- package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
- package/src/__tests__/compaction.benchmark.test.ts +33 -31
- package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
- package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
- package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
- package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
- package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
- package/src/__tests__/computer-use-tools.test.ts +121 -98
- package/src/__tests__/config-schema.test.ts +443 -347
- package/src/__tests__/config-watcher.test.ts +96 -81
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
- package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
- package/src/__tests__/conflict-policy.test.ts +151 -80
- package/src/__tests__/conflict-store.test.ts +203 -157
- package/src/__tests__/connection-policy.test.ts +89 -59
- package/src/__tests__/contacts-tools.test.ts +247 -178
- package/src/__tests__/context-memory-e2e.test.ts +306 -214
- package/src/__tests__/context-token-estimator.test.ts +114 -74
- package/src/__tests__/context-window-manager.test.ts +269 -167
- package/src/__tests__/contradiction-checker.test.ts +161 -135
- package/src/__tests__/conversation-attention-store.test.ts +350 -290
- package/src/__tests__/conversation-attention-telegram.test.ts +156 -114
- package/src/__tests__/conversation-pairing.test.ts +220 -113
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +164 -104
- package/src/__tests__/conversation-routes.test.ts +71 -41
- package/src/__tests__/conversation-store.test.ts +390 -235
- package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
- package/src/__tests__/credential-broker-server-use.test.ts +283 -243
- package/src/__tests__/credential-broker.test.ts +128 -74
- package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
- package/src/__tests__/credential-metadata-store.test.ts +360 -311
- package/src/__tests__/credential-policy-validate.test.ts +81 -65
- package/src/__tests__/credential-resolve.test.ts +212 -145
- package/src/__tests__/credential-security-e2e.test.ts +144 -103
- package/src/__tests__/credential-security-invariants.test.ts +253 -208
- package/src/__tests__/credential-selection.test.ts +254 -146
- package/src/__tests__/credential-vault-unit.test.ts +531 -341
- package/src/__tests__/credential-vault.test.ts +761 -484
- package/src/__tests__/daemon-assistant-events.test.ts +91 -66
- package/src/__tests__/daemon-lifecycle.test.ts +258 -190
- package/src/__tests__/daemon-server-session-init.test.ts +257 -191
- package/src/__tests__/date-context.test.ts +314 -249
- package/src/__tests__/db-migration-rollback.test.ts +259 -130
- package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
- package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
- package/src/__tests__/deterministic-verification-control-plane.test.ts +183 -135
- package/src/__tests__/dictation-mode-detection.test.ts +77 -55
- package/src/__tests__/dictation-profile-store.test.ts +70 -56
- package/src/__tests__/dictation-text-processing.test.ts +53 -35
- package/src/__tests__/diff.test.ts +102 -98
- package/src/__tests__/domain-normalize.test.ts +54 -54
- package/src/__tests__/domain-policy.test.ts +71 -55
- package/src/__tests__/dynamic-page-surface.test.ts +31 -33
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
- package/src/__tests__/edit-engine.test.ts +56 -56
- package/src/__tests__/elevenlabs-client.test.ts +117 -91
- package/src/__tests__/elevenlabs-config.test.ts +32 -31
- package/src/__tests__/email-classifier.test.ts +15 -12
- package/src/__tests__/email-cli.test.ts +121 -108
- package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
- package/src/__tests__/encrypted-store.test.ts +180 -154
- package/src/__tests__/entity-extractor.test.ts +108 -87
- package/src/__tests__/entity-search.test.ts +664 -258
- package/src/__tests__/ephemeral-permissions.test.ts +224 -188
- package/src/__tests__/event-bus.test.ts +81 -77
- package/src/__tests__/extract-email.test.ts +51 -0
- package/src/__tests__/file-edit-tool.test.ts +62 -44
- package/src/__tests__/file-ops-service.test.ts +131 -114
- package/src/__tests__/file-read-tool.test.ts +48 -31
- package/src/__tests__/file-write-tool.test.ts +43 -37
- package/src/__tests__/filesystem-tools.test.ts +238 -209
- package/src/__tests__/followup-tools.test.ts +237 -162
- package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
- package/src/__tests__/frontmatter.test.ts +96 -81
- package/src/__tests__/fuzzy-match-property.test.ts +75 -81
- package/src/__tests__/fuzzy-match.test.ts +71 -65
- package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
- package/src/__tests__/gateway-only-enforcement.test.ts +467 -369
- package/src/__tests__/gateway-only-guard.test.ts +54 -56
- package/src/__tests__/gemini-image-service.test.ts +113 -100
- package/src/__tests__/gemini-provider.test.ts +297 -220
- package/src/__tests__/get-weather.test.ts +188 -114
- package/src/__tests__/gmail-integration.test.ts +47 -46
- package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
- package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
- package/src/__tests__/guardian-action-followup-executor.test.ts +215 -151
- package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
- package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
- package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
- package/src/__tests__/guardian-action-store.test.ts +158 -109
- package/src/__tests__/guardian-action-sweep.test.ts +114 -100
- package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
- package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
- package/src/__tests__/guardian-dispatch.test.ts +316 -256
- package/src/__tests__/guardian-grant-minting.test.ts +247 -178
- package/src/__tests__/guardian-outbound-http.test.ts +337 -209
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
- package/src/__tests__/guardian-question-copy.test.ts +17 -17
- package/src/__tests__/guardian-question-mode.test.ts +134 -100
- package/src/__tests__/guardian-routing-invariants.test.ts +679 -613
- package/src/__tests__/guardian-routing-state.test.ts +256 -209
- package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
- package/src/__tests__/guardian-verification-voice-binding.test.ts +47 -41
- package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
- package/src/__tests__/handle-user-message-secret-resume.test.ts +43 -21
- package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
- package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
- package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
- package/src/__tests__/handlers-slack-config.test.ts +63 -54
- package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
- package/src/__tests__/handlers-telegram-config.test.ts +662 -329
- package/src/__tests__/handlers-twitter-config.test.ts +525 -298
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +270 -195
- package/src/__tests__/headless-browser-interactions.test.ts +444 -280
- package/src/__tests__/headless-browser-navigate.test.ts +116 -79
- package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
- package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
- package/src/__tests__/heartbeat-service.test.ts +76 -58
- package/src/__tests__/history-repair-observability.test.ts +14 -14
- package/src/__tests__/history-repair.test.ts +171 -167
- package/src/__tests__/home-base-bootstrap.test.ts +30 -27
- package/src/__tests__/hooks-blocking.test.ts +86 -37
- package/src/__tests__/hooks-cli.test.ts +104 -68
- package/src/__tests__/hooks-config.test.ts +81 -43
- package/src/__tests__/hooks-discovery.test.ts +106 -96
- package/src/__tests__/hooks-integration.test.ts +78 -72
- package/src/__tests__/hooks-manager.test.ts +99 -61
- package/src/__tests__/hooks-runner.test.ts +94 -71
- package/src/__tests__/hooks-settings.test.ts +69 -64
- package/src/__tests__/hooks-templates.test.ts +85 -54
- package/src/__tests__/hooks-ts-runner.test.ts +82 -45
- package/src/__tests__/hooks-watch.test.ts +32 -22
- package/src/__tests__/host-file-edit-tool.test.ts +190 -148
- package/src/__tests__/host-file-read-tool.test.ts +86 -63
- package/src/__tests__/host-file-write-tool.test.ts +98 -64
- package/src/__tests__/host-shell-tool.test.ts +342 -233
- package/src/__tests__/inbound-invite-redemption.test.ts +194 -152
- package/src/__tests__/ingress-member-store.test.ts +163 -159
- package/src/__tests__/ingress-reconcile.test.ts +183 -142
- package/src/__tests__/ingress-routes-http.test.ts +441 -356
- package/src/__tests__/ingress-url-consistency.test.ts +125 -64
- package/src/__tests__/integration-status.test.ts +93 -73
- package/src/__tests__/intent-routing.test.ts +148 -118
- package/src/__tests__/invite-redemption-service.test.ts +163 -121
- package/src/__tests__/ipc-blob-store.test.ts +104 -91
- package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
- package/src/__tests__/ipc-contract.test.ts +24 -23
- package/src/__tests__/ipc-protocol.test.ts +52 -46
- package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
- package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
- package/src/__tests__/ipc-validate.test.ts +240 -179
- package/src/__tests__/key-migration.test.ts +123 -90
- package/src/__tests__/keychain.test.ts +150 -123
- package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
- package/src/__tests__/llm-usage-store.test.ts +112 -87
- package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
- package/src/__tests__/managed-store.test.ts +411 -360
- package/src/__tests__/mcp-cli.test.ts +189 -123
- package/src/__tests__/mcp-health-check.test.ts +26 -21
- package/src/__tests__/media-generate-image.test.ts +122 -99
- package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
- package/src/__tests__/media-visibility-policy.test.ts +86 -38
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
- package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
- package/src/__tests__/memory-query-builder.test.ts +32 -33
- package/src/__tests__/memory-recall-quality.test.ts +761 -407
- package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
- package/src/__tests__/memory-regressions.test.ts +3725 -2642
- package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
- package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
- package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
- package/src/__tests__/messaging-send-tool.test.ts +36 -29
- package/src/__tests__/migration-cli-flows.test.ts +69 -53
- package/src/__tests__/migration-ordering.test.ts +103 -86
- package/src/__tests__/mime-builder.test.ts +55 -32
- package/src/__tests__/mock-signup-server.test.ts +384 -246
- package/src/__tests__/model-intents.test.ts +61 -37
- package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
- package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
- package/src/__tests__/non-member-access-request.test.ts +294 -249
- package/src/__tests__/notification-broadcaster.test.ts +99 -81
- package/src/__tests__/notification-decision-fallback.test.ts +223 -178
- package/src/__tests__/notification-decision-strategy.test.ts +375 -337
- package/src/__tests__/notification-deep-link.test.ts +67 -61
- package/src/__tests__/notification-guardian-path.test.ts +248 -206
- package/src/__tests__/notification-routing-intent.test.ts +166 -93
- package/src/__tests__/notification-telegram-adapter.test.ts +60 -46
- package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
- package/src/__tests__/notification-thread-candidates.test.ts +64 -61
- package/src/__tests__/oauth-callback-registry.test.ts +40 -30
- package/src/__tests__/oauth-connect-handler.test.ts +109 -89
- package/src/__tests__/oauth-scope-policy.test.ts +63 -55
- package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
- package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
- package/src/__tests__/onboarding-template-contract.test.ts +93 -94
- package/src/__tests__/openai-provider.test.ts +366 -274
- package/src/__tests__/pairing-concurrent.test.ts +18 -12
- package/src/__tests__/pairing-routes.test.ts +45 -41
- package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
- package/src/__tests__/parser.test.ts +316 -226
- package/src/__tests__/path-classifier.test.ts +24 -25
- package/src/__tests__/path-policy.test.ts +187 -147
- package/src/__tests__/phone.test.ts +36 -36
- package/src/__tests__/platform-move-helper.test.ts +48 -40
- package/src/__tests__/platform-socket-path.test.ts +23 -24
- package/src/__tests__/platform-workspace-migration.test.ts +464 -414
- package/src/__tests__/platform.test.ts +61 -53
- package/src/__tests__/playbook-execution.test.ts +397 -265
- package/src/__tests__/playbook-tools.test.ts +267 -196
- package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
- package/src/__tests__/pricing.test.ts +316 -136
- package/src/__tests__/profile-compiler.test.ts +206 -188
- package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
- package/src/__tests__/provider-error-scenarios.test.ts +212 -158
- package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
- package/src/__tests__/provider-registry-ollama.test.ts +13 -9
- package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
- package/src/__tests__/proxy-approval-callback.test.ts +180 -119
- package/src/__tests__/public-ingress-urls.test.ts +112 -94
- package/src/__tests__/qdrant-manager.test.ts +147 -98
- package/src/__tests__/ratelimit.test.ts +152 -82
- package/src/__tests__/recording-handler.test.ts +273 -151
- package/src/__tests__/recording-intent-fallback.test.ts +94 -75
- package/src/__tests__/recording-intent-handler.test.ts +422 -292
- package/src/__tests__/recording-intent.test.ts +578 -379
- package/src/__tests__/recording-state-machine.test.ts +530 -316
- package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
- package/src/__tests__/recurrence-engine.test.ts +81 -41
- package/src/__tests__/recurrence-types.test.ts +63 -44
- package/src/__tests__/relay-server.test.ts +2131 -1602
- package/src/__tests__/reminder-store.test.ts +158 -80
- package/src/__tests__/reminder.test.ts +113 -109
- package/src/__tests__/remote-skill-policy.test.ts +96 -72
- package/src/__tests__/request-file-tool.test.ts +74 -67
- package/src/__tests__/response-tier.test.ts +131 -74
- package/src/__tests__/runtime-attachment-metadata.test.ts +107 -70
- package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
- package/src/__tests__/runtime-events-sse.test.ts +67 -51
- package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
- package/src/__tests__/sandbox-host-parity.test.ts +377 -301
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
- package/src/__tests__/schedule-store.test.ts +268 -205
- package/src/__tests__/schedule-tools.test.ts +702 -524
- package/src/__tests__/scheduler-recurrence.test.ts +240 -130
- package/src/__tests__/scoped-approval-grants.test.ts +258 -168
- package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
- package/src/__tests__/script-proxy-certs.test.ts +38 -35
- package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
- package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
- package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
- package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
- package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
- package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
- package/src/__tests__/script-proxy-policy.test.ts +308 -153
- package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
- package/src/__tests__/script-proxy-router.test.ts +111 -77
- package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
- package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
- package/src/__tests__/secret-allowlist.test.ts +105 -90
- package/src/__tests__/secret-ingress-handler.test.ts +41 -30
- package/src/__tests__/secret-onetime-send.test.ts +67 -50
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
- package/src/__tests__/secret-response-routing.test.ts +50 -41
- package/src/__tests__/secret-scanner-executor.test.ts +152 -111
- package/src/__tests__/secret-scanner.test.ts +495 -413
- package/src/__tests__/secure-keys.test.ts +132 -121
- package/src/__tests__/send-endpoint-busy.test.ts +313 -232
- package/src/__tests__/send-notification-tool.test.ts +43 -42
- package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
- package/src/__tests__/sequence-store.test.ts +335 -167
- package/src/__tests__/server-history-render.test.ts +341 -202
- package/src/__tests__/session-abort-tool-results.test.ts +133 -70
- package/src/__tests__/session-approval-overrides.test.ts +93 -91
- package/src/__tests__/session-confirmation-signals.test.ts +252 -160
- package/src/__tests__/session-conflict-gate.test.ts +775 -585
- package/src/__tests__/session-error.test.ts +222 -191
- package/src/__tests__/session-evictor.test.ts +79 -62
- package/src/__tests__/session-init.benchmark.test.ts +170 -108
- package/src/__tests__/session-load-history-repair.test.ts +273 -139
- package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
- package/src/__tests__/session-pre-run-repair.test.ts +106 -59
- package/src/__tests__/session-profile-injection.test.ts +198 -130
- package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
- package/src/__tests__/session-queue.test.ts +624 -321
- package/src/__tests__/session-runtime-assembly.test.ts +425 -329
- package/src/__tests__/session-runtime-workspace.test.ts +69 -61
- package/src/__tests__/session-skill-tools.test.ts +973 -678
- package/src/__tests__/session-slash-known.test.ts +185 -133
- package/src/__tests__/session-slash-queue.test.ts +147 -81
- package/src/__tests__/session-slash-unknown.test.ts +135 -90
- package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
- package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
- package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
- package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
- package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
- package/src/__tests__/session-undo.test.ts +43 -30
- package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
- package/src/__tests__/session-workspace-injection.test.ts +245 -117
- package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
- package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
- package/src/__tests__/shell-credential-ref.test.ts +126 -90
- package/src/__tests__/shell-identity.test.ts +134 -111
- package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
- package/src/__tests__/shell-parser-property.test.ts +435 -288
- package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
- package/src/__tests__/size-guard.test.ts +42 -44
- package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
- package/src/__tests__/skill-feature-flags.test.ts +75 -47
- package/src/__tests__/skill-include-graph.test.ts +143 -148
- package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
- package/src/__tests__/skill-load-tool.test.ts +371 -199
- package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
- package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
- package/src/__tests__/skill-script-runner-host.test.ts +460 -250
- package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
- package/src/__tests__/skill-script-runner.test.ts +115 -74
- package/src/__tests__/skill-tool-factory.test.ts +140 -96
- package/src/__tests__/skill-tool-manifest.test.ts +306 -210
- package/src/__tests__/skill-version-hash.test.ts +70 -56
- package/src/__tests__/skills.test.ts +0 -1
- package/src/__tests__/slack-channel-config.test.ts +127 -84
- package/src/__tests__/slack-skill.test.ts +60 -47
- package/src/__tests__/slash-commands-catalog.test.ts +37 -31
- package/src/__tests__/slash-commands-parser.test.ts +71 -64
- package/src/__tests__/slash-commands-resolver.test.ts +143 -107
- package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
- package/src/__tests__/sms-messaging-provider.test.ts +74 -47
- package/src/__tests__/speaker-identification.test.ts +28 -25
- package/src/__tests__/starter-bundle.test.ts +27 -23
- package/src/__tests__/starter-task-flow.test.ts +67 -52
- package/src/__tests__/subagent-manager-notify.test.ts +154 -108
- package/src/__tests__/subagent-tools.test.ts +311 -270
- package/src/__tests__/subagent-types.test.ts +40 -40
- package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
- package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
- package/src/__tests__/swarm-orchestrator.test.ts +135 -101
- package/src/__tests__/swarm-plan-validator.test.ts +125 -73
- package/src/__tests__/swarm-recursion.test.ts +58 -46
- package/src/__tests__/swarm-router-planner.test.ts +99 -74
- package/src/__tests__/swarm-session-integration.test.ts +148 -91
- package/src/__tests__/swarm-tool.test.ts +65 -45
- package/src/__tests__/swarm-worker-backend.test.ts +59 -45
- package/src/__tests__/swarm-worker-runner.test.ts +133 -118
- package/src/__tests__/system-prompt.test.ts +290 -256
- package/src/__tests__/task-compiler.test.ts +176 -120
- package/src/__tests__/task-management-tools.test.ts +561 -456
- package/src/__tests__/task-memory-cleanup.test.ts +627 -362
- package/src/__tests__/task-runner.test.ts +117 -94
- package/src/__tests__/task-scheduler.test.ts +113 -84
- package/src/__tests__/task-tools.test.ts +349 -264
- package/src/__tests__/terminal-sandbox.test.ts +138 -108
- package/src/__tests__/terminal-tools.test.ts +350 -305
- package/src/__tests__/thread-seed-composer.test.ts +307 -180
- package/src/__tests__/tool-approval-handler.test.ts +238 -137
- package/src/__tests__/tool-audit-listener.test.ts +69 -69
- package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +153 -146
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
- package/src/__tests__/tool-executor-redaction.test.ts +112 -109
- package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
- package/src/__tests__/tool-executor.test.ts +1274 -674
- package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
- package/src/__tests__/tool-metrics-listener.test.ts +97 -85
- package/src/__tests__/tool-notification-listener.test.ts +42 -25
- package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
- package/src/__tests__/tool-policy.test.ts +44 -25
- package/src/__tests__/tool-profiling-listener.test.ts +99 -93
- package/src/__tests__/tool-result-truncation.test.ts +5 -4
- package/src/__tests__/tool-trace-listener.test.ts +131 -111
- package/src/__tests__/top-level-renderer.test.ts +62 -58
- package/src/__tests__/top-level-scanner.test.ts +68 -64
- package/src/__tests__/trace-emitter.test.ts +56 -56
- package/src/__tests__/trust-context-guards.test.ts +65 -65
- package/src/__tests__/trust-store.test.ts +1239 -806
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +339 -275
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +484 -373
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +264 -241
- package/src/__tests__/trusted-contact-multichannel.test.ts +182 -142
- package/src/__tests__/trusted-contact-verification.test.ts +251 -231
- package/src/__tests__/turn-commit.test.ts +259 -200
- package/src/__tests__/twilio-config.test.ts +49 -41
- package/src/__tests__/twilio-provider.test.ts +140 -126
- package/src/__tests__/twilio-rest.test.ts +22 -18
- package/src/__tests__/twilio-routes-elevenlabs.test.ts +188 -162
- package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
- package/src/__tests__/twilio-routes.test.ts +389 -281
- package/src/__tests__/twitter-auth-handler.test.ts +184 -139
- package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
- package/src/__tests__/twitter-cli-routing.test.ts +146 -99
- package/src/__tests__/twitter-oauth-client.test.ts +82 -65
- package/src/__tests__/update-bulletin-format.test.ts +69 -66
- package/src/__tests__/update-bulletin-state.test.ts +66 -60
- package/src/__tests__/update-bulletin.test.ts +150 -114
- package/src/__tests__/update-template-contract.test.ts +15 -10
- package/src/__tests__/url-safety.test.ts +288 -265
- package/src/__tests__/user-reference.test.ts +32 -32
- package/src/__tests__/view-image-tool.test.ts +118 -96
- package/src/__tests__/voice-invite-redemption.test.ts +111 -106
- package/src/__tests__/voice-quality.test.ts +117 -102
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
- package/src/__tests__/voice-session-bridge.test.ts +351 -216
- package/src/__tests__/weather-skill-regression.test.ts +170 -120
- package/src/__tests__/web-fetch.test.ts +664 -526
- package/src/__tests__/web-search.test.ts +379 -213
- package/src/__tests__/work-item-output.test.ts +90 -53
- package/src/__tests__/workspace-git-service.test.ts +437 -356
- package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
- package/src/__tests__/workspace-lifecycle.test.ts +98 -64
- package/src/__tests__/workspace-policy.test.ts +139 -71
- package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +44 -4
- package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
- package/src/config/bundled-skills/messaging/SKILL.md +9 -7
- package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
- package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
- package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +11 -7
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/env.ts +38 -29
- package/src/daemon/handlers/skills.ts +18 -10
- package/src/daemon/ipc-contract/messages.ts +1 -0
- package/src/daemon/ipc-contract/surfaces.ts +7 -1
- package/src/daemon/session-agent-loop-handlers.ts +5 -0
- package/src/daemon/session-agent-loop.ts +1 -1
- package/src/daemon/session-process.ts +1 -1
- package/src/daemon/session-surfaces.ts +42 -2
- package/src/memory/db-connection.ts +16 -10
- package/src/messaging/providers/gmail/adapter.ts +10 -3
- package/src/messaging/providers/gmail/client.ts +280 -72
- package/src/runtime/auth/__tests__/context.test.ts +75 -65
- package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
- package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
- package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
- package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
- package/src/runtime/auth/__tests__/policy.test.ts +9 -9
- package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
- package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
- package/src/runtime/auth/__tests__/subject.test.ts +54 -54
- package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
- package/src/runtime/auth/scopes.ts +3 -0
- package/src/runtime/auth/token-service.ts +78 -48
- package/src/runtime/auth/types.ts +2 -1
- package/src/runtime/http-server.ts +2 -1
- package/src/security/secure-keys.ts +103 -53
- package/src/sequence/reply-matcher.ts +10 -6
- package/src/skills/frontmatter.ts +9 -6
- package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
- package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
- package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
- package/src/tools/ui-surface/definitions.ts +2 -1
- package/src/util/platform.ts +0 -12
- package/docs/architecture/http-token-refresh.md +0 -274
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import { describe, expect,test } from
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import type { AuthChallenge } from
|
|
4
|
-
import { buildAuthForm, buildTimeoutMessage } from
|
|
3
|
+
import type { AuthChallenge } from "../auth-detector.js";
|
|
4
|
+
import { buildAuthForm, buildTimeoutMessage } from "../jit-auth.js";
|
|
5
5
|
|
|
6
|
-
describe(
|
|
7
|
-
test(
|
|
6
|
+
describe("buildAuthForm", () => {
|
|
7
|
+
test("login challenge produces form with email (text) and password (password) fields", () => {
|
|
8
8
|
const challenge: AuthChallenge = {
|
|
9
|
-
type:
|
|
10
|
-
service:
|
|
11
|
-
url:
|
|
9
|
+
type: "login",
|
|
10
|
+
service: "Google",
|
|
11
|
+
url: "https://accounts.google.com/signin",
|
|
12
12
|
fields: [
|
|
13
|
-
{ type:
|
|
14
|
-
{
|
|
13
|
+
{ type: "email", selector: "#identifierId", label: "Google email" },
|
|
14
|
+
{
|
|
15
|
+
type: "password",
|
|
16
|
+
selector: 'input[type="password"]',
|
|
17
|
+
label: "Google password",
|
|
18
|
+
},
|
|
15
19
|
],
|
|
16
20
|
};
|
|
17
21
|
|
|
@@ -19,172 +23,152 @@ describe('buildAuthForm', () => {
|
|
|
19
23
|
|
|
20
24
|
expect(form.fields).toHaveLength(2);
|
|
21
25
|
|
|
22
|
-
expect(form.fields[0].id).toBe(
|
|
23
|
-
expect(form.fields[0].type).toBe(
|
|
24
|
-
expect(form.fields[0].label).toBe(
|
|
25
|
-
expect(form.fields[0].placeholder).toBe(
|
|
26
|
+
expect(form.fields[0].id).toBe("email");
|
|
27
|
+
expect(form.fields[0].type).toBe("text");
|
|
28
|
+
expect(form.fields[0].label).toBe("Google email");
|
|
29
|
+
expect(form.fields[0].placeholder).toBe("you@example.com");
|
|
26
30
|
expect(form.fields[0].required).toBe(true);
|
|
27
31
|
|
|
28
|
-
expect(form.fields[1].id).toBe(
|
|
29
|
-
expect(form.fields[1].type).toBe(
|
|
30
|
-
expect(form.fields[1].label).toBe(
|
|
31
|
-
expect(form.fields[1].placeholder).toBe(
|
|
32
|
+
expect(form.fields[1].id).toBe("password");
|
|
33
|
+
expect(form.fields[1].type).toBe("password");
|
|
34
|
+
expect(form.fields[1].label).toBe("Google password");
|
|
35
|
+
expect(form.fields[1].placeholder).toBe("Enter your password");
|
|
32
36
|
expect(form.fields[1].required).toBe(true);
|
|
33
37
|
});
|
|
34
38
|
|
|
35
|
-
test(
|
|
39
|
+
test("2FA challenge produces form with code (text) field", () => {
|
|
36
40
|
const challenge: AuthChallenge = {
|
|
37
|
-
type:
|
|
38
|
-
service:
|
|
39
|
-
url:
|
|
40
|
-
fields: [
|
|
41
|
-
{ type: 'code', selector: '#otp', label: 'verification code' },
|
|
42
|
-
],
|
|
41
|
+
type: "2fa",
|
|
42
|
+
service: "GitHub",
|
|
43
|
+
url: "https://github.com/sessions/two-factor",
|
|
44
|
+
fields: [{ type: "code", selector: "#otp", label: "verification code" }],
|
|
43
45
|
};
|
|
44
46
|
|
|
45
47
|
const form = buildAuthForm(challenge);
|
|
46
48
|
|
|
47
49
|
expect(form.fields).toHaveLength(1);
|
|
48
|
-
expect(form.fields[0].id).toBe(
|
|
49
|
-
expect(form.fields[0].type).toBe(
|
|
50
|
-
expect(form.fields[0].label).toBe(
|
|
51
|
-
expect(form.fields[0].placeholder).toBe(
|
|
50
|
+
expect(form.fields[0].id).toBe("code");
|
|
51
|
+
expect(form.fields[0].type).toBe("text");
|
|
52
|
+
expect(form.fields[0].label).toBe("verification code");
|
|
53
|
+
expect(form.fields[0].placeholder).toBe("Enter the code");
|
|
52
54
|
expect(form.fields[0].required).toBe(true);
|
|
53
55
|
});
|
|
54
56
|
|
|
55
|
-
test(
|
|
57
|
+
test("OAuth consent challenge produces form with approval (toggle) field", () => {
|
|
56
58
|
const challenge: AuthChallenge = {
|
|
57
|
-
type:
|
|
58
|
-
service:
|
|
59
|
-
url:
|
|
60
|
-
fields: [
|
|
61
|
-
{ type: 'approval', selector: '#approve', label: 'Allow' },
|
|
62
|
-
],
|
|
59
|
+
type: "oauth_consent",
|
|
60
|
+
service: "Google",
|
|
61
|
+
url: "https://accounts.google.com/o/oauth2/consent",
|
|
62
|
+
fields: [{ type: "approval", selector: "#approve", label: "Allow" }],
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
const form = buildAuthForm(challenge);
|
|
66
66
|
|
|
67
67
|
expect(form.fields).toHaveLength(1);
|
|
68
|
-
expect(form.fields[0].id).toBe(
|
|
69
|
-
expect(form.fields[0].type).toBe(
|
|
70
|
-
expect(form.fields[0].label).toBe(
|
|
68
|
+
expect(form.fields[0].id).toBe("field_0");
|
|
69
|
+
expect(form.fields[0].type).toBe("toggle");
|
|
70
|
+
expect(form.fields[0].label).toBe("Allow");
|
|
71
71
|
expect(form.fields[0].placeholder).toBeUndefined();
|
|
72
72
|
expect(form.fields[0].required).toBe(true);
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
-
test(
|
|
75
|
+
test("service name appears in description", () => {
|
|
76
76
|
const challenge: AuthChallenge = {
|
|
77
|
-
type:
|
|
78
|
-
service:
|
|
79
|
-
url:
|
|
80
|
-
fields: [
|
|
81
|
-
{ type: 'email', selector: '#login_field', label: 'email' },
|
|
82
|
-
],
|
|
77
|
+
type: "login",
|
|
78
|
+
service: "GitHub",
|
|
79
|
+
url: "https://github.com/login",
|
|
80
|
+
fields: [{ type: "email", selector: "#login_field", label: "email" }],
|
|
83
81
|
};
|
|
84
82
|
|
|
85
83
|
const form = buildAuthForm(challenge);
|
|
86
|
-
expect(form.description).toContain(
|
|
84
|
+
expect(form.description).toContain("GitHub");
|
|
87
85
|
});
|
|
88
86
|
|
|
89
87
|
test('default service name ("this website") when service is undefined', () => {
|
|
90
88
|
const challenge: AuthChallenge = {
|
|
91
|
-
type:
|
|
89
|
+
type: "login",
|
|
92
90
|
service: undefined,
|
|
93
|
-
url:
|
|
94
|
-
fields: [
|
|
95
|
-
{ type: 'email', selector: '#email', label: 'email' },
|
|
96
|
-
],
|
|
91
|
+
url: "https://example.com/login",
|
|
92
|
+
fields: [{ type: "email", selector: "#email", label: "email" }],
|
|
97
93
|
};
|
|
98
94
|
|
|
99
95
|
const form = buildAuthForm(challenge);
|
|
100
|
-
expect(form.description).toContain(
|
|
96
|
+
expect(form.description).toContain("this website");
|
|
101
97
|
});
|
|
102
98
|
|
|
103
99
|
test('submit label is "Continue" for login', () => {
|
|
104
100
|
const challenge: AuthChallenge = {
|
|
105
|
-
type:
|
|
106
|
-
service:
|
|
107
|
-
url:
|
|
108
|
-
fields: [
|
|
109
|
-
{ type: 'email', selector: '#identifierId', label: 'email' },
|
|
110
|
-
],
|
|
101
|
+
type: "login",
|
|
102
|
+
service: "Google",
|
|
103
|
+
url: "https://accounts.google.com/signin",
|
|
104
|
+
fields: [{ type: "email", selector: "#identifierId", label: "email" }],
|
|
111
105
|
};
|
|
112
106
|
|
|
113
107
|
const form = buildAuthForm(challenge);
|
|
114
|
-
expect(form.submitLabel).toBe(
|
|
108
|
+
expect(form.submitLabel).toBe("Continue");
|
|
115
109
|
});
|
|
116
110
|
|
|
117
111
|
test('submit label is "Approve" for oauth_consent', () => {
|
|
118
112
|
const challenge: AuthChallenge = {
|
|
119
|
-
type:
|
|
120
|
-
service:
|
|
121
|
-
url:
|
|
122
|
-
fields: [
|
|
123
|
-
{ type: 'approval', selector: '#approve', label: 'Allow' },
|
|
124
|
-
],
|
|
113
|
+
type: "oauth_consent",
|
|
114
|
+
service: "Google",
|
|
115
|
+
url: "https://accounts.google.com/o/oauth2/consent",
|
|
116
|
+
fields: [{ type: "approval", selector: "#approve", label: "Allow" }],
|
|
125
117
|
};
|
|
126
118
|
|
|
127
119
|
const form = buildAuthForm(challenge);
|
|
128
|
-
expect(form.submitLabel).toBe(
|
|
120
|
+
expect(form.submitLabel).toBe("Approve");
|
|
129
121
|
});
|
|
130
122
|
|
|
131
123
|
test('submit label is "Continue" for 2fa', () => {
|
|
132
124
|
const challenge: AuthChallenge = {
|
|
133
|
-
type:
|
|
134
|
-
service:
|
|
135
|
-
url:
|
|
136
|
-
fields: [
|
|
137
|
-
{ type: 'code', selector: '#otp', label: 'verification code' },
|
|
138
|
-
],
|
|
125
|
+
type: "2fa",
|
|
126
|
+
service: "GitHub",
|
|
127
|
+
url: "https://github.com/sessions/two-factor",
|
|
128
|
+
fields: [{ type: "code", selector: "#otp", label: "verification code" }],
|
|
139
129
|
};
|
|
140
130
|
|
|
141
131
|
const form = buildAuthForm(challenge);
|
|
142
|
-
expect(form.submitLabel).toBe(
|
|
132
|
+
expect(form.submitLabel).toBe("Continue");
|
|
143
133
|
});
|
|
144
134
|
});
|
|
145
135
|
|
|
146
|
-
describe(
|
|
147
|
-
test(
|
|
136
|
+
describe("buildTimeoutMessage", () => {
|
|
137
|
+
test("returns 2FA-specific message for 2fa challenges", () => {
|
|
148
138
|
const challenge: AuthChallenge = {
|
|
149
|
-
type:
|
|
150
|
-
service:
|
|
151
|
-
url:
|
|
152
|
-
fields: [
|
|
153
|
-
{ type: 'code', selector: '#otp', label: 'verification code' },
|
|
154
|
-
],
|
|
139
|
+
type: "2fa",
|
|
140
|
+
service: "GitHub",
|
|
141
|
+
url: "https://github.com/sessions/two-factor",
|
|
142
|
+
fields: [{ type: "code", selector: "#otp", label: "verification code" }],
|
|
155
143
|
};
|
|
156
144
|
|
|
157
145
|
const message = buildTimeoutMessage(challenge);
|
|
158
|
-
expect(message).toContain(
|
|
159
|
-
expect(message).toContain(
|
|
146
|
+
expect(message).toContain("verification code");
|
|
147
|
+
expect(message).toContain("GitHub");
|
|
160
148
|
});
|
|
161
149
|
|
|
162
|
-
test(
|
|
150
|
+
test("returns sign-in message for login challenges", () => {
|
|
163
151
|
const challenge: AuthChallenge = {
|
|
164
|
-
type:
|
|
165
|
-
service:
|
|
166
|
-
url:
|
|
167
|
-
fields: [
|
|
168
|
-
{ type: 'email', selector: '#identifierId', label: 'email' },
|
|
169
|
-
],
|
|
152
|
+
type: "login",
|
|
153
|
+
service: "Google",
|
|
154
|
+
url: "https://accounts.google.com/signin",
|
|
155
|
+
fields: [{ type: "email", selector: "#identifierId", label: "email" }],
|
|
170
156
|
};
|
|
171
157
|
|
|
172
158
|
const message = buildTimeoutMessage(challenge);
|
|
173
|
-
expect(message).toContain(
|
|
174
|
-
expect(message).toContain(
|
|
159
|
+
expect(message).toContain("sign in");
|
|
160
|
+
expect(message).toContain("Google");
|
|
175
161
|
});
|
|
176
162
|
|
|
177
163
|
test('uses "the website" when service is undefined', () => {
|
|
178
164
|
const challenge: AuthChallenge = {
|
|
179
|
-
type:
|
|
165
|
+
type: "login",
|
|
180
166
|
service: undefined,
|
|
181
|
-
url:
|
|
182
|
-
fields: [
|
|
183
|
-
{ type: 'email', selector: '#email', label: 'email' },
|
|
184
|
-
],
|
|
167
|
+
url: "https://example.com/login",
|
|
168
|
+
fields: [{ type: "email", selector: "#email", label: "email" }],
|
|
185
169
|
};
|
|
186
170
|
|
|
187
171
|
const message = buildTimeoutMessage(challenge);
|
|
188
|
-
expect(message).toContain(
|
|
172
|
+
expect(message).toContain("the website");
|
|
189
173
|
});
|
|
190
174
|
});
|
|
@@ -39,7 +39,8 @@ export const uiShowTool: Tool = {
|
|
|
39
39
|
'templateData shape: { title: string, status: "in_progress"|"completed"|"failed", ' +
|
|
40
40
|
'steps: Array<{ label: string, status: "pending"|"in_progress"|"completed"|"failed", detail?: string }> }\n' +
|
|
41
41
|
'- table: Data table with columns, selectable rows, and action buttons. ' +
|
|
42
|
-
'data shape: { columns: Array<{ id: string, label: string, width?: number }>, rows: Array<{ id: string, cells: Record<string, string>, selectable?: boolean, selected?: boolean }>, selectionMode?: "none"|"single"|"multiple", caption?: string }. ' +
|
|
42
|
+
'data shape: { columns: Array<{ id: string, label: string, width?: number }>, rows: Array<{ id: string, cells: Record<string, string | { text: string, icon?: string, iconColor?: "success"|"warning"|"error"|"muted" }>, selectable?: boolean, selected?: boolean }>, selectionMode?: "none"|"single"|"multiple", caption?: string }. ' +
|
|
43
|
+
'Cell values can be plain strings or rich objects with icon (SF Symbol name) and iconColor. ' +
|
|
43
44
|
'Column width is in points — use it for narrow columns (e.g. counts, short labels) so flexible columns get more space. Omit width for columns that should expand.\n' +
|
|
44
45
|
'- form: Input form with typed fields. ' +
|
|
45
46
|
'data shape: { description?: string, fields: Array<{ id: string, type: "text"|"textarea"|"select"|"toggle"|"number"|"password", label: string, placeholder?: string, required?: boolean, defaultValue?: string|number|boolean, options?: Array<{ label: string, value: string }> }>, submitLabel?: string }. ' +
|
package/src/util/platform.ts
CHANGED
|
@@ -267,18 +267,6 @@ export function readSessionToken(): string | null {
|
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
-
/**
|
|
271
|
-
* Read the runtime HTTP bearer token from disk. Returns null if the
|
|
272
|
-
* file doesn't exist or can't be read (HTTP server not running).
|
|
273
|
-
*/
|
|
274
|
-
export function readHttpToken(): string | null {
|
|
275
|
-
try {
|
|
276
|
-
return readFileSync(getHttpTokenPath(), 'utf-8').trim();
|
|
277
|
-
} catch {
|
|
278
|
-
return null;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
270
|
function expandHomePath(p: string): string {
|
|
283
271
|
if (p === '~') return homedir();
|
|
284
272
|
if (p.startsWith('~/')) return join(homedir(), p.slice(2));
|
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
# HTTP Token Refresh Protocol
|
|
2
|
-
|
|
3
|
-
Design for how the daemon notifies clients of bearer token rotation and how clients recover from stale tokens.
|
|
4
|
-
|
|
5
|
-
## Current State
|
|
6
|
-
|
|
7
|
-
The daemon's HTTP bearer token is resolved at startup and persisted to `~/.vellum/http-token` (mode 0600). The startup token resolution order is: (1) the `RUNTIME_PROXY_BEARER_TOKEN` env var if set, (2) the existing token read from `~/.vellum/http-token` if the file is readable and non-empty, (3) a newly generated random token as a last resort. Clients read this file at connection time:
|
|
8
|
-
|
|
9
|
-
- **macOS (local)**: Reads `~/.vellum/http-token` from disk via `resolveHttpTokenPath()` / `readHttpToken()`. Has direct filesystem access to the token file.
|
|
10
|
-
- **iOS (remote)**: Receives the bearer token during the QR-code pairing flow. The token is stored in the iOS Keychain and used for all subsequent HTTP/SSE requests.
|
|
11
|
-
- **Chrome extension**: User manually pastes the token from `~/.vellum/http-token` into the extension popup.
|
|
12
|
-
|
|
13
|
-
Token regeneration today (macOS Settings > Connect > Regenerate Bearer Token):
|
|
14
|
-
1. macOS client writes a new random token to `~/.vellum/http-token`.
|
|
15
|
-
2. macOS client kills the daemon process.
|
|
16
|
-
3. The health monitor restarts the daemon, which reads the new token from disk.
|
|
17
|
-
4. macOS client re-reads the token from disk on next health check.
|
|
18
|
-
5. **iOS clients are broken** -- they still hold the old token and get 401s. The only recovery is to re-pair via QR code.
|
|
19
|
-
|
|
20
|
-
## Problem
|
|
21
|
-
|
|
22
|
-
When the bearer token is rotated (manually or programmatically), remote clients (iOS, Chrome extension) have no way to learn about the new token. They receive 401 responses and cannot recover without manual re-configuration.
|
|
23
|
-
|
|
24
|
-
## Design
|
|
25
|
-
|
|
26
|
-
### 1. SSE Token Rotation Event
|
|
27
|
-
|
|
28
|
-
When the daemon detects that its bearer token has changed, it emits a `token_rotated` SSE event to all connected clients **before** the old token is invalidated. This gives clients a window to capture the new token and seamlessly reconnect.
|
|
29
|
-
|
|
30
|
-
**Event format** (delivered as an `AssistantEvent` envelope wrapping a new `ServerMessage` type):
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
// New ServerMessage variant
|
|
34
|
-
interface TokenRotatedMessage {
|
|
35
|
-
type: 'token_rotated';
|
|
36
|
-
newToken: string; // The replacement bearer token
|
|
37
|
-
expiresOldAt: number; // Unix timestamp (ms) -- old token stops working after this
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
**Grace period**: The daemon accepts both old and new tokens for a configurable grace window (default: 30 seconds) after emitting the event. This gives slow clients time to process the event and switch tokens. After the grace period, only the new token is valid.
|
|
42
|
-
|
|
43
|
-
**Sequence diagram (routine rotation)**:
|
|
44
|
-
|
|
45
|
-
```mermaid
|
|
46
|
-
sequenceDiagram
|
|
47
|
-
participant Trigger as Rotation Trigger
|
|
48
|
-
participant Daemon as Daemon
|
|
49
|
-
participant SSE as SSE Stream
|
|
50
|
-
participant Client as iOS / Chrome Client
|
|
51
|
-
|
|
52
|
-
Trigger->>Daemon: Rotate token (manual, API, periodic)
|
|
53
|
-
Daemon->>Daemon: Generate new token, write to ~/.vellum/http-token
|
|
54
|
-
Daemon->>Daemon: Enter grace period (accept old + new)
|
|
55
|
-
Daemon->>SSE: Emit token_rotated {newToken, expiresOldAt}
|
|
56
|
-
SSE->>Client: token_rotated event
|
|
57
|
-
Client->>Client: Store new token (Keychain / localStorage)
|
|
58
|
-
Client->>Client: Update Authorization header
|
|
59
|
-
Client->>Daemon: Reconnect SSE with new token
|
|
60
|
-
Note over Daemon: Grace period expires
|
|
61
|
-
Daemon->>Daemon: Reject old token (401)
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
**Sequence diagram (revocation rotation)**:
|
|
65
|
-
|
|
66
|
-
```mermaid
|
|
67
|
-
sequenceDiagram
|
|
68
|
-
participant Trigger as Security Event
|
|
69
|
-
participant Daemon as Daemon
|
|
70
|
-
participant SSE as SSE Stream
|
|
71
|
-
participant Client as iOS / Chrome Client
|
|
72
|
-
|
|
73
|
-
Trigger->>Daemon: Rotate token (revoke: true)
|
|
74
|
-
Daemon->>Daemon: Generate new token, immediately invalidate old token
|
|
75
|
-
Daemon->>SSE: Terminate all old-token connections
|
|
76
|
-
Daemon->>Daemon: Write new token to ~/.vellum/http-token
|
|
77
|
-
Note over SSE: No token_rotated event emitted
|
|
78
|
-
Client->>Daemon: Next request with old token → 401
|
|
79
|
-
Client->>Client: Trigger fallback recovery (re-pair / re-read / re-paste)
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### 2. Client 401 Recovery (Stale Token Detection)
|
|
83
|
-
|
|
84
|
-
If a client misses the SSE event (network partition, app backgrounded, SSE disconnected at rotation time), it needs a fallback recovery mechanism.
|
|
85
|
-
|
|
86
|
-
**401 response handling**:
|
|
87
|
-
|
|
88
|
-
When a client receives a `401 Unauthorized` response:
|
|
89
|
-
|
|
90
|
-
1. **macOS (local)**: Re-reads `~/.vellum/http-token` from disk. If the token differs from the in-memory token, updates and retries. This already works implicitly since macOS re-reads the token on most HTTP calls via `resolveLocalDaemonHTTPEndpoint()`.
|
|
91
|
-
|
|
92
|
-
2. **iOS (remote)**: Cannot read the token file. Must re-pair via QR code. The 401 response triggers the client to surface a "Session expired -- re-pair required" UI prompt. This is the expected behavior when the SSE notification is missed.
|
|
93
|
-
|
|
94
|
-
3. **Chrome extension**: Surfaces an error message directing the user to paste the new token.
|
|
95
|
-
|
|
96
|
-
**Retry logic**: Clients should retry at most once after a 401 before surfacing the error UI. This prevents retry storms during legitimate auth failures (wrong token, not just stale).
|
|
97
|
-
|
|
98
|
-
### 3. Token Rotation Triggers
|
|
99
|
-
|
|
100
|
-
The token can be rotated via:
|
|
101
|
-
|
|
102
|
-
| Trigger | Description | Current | Proposed | Mode |
|
|
103
|
-
|---------|-------------|---------|----------|------|
|
|
104
|
-
| Manual (macOS Settings) | User clicks "Regenerate Bearer Token" | Yes (kills daemon) | Graceful rotation via daemon API | Routine |
|
|
105
|
-
| API endpoint | `POST /v1/auth/rotate-token` | No | New endpoint | Routine (default) or Revocation (`revoke: true`) |
|
|
106
|
-
| Periodic rotation | Automatic rotation on a configurable schedule | No | Future consideration | Routine |
|
|
107
|
-
| Security event | Forced rotation after suspicious activity | No | Future consideration | Revocation |
|
|
108
|
-
|
|
109
|
-
**`POST /v1/auth/rotate-token`** (new endpoint):
|
|
110
|
-
|
|
111
|
-
Allows programmatic token rotation without restarting the daemon.
|
|
112
|
-
|
|
113
|
-
Request body (optional): `{ "revoke": boolean }` (default: `false`).
|
|
114
|
-
|
|
115
|
-
**Routine mode** (`revoke: false`, default):
|
|
116
|
-
1. Generates a new random token.
|
|
117
|
-
2. Writes it to `~/.vellum/http-token`.
|
|
118
|
-
3. Emits the `token_rotated` SSE event with grace period.
|
|
119
|
-
4. Starts accepting both tokens during the grace period.
|
|
120
|
-
5. After grace period, rejects the old token.
|
|
121
|
-
|
|
122
|
-
**Revocation mode** (`revoke: true`):
|
|
123
|
-
1. Generates a new random token.
|
|
124
|
-
2. Immediately invalidates the old token in memory (no grace period).
|
|
125
|
-
3. Terminates all SSE connections authenticated with the old token.
|
|
126
|
-
4. Writes the new token to `~/.vellum/http-token`.
|
|
127
|
-
5. Does **not** emit `token_rotated` -- the new token is never sent to old-token sessions.
|
|
128
|
-
6. Clients must recover via their platform-specific fallback (re-read from disk, re-pair, or re-paste).
|
|
129
|
-
|
|
130
|
-
This eliminates the current "kill and restart" approach for token rotation.
|
|
131
|
-
|
|
132
|
-
### 4. Daemon-Side Implementation
|
|
133
|
-
|
|
134
|
-
**Grace period token validation**: During routine rotation, `verifyBearerToken()` accepts either the old or new token. The `RuntimeHttpServer` holds both tokens:
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
// Conceptual extension to RuntimeHttpServer
|
|
138
|
-
private currentToken: string;
|
|
139
|
-
private previousToken: string | null = null;
|
|
140
|
-
private graceDeadline: number | null = null;
|
|
141
|
-
|
|
142
|
-
// Modified auth check
|
|
143
|
-
private isValidToken(provided: string): boolean {
|
|
144
|
-
if (verifyBearerToken(provided, this.currentToken)) return true;
|
|
145
|
-
if (this.previousToken && this.graceDeadline && Date.now() < this.graceDeadline) {
|
|
146
|
-
return verifyBearerToken(provided, this.previousToken);
|
|
147
|
-
}
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Rotation has two ordering strategies depending on revoke mode:
|
|
152
|
-
// - Revocation: invalidate in-memory FIRST (security-critical), then persist.
|
|
153
|
-
// A disk write failure must never leave a compromised token valid.
|
|
154
|
-
// - Routine: persist to disk FIRST, then update in-memory state.
|
|
155
|
-
// A disk write failure aborts rotation — clients keep the old token
|
|
156
|
-
// rather than being locked out by an in-memory-only switch.
|
|
157
|
-
private rotateToken(revoke: boolean): string {
|
|
158
|
-
const newToken = generateToken();
|
|
159
|
-
|
|
160
|
-
if (revoke) {
|
|
161
|
-
// Revocation: invalidate the compromised token immediately.
|
|
162
|
-
// Even if the disk write below fails, the old token is gone from memory.
|
|
163
|
-
this.currentToken = newToken;
|
|
164
|
-
this.previousToken = null;
|
|
165
|
-
this.graceDeadline = null;
|
|
166
|
-
this.terminateOldTokenSSEConnections();
|
|
167
|
-
writeTokenToDisk(newToken);
|
|
168
|
-
} else {
|
|
169
|
-
// Routine: persist to disk first — if this throws, auth state is untouched
|
|
170
|
-
writeTokenToDisk(newToken);
|
|
171
|
-
this.previousToken = this.currentToken;
|
|
172
|
-
this.currentToken = newToken;
|
|
173
|
-
this.graceDeadline = Date.now() + GRACE_PERIOD_MS;
|
|
174
|
-
this.emitTokenRotatedEvent(newToken, this.graceDeadline);
|
|
175
|
-
}
|
|
176
|
-
return newToken;
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
**Failure semantics — routine vs. revocation**:
|
|
181
|
-
|
|
182
|
-
The two rotation modes have deliberately different failure ordering to match their security requirements:
|
|
183
|
-
|
|
184
|
-
| | Routine (`revoke: false`) | Revocation (`revoke: true`) |
|
|
185
|
-
|---|---|---|
|
|
186
|
-
| **Order** | Persist to disk first, then update in-memory state | Update in-memory state first, then persist to disk |
|
|
187
|
-
| **Disk write failure** | Rotation aborts cleanly — in-memory auth state is untouched, clients keep working with the old token | Old token is already invalidated in memory; the API endpoint returns an error to the caller |
|
|
188
|
-
| **Rationale** | Availability: don't lock out clients if persistence fails | Security: a potentially compromised token must never remain valid, even briefly |
|
|
189
|
-
|
|
190
|
-
**Revocation disk-write failure in detail**: If `writeTokenToDisk` throws after the in-memory switch during revocation, the system enters a degraded state:
|
|
191
|
-
|
|
192
|
-
1. **In-memory state**: `currentToken` holds the new (unpersisted) token. The old token is rejected. All old-token SSE connections have been terminated.
|
|
193
|
-
2. **Disk state**: `~/.vellum/http-token` still contains the old (now-invalid) token.
|
|
194
|
-
3. **API response**: The `POST /v1/auth/rotate-token` endpoint returns an error indicating the persistence failure. The response body includes the new token so the caller can manually persist or distribute it if needed.
|
|
195
|
-
4. **Client impact by platform**:
|
|
196
|
-
- **macOS**: Re-reading the token file yields the stale old token, which is rejected (401). Recovery requires a daemon restart (which generates a fresh token and persists it) or a successful retry of the rotation API call.
|
|
197
|
-
- **iOS**: Already disconnected (old-token SSE terminated). Cannot recover until the daemon restarts or the rotation is retried successfully, at which point re-pairing is required.
|
|
198
|
-
- **Chrome extension**: Same as iOS — the pasted token is stale and rejected.
|
|
199
|
-
5. **Daemon restart recovery**: A daemon restart does **not** automatically heal this state. At startup, the daemon first checks for the `RUNTIME_PROXY_BEARER_TOKEN` env var, then tries to read the existing token from `~/.vellum/http-token`, and only generates a new random token if both are unavailable (see `assistant/src/daemon/lifecycle.ts`, lines 110-124). In the degraded state described here — where the disk still holds the old (now-invalid) token — a restart would reload that stale token, making it the active bearer token again. To actually recover, the operator must either: (a) manually delete or overwrite `~/.vellum/http-token` before restarting the daemon, (b) set `RUNTIME_PROXY_BEARER_TOKEN` to a known-good value, or (c) successfully retry the `POST /v1/auth/rotate-token` endpoint while the daemon is still running with the new in-memory token.
|
|
200
|
-
6. **Why this is acceptable**: Revocation is a security-critical operation triggered when the old token is suspected compromised. The invariant — "a compromised token must not remain valid" — takes precedence over client convenience. The degraded state requires manual intervention but disk write failures are rare in practice (permissions, disk full), and the API response includes the new token so the caller can retry or manually persist it.
|
|
201
|
-
|
|
202
|
-
**SSE event emission** (routine rotation only): The `token_rotated` event is published to `assistantEventHub` as a `ServerMessage`, reaching all connected SSE subscribers across all conversations. This event is never emitted during revocation rotations.
|
|
203
|
-
|
|
204
|
-
### 5. iOS Client Implementation
|
|
205
|
-
|
|
206
|
-
**SSE event handler** (in `HTTPTransport`):
|
|
207
|
-
|
|
208
|
-
```swift
|
|
209
|
-
// In parseSSEData, handle the new message type
|
|
210
|
-
case .tokenRotated(let msg):
|
|
211
|
-
// Persist the new token to Keychain
|
|
212
|
-
DaemonConfigStore.shared.updateBearerToken(msg.newToken)
|
|
213
|
-
// Update in-memory token
|
|
214
|
-
self.bearerToken = msg.newToken
|
|
215
|
-
// Reconnect SSE with the new token
|
|
216
|
-
self.stopSSE()
|
|
217
|
-
self.startSSE()
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
**401 response handler**:
|
|
221
|
-
|
|
222
|
-
```swift
|
|
223
|
-
// In any HTTP request that receives 401
|
|
224
|
-
if http.statusCode == 401 {
|
|
225
|
-
// Token is stale and we missed the rotation event
|
|
226
|
-
// Surface re-pairing UI
|
|
227
|
-
onMessage?(.sessionError(SessionErrorMessage(
|
|
228
|
-
sessionId: sessionId,
|
|
229
|
-
code: .authenticationRequired,
|
|
230
|
-
userMessage: "Session expired. Please re-pair your device.",
|
|
231
|
-
retryable: false
|
|
232
|
-
)))
|
|
233
|
-
}
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### 6. Security Considerations
|
|
237
|
-
|
|
238
|
-
- **Rotation modes**: Token rotation has two distinct modes with different security requirements:
|
|
239
|
-
|
|
240
|
-
1. **Routine rotation** (manual refresh, periodic schedule): The old token is not compromised -- the goal is seamless credential rollover. The SSE `token_rotated` event delivers the new token to connected clients, and the grace period allows them to transition. This is safe because the SSE channel is authenticated, and any session holding the old token is a legitimate client.
|
|
241
|
-
|
|
242
|
-
2. **Revocation rotation** (security event, suspected compromise): The old token may be in the hands of an attacker. In this mode, the daemon **must not** push the replacement token to old-token SSE sessions -- doing so would hand the new credential to the very sessions being revoked. Instead:
|
|
243
|
-
- The daemon immediately invalidates the old token (no grace period).
|
|
244
|
-
- All SSE connections authenticated with the old token are terminated.
|
|
245
|
-
- The `POST /v1/auth/rotate-token` endpoint accepts an optional `revoke: true` flag to select this mode.
|
|
246
|
-
- Legitimate clients recover via their fallback path: macOS re-reads `~/.vellum/http-token` from disk; iOS prompts for re-pairing; Chrome extension prompts for a new token.
|
|
247
|
-
|
|
248
|
-
The `token_rotated` SSE event is only emitted during routine rotations. The rotation trigger determines the mode.
|
|
249
|
-
|
|
250
|
-
- **Grace period length**: 30 seconds is long enough for clients to process the event but short enough to limit the window where both tokens are valid. Only applies to routine rotations.
|
|
251
|
-
- **No token in logs**: The `token_rotated` event payload must be excluded from any server-side event logging. Use the existing log-redaction patterns.
|
|
252
|
-
- **Constant-time comparison**: The existing `verifyBearerToken()` using `timingSafeEqual` continues to be used for both old and new token checks during the grace period.
|
|
253
|
-
|
|
254
|
-
### 7. Migration Path
|
|
255
|
-
|
|
256
|
-
This design is additive and backward-compatible:
|
|
257
|
-
|
|
258
|
-
1. **Phase 1**: Add `POST /v1/auth/rotate-token` endpoint and `token_rotated` SSE event to the daemon. Update macOS Settings to call the API endpoint instead of kill-and-restart.
|
|
259
|
-
2. **Phase 2**: Add `token_rotated` handler to `HTTPTransport.swift` (shared between macOS and iOS). Add 401 retry-once logic.
|
|
260
|
-
3. **Phase 3** (future): Add periodic rotation and security-event-triggered rotation.
|
|
261
|
-
|
|
262
|
-
Clients that do not understand the `token_rotated` event will simply ignore it (SSE events with unknown types are safe to skip). They will eventually get 401s after the grace period and fall back to their existing recovery path (re-read from disk for macOS, re-pair for iOS).
|
|
263
|
-
|
|
264
|
-
## Key Files
|
|
265
|
-
|
|
266
|
-
| File | Role |
|
|
267
|
-
|------|------|
|
|
268
|
-
| `assistant/src/runtime/http-server.ts` | Auth check, grace period logic, rotation endpoint |
|
|
269
|
-
| `assistant/src/runtime/middleware/auth.ts` | `verifyBearerToken()` -- constant-time token comparison |
|
|
270
|
-
| `assistant/src/runtime/assistant-event.ts` | `AssistantEvent` envelope, SSE framing |
|
|
271
|
-
| `assistant/src/daemon/lifecycle.ts` | Token generation and persistence at startup |
|
|
272
|
-
| `clients/shared/IPC/HTTPDaemonClient.swift` | `HTTPTransport` -- SSE stream, 401 handling |
|
|
273
|
-
| `clients/shared/IPC/DaemonClient.swift` | `readHttpToken()`, `resolveHttpTokenPath()` |
|
|
274
|
-
| `clients/macos/.../SettingsConnectTab.swift` | Manual token regeneration UI |
|