@vellumai/assistant 0.4.35 → 0.4.36
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/AGENTS.md +1 -1
- package/ARCHITECTURE.md +44 -49
- package/README.md +32 -20
- package/docs/architecture/keychain-broker.md +186 -0
- package/docs/architecture/security.md +110 -116
- package/docs/runbook-trusted-contacts.md +2 -2
- package/docs/skills.md +25 -25
- package/package.json +4 -1
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +11 -2
- package/src/__tests__/actor-token-service.test.ts +1 -0
- package/src/__tests__/amazon-cdp-integration.test.ts +74 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +38 -9
- package/src/__tests__/assistant-id-boundary-guard.test.ts +29 -0
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/bundle-scanner.test.ts +1 -1
- package/src/__tests__/channel-guardian.test.ts +102 -102
- package/src/__tests__/channel-invite-transport.test.ts +155 -256
- package/src/__tests__/channel-readiness-routes.test.ts +336 -0
- package/src/__tests__/checker.test.ts +6 -6
- package/src/__tests__/chrome-cdp.test.ts +350 -0
- package/src/__tests__/computer-use-session-lifecycle.test.ts +3 -3
- package/src/__tests__/computer-use-session-working-dir.test.ts +86 -52
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +1 -1
- package/src/__tests__/config-loader-migration.test.ts +85 -0
- package/src/__tests__/conversation-pairing.test.ts +370 -5
- package/src/__tests__/credential-broker-browser-fill.test.ts +1 -10
- package/src/__tests__/credential-broker-server-use.test.ts +1 -10
- package/src/__tests__/credential-security-e2e.test.ts +7 -1
- package/src/__tests__/credential-security-invariants.test.ts +14 -20
- package/src/__tests__/credential-vault-unit.test.ts +1 -11
- package/src/__tests__/credential-vault.test.ts +5 -19
- package/src/__tests__/credentials-cli.test.ts +806 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +23 -4
- package/src/__tests__/email-invite-adapter.test.ts +78 -0
- package/src/__tests__/email-service-config-fallback.test.ts +102 -0
- package/src/__tests__/encrypted-store.test.ts +6 -6
- package/src/__tests__/ephemeral-permissions.test.ts +3 -3
- package/src/__tests__/gateway-only-enforcement.test.ts +5 -1
- package/src/__tests__/guardian-actions-endpoint.test.ts +70 -12
- package/src/__tests__/guardian-outbound-http.test.ts +53 -47
- package/src/__tests__/handle-user-message-secret-resume.test.ts +23 -0
- package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +32 -23
- package/src/__tests__/handlers-telegram-config.test.ts +8 -2
- package/src/__tests__/handlers-twitter-config.test.ts +2 -2
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +108 -7
- package/src/__tests__/ingress-reconcile.test.ts +6 -0
- package/src/__tests__/intent-routing.test.ts +23 -4
- package/src/__tests__/invite-routes-http.test.ts +12 -0
- package/src/__tests__/ipc-snapshot.test.ts +8 -2
- package/src/__tests__/keychain-broker-client.test.ts +543 -0
- package/src/__tests__/llm-usage-store.test.ts +344 -0
- package/src/__tests__/mcp-client-auth.test.ts +2 -2
- package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
- package/src/__tests__/migration-transport.test.ts +49 -0
- package/src/__tests__/notification-broadcaster.test.ts +205 -5
- package/src/__tests__/notification-deep-link.test.ts +365 -1
- package/src/__tests__/oauth-connect-handler.test.ts +2 -2
- package/src/__tests__/onboarding-starter-tasks.test.ts +17 -4
- package/src/__tests__/proxy-approval-callback.test.ts +1 -1
- package/src/__tests__/recording-handler.test.ts +1 -1
- package/src/__tests__/recording-intent-handler.test.ts +6 -1
- package/src/__tests__/recording-state-machine.test.ts +1 -1
- package/src/__tests__/relay-server.test.ts +9 -1
- package/src/__tests__/ride-shotgun-handler.test.ts +499 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +160 -1
- package/src/__tests__/script-proxy-injection-runtime.test.ts +299 -2
- package/src/__tests__/script-proxy-profile-template-fallback.test.ts +1 -1
- package/src/__tests__/secret-onetime-send.test.ts +8 -2
- package/src/__tests__/secure-keys.test.ts +175 -216
- package/src/__tests__/session-confirmation-signals.test.ts +1 -1
- package/src/__tests__/session-messaging-secret-redirect.test.ts +1 -1
- package/src/__tests__/session-queue.test.ts +2 -1
- package/src/__tests__/session-tool-setup-app-refresh.test.ts +2 -2
- package/src/__tests__/skill-feature-flags-integration.test.ts +29 -4
- package/src/__tests__/skill-feature-flags.test.ts +12 -9
- package/src/__tests__/skill-load-feature-flag.test.ts +26 -5
- package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
- package/src/__tests__/skills.test.ts +34 -4
- package/src/__tests__/slack-channel-config.test.ts +2 -2
- package/src/__tests__/system-prompt.test.ts +26 -4
- package/src/__tests__/telegram-bot-username-resolution.test.ts +212 -0
- package/src/__tests__/telegram-invite-adapter.test.ts +164 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
- package/src/__tests__/tool-permission-simulate-handler.test.ts +8 -2
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +9 -1
- package/src/__tests__/twitter-auth-handler.test.ts +2 -2
- package/src/__tests__/twitter-oauth-client.test.ts +1 -1
- package/src/__tests__/usage-routes.test.ts +339 -0
- package/src/__tests__/whatsapp-invite-adapter.test.ts +94 -0
- package/src/agent/loop.ts +3 -0
- package/src/amazon/checkout.ts +0 -1
- package/src/approvals/guardian-request-resolvers.ts +9 -1
- package/src/bundler/app-bundler.ts +28 -12
- package/src/bundler/bundle-scanner.ts +1 -1
- package/src/bundler/bundle-signer.ts +3 -3
- package/src/bundler/manifest.ts +1 -1
- package/src/bundler/signature-verifier.ts +3 -3
- package/src/channels/config.ts +1 -1
- package/src/cli/AGENTS.md +63 -0
- package/src/cli/__tests__/notifications.test.ts +470 -0
- package/src/cli/amazon.ts +344 -167
- package/src/cli/audit.ts +85 -0
- package/src/cli/autonomy.ts +369 -0
- package/src/cli/channels.ts +51 -0
- package/src/cli/completions.ts +208 -0
- package/src/cli/config.ts +220 -0
- package/src/cli/contacts.ts +471 -0
- package/src/cli/credentials.ts +564 -0
- package/src/cli/default-action.ts +14 -0
- package/src/cli/dev.ts +131 -0
- package/src/cli/doctor.ts +398 -0
- package/src/cli/email.ts +491 -0
- package/src/cli/influencer.ts +72 -0
- package/src/cli/integrations.ts +248 -57
- package/src/cli/keys.ts +114 -0
- package/src/cli/map.ts +46 -54
- package/src/cli/mcp.ts +111 -3
- package/src/cli/{config-commands.ts → memory.ts} +133 -242
- package/src/cli/notifications.ts +407 -0
- package/src/cli/program.ts +65 -0
- package/src/cli/reference.ts +48 -0
- package/src/cli/sequence.ts +154 -0
- package/src/cli/sessions.ts +262 -0
- package/src/cli/trust.ts +177 -0
- package/src/cli/twitter.ts +323 -106
- package/src/config/__tests__/build-cli-reference-section.test.ts +49 -0
- package/src/config/bundled-skills/amazon/SKILL.md +2 -2
- package/src/config/bundled-skills/app-builder/TOOLS.json +26 -0
- package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +13 -0
- package/src/config/bundled-skills/contacts/SKILL.md +178 -10
- package/src/config/bundled-skills/doordash/doordash-cli.ts +23 -168
- package/src/config/bundled-skills/google-oauth-setup/SKILL.md +135 -34
- package/src/config/bundled-skills/messaging/tools/shared.ts +4 -1
- package/src/config/bundled-skills/twilio-setup/SKILL.md +70 -17
- package/src/config/bundled-tool-registry.ts +2 -0
- package/src/config/core-schema.ts +7 -0
- package/src/config/feature-flag-registry.json +16 -0
- package/src/config/loader.ts +26 -0
- package/src/config/schema.ts +4 -0
- package/src/config/skill-state.ts +0 -13
- package/src/config/system-prompt.ts +27 -0
- package/src/contacts/contact-store.ts +25 -0
- package/src/daemon/computer-use-session.ts +1 -1
- package/src/daemon/handlers/apps.ts +1 -0
- package/src/daemon/handlers/config-channels.ts +3 -3
- package/src/daemon/handlers/config-dispatch.ts +29 -0
- package/src/daemon/handlers/config-inbox.ts +4 -3
- package/src/daemon/handlers/config.ts +3 -43
- package/src/daemon/handlers/contacts.ts +34 -0
- package/src/daemon/handlers/index.ts +17 -3
- package/src/daemon/handlers/session-user-message.ts +7 -0
- package/src/daemon/handlers/sessions.ts +21 -2
- package/src/daemon/handlers/shared.ts +17 -0
- package/src/daemon/ipc-contract/apps.ts +2 -0
- package/src/daemon/ipc-contract/computer-use.ts +9 -0
- package/src/daemon/ipc-contract/contacts.ts +3 -3
- package/src/daemon/ipc-contract/inbox.ts +2 -0
- package/src/daemon/ipc-contract/messages.ts +4 -0
- package/src/daemon/ipc-contract/sessions.ts +8 -0
- package/src/daemon/ipc-contract-inventory.json +1 -0
- package/src/daemon/lifecycle.ts +0 -5
- package/src/daemon/ride-shotgun-handler.ts +139 -25
- package/src/daemon/session-agent-loop-handlers.ts +100 -0
- package/src/daemon/session-agent-loop.ts +72 -0
- package/src/daemon/session-tool-setup.ts +7 -0
- package/src/daemon/session.ts +23 -1
- package/src/daemon/tool-side-effects.ts +39 -1
- package/src/email/service.ts +59 -2
- package/src/index.ts +2 -60
- package/src/mcp/mcp-oauth-provider.ts +90 -8
- package/src/media/app-icon-generator.ts +86 -0
- package/src/memory/db-init.ts +11 -0
- package/src/memory/llm-usage-store.ts +186 -0
- package/src/memory/migrations/137-usage-dashboard-indexes.ts +26 -0
- package/src/memory/migrations/139-drop-usage-composite-indexes.ts +30 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/schema-migration.ts +1 -0
- package/src/memory/shared-app-links-store.ts +1 -1
- package/src/messaging/registry.ts +27 -0
- package/src/notifications/README.md +79 -70
- package/src/notifications/broadcaster.ts +2 -1
- package/src/notifications/conversation-pairing.ts +147 -13
- package/src/notifications/copy-composer.ts +7 -3
- package/src/notifications/destination-resolver.ts +14 -1
- package/src/notifications/emit-signal.ts +3 -2
- package/src/notifications/signal.ts +105 -1
- package/src/notifications/types.ts +16 -0
- package/src/permissions/checker.ts +29 -3
- package/src/permissions/prompter.ts +11 -3
- package/src/runtime/access-request-helper.ts +2 -1
- package/src/runtime/auth/route-policy.ts +7 -1
- package/src/runtime/channel-invite-transport.ts +40 -63
- package/src/runtime/channel-invite-transports/email.ts +13 -39
- package/src/runtime/channel-invite-transports/slack.ts +5 -34
- package/src/runtime/channel-invite-transports/sms.ts +8 -29
- package/src/runtime/channel-invite-transports/telegram.ts +69 -28
- package/src/runtime/channel-invite-transports/voice.ts +0 -7
- package/src/runtime/channel-invite-transports/whatsapp.ts +43 -0
- package/src/runtime/channel-readiness-service.ts +202 -45
- package/src/runtime/confirmation-request-guardian-bridge.ts +2 -1
- package/src/runtime/guardian-outbound-actions.ts +8 -5
- package/src/runtime/http-server.ts +2 -0
- package/src/runtime/invite-instruction-generator.ts +178 -0
- package/src/runtime/invite-service.ts +22 -25
- package/src/runtime/migrations/migration-transport.ts +13 -0
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +8 -7
- package/src/runtime/routes/channel-readiness-routes.ts +30 -11
- package/src/runtime/routes/contact-routes.ts +54 -26
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +1 -1
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +2 -1
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +2 -1
- package/src/runtime/routes/integration-routes.ts +1 -1
- package/src/runtime/routes/invite-routes.ts +1 -1
- package/src/runtime/routes/secret-routes.ts +31 -7
- package/src/runtime/routes/twilio-routes.ts +32 -1
- package/src/runtime/routes/usage-routes.ts +114 -0
- package/src/runtime/tool-grant-request-helper.ts +2 -1
- package/src/security/encrypted-store.ts +9 -5
- package/src/security/keychain-broker-client.ts +393 -0
- package/src/security/secure-keys.ts +106 -321
- package/src/tools/apps/executors.ts +73 -0
- package/src/tools/browser/auto-navigate.ts +15 -6
- package/src/tools/browser/chrome-cdp.ts +211 -0
- package/src/tools/browser/network-recorder.test.ts +83 -0
- package/src/tools/browser/network-recorder.ts +8 -7
- package/src/tools/browser/x-auto-navigate.ts +12 -6
- package/src/tools/credentials/policy-types.ts +24 -0
- package/src/tools/credentials/vault.ts +22 -27
- package/src/tools/network/script-proxy/session-manager.ts +47 -3
- package/src/tools/permission-checker.ts +1 -0
- package/src/tools/types.ts +2 -0
- package/src/tools/ui-surface/definitions.ts +1 -2
- package/src/tools/watch/watch-state.ts +2 -0
- package/src/__tests__/key-migration.test.ts +0 -240
- package/src/__tests__/keychain.test.ts +0 -286
- package/src/cli/core-commands.ts +0 -899
- package/src/security/keychain-to-encrypted-migration.ts +0 -66
- package/src/security/keychain.ts +0 -490
|
@@ -1358,7 +1358,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1358
1358
|
resetTables();
|
|
1359
1359
|
});
|
|
1360
1360
|
|
|
1361
|
-
test("status action for telegram returns channel and assistantId fields", () => {
|
|
1361
|
+
test("status action for telegram returns channel and assistantId fields", async () => {
|
|
1362
1362
|
const { ctx, lastResponse } = createMockCtx();
|
|
1363
1363
|
const msg: GuardianVerificationRequest = {
|
|
1364
1364
|
type: "guardian_verification",
|
|
@@ -1366,7 +1366,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1366
1366
|
channel: "telegram",
|
|
1367
1367
|
};
|
|
1368
1368
|
|
|
1369
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
1369
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
1370
1370
|
|
|
1371
1371
|
const resp = lastResponse();
|
|
1372
1372
|
expect(resp).not.toBeNull();
|
|
@@ -1377,7 +1377,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1377
1377
|
expect(resp!.guardianDeliveryChatId).toBeUndefined();
|
|
1378
1378
|
});
|
|
1379
1379
|
|
|
1380
|
-
test("status action for sms returns channel: sms and assistantId: self", () => {
|
|
1380
|
+
test("status action for sms returns channel: sms and assistantId: self", async () => {
|
|
1381
1381
|
const { ctx, lastResponse } = createMockCtx();
|
|
1382
1382
|
const msg: GuardianVerificationRequest = {
|
|
1383
1383
|
type: "guardian_verification",
|
|
@@ -1385,7 +1385,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1385
1385
|
channel: "sms",
|
|
1386
1386
|
};
|
|
1387
1387
|
|
|
1388
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
1388
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
1389
1389
|
|
|
1390
1390
|
const resp = lastResponse();
|
|
1391
1391
|
expect(resp).not.toBeNull();
|
|
@@ -1395,7 +1395,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1395
1395
|
expect(resp!.bound).toBe(false);
|
|
1396
1396
|
});
|
|
1397
1397
|
|
|
1398
|
-
test("status action returns guardianDeliveryChatId when bound", () => {
|
|
1398
|
+
test("status action returns guardianDeliveryChatId when bound", async () => {
|
|
1399
1399
|
createGuardianBinding({
|
|
1400
1400
|
channel: "telegram",
|
|
1401
1401
|
guardianExternalUserId: "user-42",
|
|
@@ -1410,7 +1410,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1410
1410
|
channel: "telegram",
|
|
1411
1411
|
};
|
|
1412
1412
|
|
|
1413
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
1413
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
1414
1414
|
|
|
1415
1415
|
const resp = lastResponse();
|
|
1416
1416
|
expect(resp).not.toBeNull();
|
|
@@ -1422,7 +1422,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1422
1422
|
expect(resp!.assistantId).toBe("self");
|
|
1423
1423
|
});
|
|
1424
1424
|
|
|
1425
|
-
test("status action returns guardian username/displayName from binding metadata", () => {
|
|
1425
|
+
test("status action returns guardian username/displayName from binding metadata", async () => {
|
|
1426
1426
|
createGuardianBinding({
|
|
1427
1427
|
channel: "telegram",
|
|
1428
1428
|
guardianExternalUserId: "user-43",
|
|
@@ -1462,7 +1462,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1462
1462
|
channel: "telegram",
|
|
1463
1463
|
};
|
|
1464
1464
|
|
|
1465
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
1465
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
1466
1466
|
|
|
1467
1467
|
const resp = lastResponse();
|
|
1468
1468
|
expect(resp).not.toBeNull();
|
|
@@ -1470,7 +1470,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1470
1470
|
expect(resp!.guardianDisplayName).toBe("Guardian Name");
|
|
1471
1471
|
});
|
|
1472
1472
|
|
|
1473
|
-
test("status action defaults channel to telegram when omitted (backward compat)", () => {
|
|
1473
|
+
test("status action defaults channel to telegram when omitted (backward compat)", async () => {
|
|
1474
1474
|
const { ctx, lastResponse } = createMockCtx();
|
|
1475
1475
|
const msg: GuardianVerificationRequest = {
|
|
1476
1476
|
type: "guardian_verification",
|
|
@@ -1478,7 +1478,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1478
1478
|
// channel omitted — should default to 'telegram'
|
|
1479
1479
|
};
|
|
1480
1480
|
|
|
1481
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
1481
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
1482
1482
|
|
|
1483
1483
|
const resp = lastResponse();
|
|
1484
1484
|
expect(resp).not.toBeNull();
|
|
@@ -1486,7 +1486,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1486
1486
|
expect(resp!.assistantId).toBe("self");
|
|
1487
1487
|
});
|
|
1488
1488
|
|
|
1489
|
-
test("status action defaults assistantId to self when omitted (backward compat)", () => {
|
|
1489
|
+
test("status action defaults assistantId to self when omitted (backward compat)", async () => {
|
|
1490
1490
|
const { ctx, lastResponse } = createMockCtx();
|
|
1491
1491
|
const msg: GuardianVerificationRequest = {
|
|
1492
1492
|
type: "guardian_verification",
|
|
@@ -1495,7 +1495,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1495
1495
|
// assistantId omitted — should default to 'self'
|
|
1496
1496
|
};
|
|
1497
1497
|
|
|
1498
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
1498
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
1499
1499
|
|
|
1500
1500
|
const resp = lastResponse();
|
|
1501
1501
|
expect(resp).not.toBeNull();
|
|
@@ -1503,7 +1503,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1503
1503
|
expect(resp!.channel).toBe("sms");
|
|
1504
1504
|
});
|
|
1505
1505
|
|
|
1506
|
-
test("status action for unbound sms does not return guardianDeliveryChatId", () => {
|
|
1506
|
+
test("status action for unbound sms does not return guardianDeliveryChatId", async () => {
|
|
1507
1507
|
const { ctx, lastResponse } = createMockCtx();
|
|
1508
1508
|
const msg: GuardianVerificationRequest = {
|
|
1509
1509
|
type: "guardian_verification",
|
|
@@ -1511,7 +1511,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1511
1511
|
channel: "sms",
|
|
1512
1512
|
};
|
|
1513
1513
|
|
|
1514
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
1514
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
1515
1515
|
|
|
1516
1516
|
const resp = lastResponse();
|
|
1517
1517
|
expect(resp).not.toBeNull();
|
|
@@ -1520,7 +1520,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1520
1520
|
expect(resp!.guardianExternalUserId).toBeUndefined();
|
|
1521
1521
|
});
|
|
1522
1522
|
|
|
1523
|
-
test("status action includes hasPendingChallenge when challenge exists", () => {
|
|
1523
|
+
test("status action includes hasPendingChallenge when challenge exists", async () => {
|
|
1524
1524
|
createVerificationChallenge("voice");
|
|
1525
1525
|
|
|
1526
1526
|
const { ctx, lastResponse } = createMockCtx();
|
|
@@ -1530,7 +1530,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1530
1530
|
channel: "voice",
|
|
1531
1531
|
};
|
|
1532
1532
|
|
|
1533
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
1533
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
1534
1534
|
|
|
1535
1535
|
const resp = lastResponse();
|
|
1536
1536
|
expect(resp).not.toBeNull();
|
|
@@ -1538,7 +1538,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1538
1538
|
expect(resp!.hasPendingChallenge).toBe(true);
|
|
1539
1539
|
});
|
|
1540
1540
|
|
|
1541
|
-
test("status action hasPendingChallenge is false when no challenge exists", () => {
|
|
1541
|
+
test("status action hasPendingChallenge is false when no challenge exists", async () => {
|
|
1542
1542
|
const { ctx, lastResponse } = createMockCtx();
|
|
1543
1543
|
const msg: GuardianVerificationRequest = {
|
|
1544
1544
|
type: "guardian_verification",
|
|
@@ -1546,7 +1546,7 @@ describe("IPC handler channel-aware guardian status", () => {
|
|
|
1546
1546
|
channel: "voice",
|
|
1547
1547
|
};
|
|
1548
1548
|
|
|
1549
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
1549
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
1550
1550
|
|
|
1551
1551
|
const resp = lastResponse();
|
|
1552
1552
|
expect(resp).not.toBeNull();
|
|
@@ -1982,7 +1982,7 @@ describe("IPC handler voice guardian verification", () => {
|
|
|
1982
1982
|
resetTables();
|
|
1983
1983
|
});
|
|
1984
1984
|
|
|
1985
|
-
test("create_challenge for voice returns a high-entropy hex secret", () => {
|
|
1985
|
+
test("create_challenge for voice returns a high-entropy hex secret", async () => {
|
|
1986
1986
|
const { ctx, lastResponse } = createMockCtx();
|
|
1987
1987
|
const msg: GuardianVerificationRequest = {
|
|
1988
1988
|
type: "guardian_verification",
|
|
@@ -1990,7 +1990,7 @@ describe("IPC handler voice guardian verification", () => {
|
|
|
1990
1990
|
channel: "voice",
|
|
1991
1991
|
};
|
|
1992
1992
|
|
|
1993
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
1993
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
1994
1994
|
|
|
1995
1995
|
const resp = lastResponse();
|
|
1996
1996
|
expect(resp).not.toBeNull();
|
|
@@ -2002,7 +2002,7 @@ describe("IPC handler voice guardian verification", () => {
|
|
|
2002
2002
|
expect(resp!.channel).toBe("voice");
|
|
2003
2003
|
});
|
|
2004
2004
|
|
|
2005
|
-
test("status for voice reflects unbound state", () => {
|
|
2005
|
+
test("status for voice reflects unbound state", async () => {
|
|
2006
2006
|
const { ctx, lastResponse } = createMockCtx();
|
|
2007
2007
|
const msg: GuardianVerificationRequest = {
|
|
2008
2008
|
type: "guardian_verification",
|
|
@@ -2010,7 +2010,7 @@ describe("IPC handler voice guardian verification", () => {
|
|
|
2010
2010
|
channel: "voice",
|
|
2011
2011
|
};
|
|
2012
2012
|
|
|
2013
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
2013
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
2014
2014
|
|
|
2015
2015
|
const resp = lastResponse();
|
|
2016
2016
|
expect(resp).not.toBeNull();
|
|
@@ -2020,7 +2020,7 @@ describe("IPC handler voice guardian verification", () => {
|
|
|
2020
2020
|
expect(resp!.guardianExternalUserId).toBeUndefined();
|
|
2021
2021
|
});
|
|
2022
2022
|
|
|
2023
|
-
test("status for voice reflects bound state", () => {
|
|
2023
|
+
test("status for voice reflects bound state", async () => {
|
|
2024
2024
|
createGuardianBinding({
|
|
2025
2025
|
channel: "voice",
|
|
2026
2026
|
guardianExternalUserId: "voice-user-1",
|
|
@@ -2035,7 +2035,7 @@ describe("IPC handler voice guardian verification", () => {
|
|
|
2035
2035
|
channel: "voice",
|
|
2036
2036
|
};
|
|
2037
2037
|
|
|
2038
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
2038
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
2039
2039
|
|
|
2040
2040
|
const resp = lastResponse();
|
|
2041
2041
|
expect(resp).not.toBeNull();
|
|
@@ -2046,7 +2046,7 @@ describe("IPC handler voice guardian verification", () => {
|
|
|
2046
2046
|
expect(resp!.channel).toBe("voice");
|
|
2047
2047
|
});
|
|
2048
2048
|
|
|
2049
|
-
test("revoke for voice clears active binding", () => {
|
|
2049
|
+
test("revoke for voice clears active binding", async () => {
|
|
2050
2050
|
createGuardianBinding({
|
|
2051
2051
|
channel: "voice",
|
|
2052
2052
|
guardianExternalUserId: "voice-user-1",
|
|
@@ -2061,7 +2061,7 @@ describe("IPC handler voice guardian verification", () => {
|
|
|
2061
2061
|
channel: "voice",
|
|
2062
2062
|
};
|
|
2063
2063
|
|
|
2064
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
2064
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
2065
2065
|
|
|
2066
2066
|
const resp = lastResponse();
|
|
2067
2067
|
expect(resp).not.toBeNull();
|
|
@@ -2072,7 +2072,7 @@ describe("IPC handler voice guardian verification", () => {
|
|
|
2072
2072
|
expect(getGuardianBinding("self", "voice")).toBeNull();
|
|
2073
2073
|
});
|
|
2074
2074
|
|
|
2075
|
-
test("revoke for voice does not affect telegram binding", () => {
|
|
2075
|
+
test("revoke for voice does not affect telegram binding", async () => {
|
|
2076
2076
|
createGuardianBinding({
|
|
2077
2077
|
channel: "voice",
|
|
2078
2078
|
guardianExternalUserId: "voice-user-1",
|
|
@@ -2093,7 +2093,7 @@ describe("IPC handler voice guardian verification", () => {
|
|
|
2093
2093
|
channel: "voice",
|
|
2094
2094
|
};
|
|
2095
2095
|
|
|
2096
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
2096
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
2097
2097
|
|
|
2098
2098
|
expect(getGuardianBinding("self", "voice")).toBeNull();
|
|
2099
2099
|
expect(getGuardianBinding("self", "telegram")).not.toBeNull();
|
|
@@ -2568,7 +2568,7 @@ describe("outbound SMS verification", () => {
|
|
|
2568
2568
|
resetTables();
|
|
2569
2569
|
});
|
|
2570
2570
|
|
|
2571
|
-
test("start_outbound creates session with expected E.164 identity and returns code", () => {
|
|
2571
|
+
test("start_outbound creates session with expected E.164 identity and returns code", async () => {
|
|
2572
2572
|
const { ctx, lastResponse } = createMockCtx();
|
|
2573
2573
|
const msg: GuardianVerificationRequest = {
|
|
2574
2574
|
type: "guardian_verification",
|
|
@@ -2577,7 +2577,7 @@ describe("outbound SMS verification", () => {
|
|
|
2577
2577
|
destination: "+15551234567",
|
|
2578
2578
|
};
|
|
2579
2579
|
|
|
2580
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
2580
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
2581
2581
|
|
|
2582
2582
|
const resp = lastResponse();
|
|
2583
2583
|
expect(resp).not.toBeNull();
|
|
@@ -2596,7 +2596,7 @@ describe("outbound SMS verification", () => {
|
|
|
2596
2596
|
expect(session!.destinationAddress).toBe("+15551234567");
|
|
2597
2597
|
});
|
|
2598
2598
|
|
|
2599
|
-
test("start_outbound rejects when active binding exists (rebind=false)", () => {
|
|
2599
|
+
test("start_outbound rejects when active binding exists (rebind=false)", async () => {
|
|
2600
2600
|
// Create an existing guardian binding
|
|
2601
2601
|
createGuardianBinding({
|
|
2602
2602
|
channel: "sms",
|
|
@@ -2614,7 +2614,7 @@ describe("outbound SMS verification", () => {
|
|
|
2614
2614
|
rebind: false,
|
|
2615
2615
|
};
|
|
2616
2616
|
|
|
2617
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
2617
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
2618
2618
|
|
|
2619
2619
|
const resp = lastResponse();
|
|
2620
2620
|
expect(resp).not.toBeNull();
|
|
@@ -2622,7 +2622,7 @@ describe("outbound SMS verification", () => {
|
|
|
2622
2622
|
expect(resp!.error).toBe("already_bound");
|
|
2623
2623
|
});
|
|
2624
2624
|
|
|
2625
|
-
test("start_outbound allows rebind when rebind=true", () => {
|
|
2625
|
+
test("start_outbound allows rebind when rebind=true", async () => {
|
|
2626
2626
|
// Create an existing guardian binding
|
|
2627
2627
|
createGuardianBinding({
|
|
2628
2628
|
channel: "sms",
|
|
@@ -2640,7 +2640,7 @@ describe("outbound SMS verification", () => {
|
|
|
2640
2640
|
rebind: true,
|
|
2641
2641
|
};
|
|
2642
2642
|
|
|
2643
|
-
handleGuardianVerification(msg, mockSocket, ctx);
|
|
2643
|
+
await handleGuardianVerification(msg, mockSocket, ctx);
|
|
2644
2644
|
|
|
2645
2645
|
const resp = lastResponse();
|
|
2646
2646
|
expect(resp).not.toBeNull();
|
|
@@ -2648,10 +2648,10 @@ describe("outbound SMS verification", () => {
|
|
|
2648
2648
|
expect(resp!.verificationSessionId).toBeDefined();
|
|
2649
2649
|
});
|
|
2650
2650
|
|
|
2651
|
-
test("resend_outbound before cooldown is rejected", () => {
|
|
2651
|
+
test("resend_outbound before cooldown is rejected", async () => {
|
|
2652
2652
|
// Start an outbound session first
|
|
2653
2653
|
const { ctx: startCtx } = createMockCtx();
|
|
2654
|
-
handleGuardianVerification(
|
|
2654
|
+
await handleGuardianVerification(
|
|
2655
2655
|
{
|
|
2656
2656
|
type: "guardian_verification",
|
|
2657
2657
|
action: "start_outbound",
|
|
@@ -2664,7 +2664,7 @@ describe("outbound SMS verification", () => {
|
|
|
2664
2664
|
|
|
2665
2665
|
// Immediately try to resend (before cooldown)
|
|
2666
2666
|
const { ctx, lastResponse } = createMockCtx();
|
|
2667
|
-
handleGuardianVerification(
|
|
2667
|
+
await handleGuardianVerification(
|
|
2668
2668
|
{
|
|
2669
2669
|
type: "guardian_verification",
|
|
2670
2670
|
action: "resend_outbound",
|
|
@@ -2680,10 +2680,10 @@ describe("outbound SMS verification", () => {
|
|
|
2680
2680
|
expect(resp!.error).toBe("rate_limited");
|
|
2681
2681
|
});
|
|
2682
2682
|
|
|
2683
|
-
test("resend_outbound after cooldown succeeds and increments sendCount", () => {
|
|
2683
|
+
test("resend_outbound after cooldown succeeds and increments sendCount", async () => {
|
|
2684
2684
|
// Start an outbound session
|
|
2685
2685
|
const { ctx: startCtx, lastResponse: startResp } = createMockCtx();
|
|
2686
|
-
handleGuardianVerification(
|
|
2686
|
+
await handleGuardianVerification(
|
|
2687
2687
|
{
|
|
2688
2688
|
type: "guardian_verification",
|
|
2689
2689
|
action: "start_outbound",
|
|
@@ -2709,7 +2709,7 @@ describe("outbound SMS verification", () => {
|
|
|
2709
2709
|
|
|
2710
2710
|
// Now resend should succeed
|
|
2711
2711
|
const { ctx, lastResponse } = createMockCtx();
|
|
2712
|
-
handleGuardianVerification(
|
|
2712
|
+
await handleGuardianVerification(
|
|
2713
2713
|
{
|
|
2714
2714
|
type: "guardian_verification",
|
|
2715
2715
|
action: "resend_outbound",
|
|
@@ -2726,10 +2726,10 @@ describe("outbound SMS verification", () => {
|
|
|
2726
2726
|
expect(resp!.nextResendAt).toBeGreaterThan(Date.now());
|
|
2727
2727
|
});
|
|
2728
2728
|
|
|
2729
|
-
test("resend_outbound exceeding max sends is rejected", () => {
|
|
2729
|
+
test("resend_outbound exceeding max sends is rejected", async () => {
|
|
2730
2730
|
// Start an outbound session
|
|
2731
2731
|
const { ctx: startCtx } = createMockCtx();
|
|
2732
|
-
handleGuardianVerification(
|
|
2732
|
+
await handleGuardianVerification(
|
|
2733
2733
|
{
|
|
2734
2734
|
type: "guardian_verification",
|
|
2735
2735
|
action: "start_outbound",
|
|
@@ -2752,7 +2752,7 @@ describe("outbound SMS verification", () => {
|
|
|
2752
2752
|
|
|
2753
2753
|
// Resend should be rejected due to max sends
|
|
2754
2754
|
const { ctx, lastResponse } = createMockCtx();
|
|
2755
|
-
handleGuardianVerification(
|
|
2755
|
+
await handleGuardianVerification(
|
|
2756
2756
|
{
|
|
2757
2757
|
type: "guardian_verification",
|
|
2758
2758
|
action: "resend_outbound",
|
|
@@ -2768,10 +2768,10 @@ describe("outbound SMS verification", () => {
|
|
|
2768
2768
|
expect(resp!.error).toBe("max_sends_exceeded");
|
|
2769
2769
|
});
|
|
2770
2770
|
|
|
2771
|
-
test("cancel_outbound revokes active session", () => {
|
|
2771
|
+
test("cancel_outbound revokes active session", async () => {
|
|
2772
2772
|
// Start an outbound session
|
|
2773
2773
|
const { ctx: startCtx } = createMockCtx();
|
|
2774
|
-
handleGuardianVerification(
|
|
2774
|
+
await handleGuardianVerification(
|
|
2775
2775
|
{
|
|
2776
2776
|
type: "guardian_verification",
|
|
2777
2777
|
action: "start_outbound",
|
|
@@ -2788,7 +2788,7 @@ describe("outbound SMS verification", () => {
|
|
|
2788
2788
|
|
|
2789
2789
|
// Cancel it
|
|
2790
2790
|
const { ctx, lastResponse } = createMockCtx();
|
|
2791
|
-
handleGuardianVerification(
|
|
2791
|
+
await handleGuardianVerification(
|
|
2792
2792
|
{
|
|
2793
2793
|
type: "guardian_verification",
|
|
2794
2794
|
action: "cancel_outbound",
|
|
@@ -2880,9 +2880,9 @@ describe("outbound SMS verification", () => {
|
|
|
2880
2880
|
expect(alreadySms).toContain("already verified");
|
|
2881
2881
|
});
|
|
2882
2882
|
|
|
2883
|
-
test("start_outbound rejects unsupported channels", () => {
|
|
2883
|
+
test("start_outbound rejects unsupported channels", async () => {
|
|
2884
2884
|
const { ctx, lastResponse } = createMockCtx();
|
|
2885
|
-
handleGuardianVerification(
|
|
2885
|
+
await handleGuardianVerification(
|
|
2886
2886
|
{
|
|
2887
2887
|
type: "guardian_verification",
|
|
2888
2888
|
action: "start_outbound",
|
|
@@ -2899,9 +2899,9 @@ describe("outbound SMS verification", () => {
|
|
|
2899
2899
|
expect(resp!.error).toBe("unsupported_channel");
|
|
2900
2900
|
});
|
|
2901
2901
|
|
|
2902
|
-
test("start_outbound rejects missing destination", () => {
|
|
2902
|
+
test("start_outbound rejects missing destination", async () => {
|
|
2903
2903
|
const { ctx, lastResponse } = createMockCtx();
|
|
2904
|
-
handleGuardianVerification(
|
|
2904
|
+
await handleGuardianVerification(
|
|
2905
2905
|
{
|
|
2906
2906
|
type: "guardian_verification",
|
|
2907
2907
|
action: "start_outbound",
|
|
@@ -2918,9 +2918,9 @@ describe("outbound SMS verification", () => {
|
|
|
2918
2918
|
expect(resp!.error).toBe("missing_destination");
|
|
2919
2919
|
});
|
|
2920
2920
|
|
|
2921
|
-
test("start_outbound rejects unparseable phone number", () => {
|
|
2921
|
+
test("start_outbound rejects unparseable phone number", async () => {
|
|
2922
2922
|
const { ctx, lastResponse } = createMockCtx();
|
|
2923
|
-
handleGuardianVerification(
|
|
2923
|
+
await handleGuardianVerification(
|
|
2924
2924
|
{
|
|
2925
2925
|
type: "guardian_verification",
|
|
2926
2926
|
action: "start_outbound",
|
|
@@ -2939,7 +2939,7 @@ describe("outbound SMS verification", () => {
|
|
|
2939
2939
|
|
|
2940
2940
|
test("start_outbound normalizes formatted phone number for SMS", async () => {
|
|
2941
2941
|
const { ctx, lastResponse } = createMockCtx();
|
|
2942
|
-
handleGuardianVerification(
|
|
2942
|
+
await handleGuardianVerification(
|
|
2943
2943
|
{
|
|
2944
2944
|
type: "guardian_verification",
|
|
2945
2945
|
action: "start_outbound",
|
|
@@ -2981,9 +2981,9 @@ describe("outbound SMS verification", () => {
|
|
|
2981
2981
|
expect(sms).not.toContain("999999");
|
|
2982
2982
|
});
|
|
2983
2983
|
|
|
2984
|
-
test("cancel_outbound returns error when no active session", () => {
|
|
2984
|
+
test("cancel_outbound returns error when no active session", async () => {
|
|
2985
2985
|
const { ctx, lastResponse } = createMockCtx();
|
|
2986
|
-
handleGuardianVerification(
|
|
2986
|
+
await handleGuardianVerification(
|
|
2987
2987
|
{
|
|
2988
2988
|
type: "guardian_verification",
|
|
2989
2989
|
action: "cancel_outbound",
|
|
@@ -3009,9 +3009,9 @@ describe("outbound Telegram verification", () => {
|
|
|
3009
3009
|
resetTables();
|
|
3010
3010
|
});
|
|
3011
3011
|
|
|
3012
|
-
test("start_outbound for telegram with handle returns deep link URL, no outbound message", () => {
|
|
3012
|
+
test("start_outbound for telegram with handle returns deep link URL, no outbound message", async () => {
|
|
3013
3013
|
const { ctx, lastResponse } = createMockCtx();
|
|
3014
|
-
handleGuardianVerification(
|
|
3014
|
+
await handleGuardianVerification(
|
|
3015
3015
|
{
|
|
3016
3016
|
type: "guardian_verification",
|
|
3017
3017
|
action: "start_outbound",
|
|
@@ -3044,9 +3044,9 @@ describe("outbound Telegram verification", () => {
|
|
|
3044
3044
|
expect(session!.bootstrapTokenHash).not.toBeNull();
|
|
3045
3045
|
});
|
|
3046
3046
|
|
|
3047
|
-
test("start_outbound for telegram with handle (no @ prefix) returns deep link", () => {
|
|
3047
|
+
test("start_outbound for telegram with handle (no @ prefix) returns deep link", async () => {
|
|
3048
3048
|
const { ctx, lastResponse } = createMockCtx();
|
|
3049
|
-
handleGuardianVerification(
|
|
3049
|
+
await handleGuardianVerification(
|
|
3050
3050
|
{
|
|
3051
3051
|
type: "guardian_verification",
|
|
3052
3052
|
action: "start_outbound",
|
|
@@ -3068,7 +3068,7 @@ describe("outbound Telegram verification", () => {
|
|
|
3068
3068
|
|
|
3069
3069
|
test("start_outbound for telegram with known chat ID sends message, no deep link", async () => {
|
|
3070
3070
|
const { ctx, lastResponse } = createMockCtx();
|
|
3071
|
-
handleGuardianVerification(
|
|
3071
|
+
await handleGuardianVerification(
|
|
3072
3072
|
{
|
|
3073
3073
|
type: "guardian_verification",
|
|
3074
3074
|
action: "start_outbound",
|
|
@@ -3105,11 +3105,11 @@ describe("outbound Telegram verification", () => {
|
|
|
3105
3105
|
expect(telegramDeliverCalls[0].text).toContain("code you were given");
|
|
3106
3106
|
});
|
|
3107
3107
|
|
|
3108
|
-
test("start_outbound for telegram without bot username fails", () => {
|
|
3108
|
+
test("start_outbound for telegram without bot username fails", async () => {
|
|
3109
3109
|
mockBotUsername = undefined;
|
|
3110
3110
|
|
|
3111
3111
|
const { ctx, lastResponse } = createMockCtx();
|
|
3112
|
-
handleGuardianVerification(
|
|
3112
|
+
await handleGuardianVerification(
|
|
3113
3113
|
{
|
|
3114
3114
|
type: "guardian_verification",
|
|
3115
3115
|
action: "start_outbound",
|
|
@@ -3126,7 +3126,7 @@ describe("outbound Telegram verification", () => {
|
|
|
3126
3126
|
expect(resp!.error).toBe("no_bot_username");
|
|
3127
3127
|
});
|
|
3128
3128
|
|
|
3129
|
-
test("start_outbound for telegram rejects when active binding exists (rebind=false)", () => {
|
|
3129
|
+
test("start_outbound for telegram rejects when active binding exists (rebind=false)", async () => {
|
|
3130
3130
|
createGuardianBinding({
|
|
3131
3131
|
channel: "telegram",
|
|
3132
3132
|
guardianExternalUserId: "user-42",
|
|
@@ -3135,7 +3135,7 @@ describe("outbound Telegram verification", () => {
|
|
|
3135
3135
|
});
|
|
3136
3136
|
|
|
3137
3137
|
const { ctx, lastResponse } = createMockCtx();
|
|
3138
|
-
handleGuardianVerification(
|
|
3138
|
+
await handleGuardianVerification(
|
|
3139
3139
|
{
|
|
3140
3140
|
type: "guardian_verification",
|
|
3141
3141
|
action: "start_outbound",
|
|
@@ -3299,7 +3299,7 @@ describe("outbound Telegram verification", () => {
|
|
|
3299
3299
|
test("resend_outbound for telegram works with known chat ID", async () => {
|
|
3300
3300
|
// Start an outbound session with a known chat ID
|
|
3301
3301
|
const { ctx: startCtx } = createMockCtx();
|
|
3302
|
-
handleGuardianVerification(
|
|
3302
|
+
await handleGuardianVerification(
|
|
3303
3303
|
{
|
|
3304
3304
|
type: "guardian_verification",
|
|
3305
3305
|
action: "start_outbound",
|
|
@@ -3321,7 +3321,7 @@ describe("outbound Telegram verification", () => {
|
|
|
3321
3321
|
);
|
|
3322
3322
|
|
|
3323
3323
|
const { ctx, lastResponse } = createMockCtx();
|
|
3324
|
-
handleGuardianVerification(
|
|
3324
|
+
await handleGuardianVerification(
|
|
3325
3325
|
{
|
|
3326
3326
|
type: "guardian_verification",
|
|
3327
3327
|
action: "resend_outbound",
|
|
@@ -3342,10 +3342,10 @@ describe("outbound Telegram verification", () => {
|
|
|
3342
3342
|
expect(telegramDeliverCalls.length).toBeGreaterThanOrEqual(2);
|
|
3343
3343
|
});
|
|
3344
3344
|
|
|
3345
|
-
test("resend_outbound for pending_bootstrap session is rejected", () => {
|
|
3345
|
+
test("resend_outbound for pending_bootstrap session is rejected", async () => {
|
|
3346
3346
|
// Start an outbound session with a handle (pending_bootstrap)
|
|
3347
3347
|
const { ctx: startCtx } = createMockCtx();
|
|
3348
|
-
handleGuardianVerification(
|
|
3348
|
+
await handleGuardianVerification(
|
|
3349
3349
|
{
|
|
3350
3350
|
type: "guardian_verification",
|
|
3351
3351
|
action: "start_outbound",
|
|
@@ -3357,7 +3357,7 @@ describe("outbound Telegram verification", () => {
|
|
|
3357
3357
|
);
|
|
3358
3358
|
|
|
3359
3359
|
const { ctx, lastResponse } = createMockCtx();
|
|
3360
|
-
handleGuardianVerification(
|
|
3360
|
+
await handleGuardianVerification(
|
|
3361
3361
|
{
|
|
3362
3362
|
type: "guardian_verification",
|
|
3363
3363
|
action: "resend_outbound",
|
|
@@ -3373,10 +3373,10 @@ describe("outbound Telegram verification", () => {
|
|
|
3373
3373
|
expect(resp!.error).toBe("pending_bootstrap");
|
|
3374
3374
|
});
|
|
3375
3375
|
|
|
3376
|
-
test("cancel_outbound for telegram revokes session", () => {
|
|
3376
|
+
test("cancel_outbound for telegram revokes session", async () => {
|
|
3377
3377
|
// Start an outbound session
|
|
3378
3378
|
const { ctx: startCtx } = createMockCtx();
|
|
3379
|
-
handleGuardianVerification(
|
|
3379
|
+
await handleGuardianVerification(
|
|
3380
3380
|
{
|
|
3381
3381
|
type: "guardian_verification",
|
|
3382
3382
|
action: "start_outbound",
|
|
@@ -3391,7 +3391,7 @@ describe("outbound Telegram verification", () => {
|
|
|
3391
3391
|
expect(session).not.toBeNull();
|
|
3392
3392
|
|
|
3393
3393
|
const { ctx, lastResponse } = createMockCtx();
|
|
3394
|
-
handleGuardianVerification(
|
|
3394
|
+
await handleGuardianVerification(
|
|
3395
3395
|
{
|
|
3396
3396
|
type: "guardian_verification",
|
|
3397
3397
|
action: "cancel_outbound",
|
|
@@ -3438,9 +3438,9 @@ describe("outbound Telegram verification", () => {
|
|
|
3438
3438
|
expect(msg).not.toContain("999999");
|
|
3439
3439
|
});
|
|
3440
3440
|
|
|
3441
|
-
test("start_outbound for telegram with missing destination fails", () => {
|
|
3441
|
+
test("start_outbound for telegram with missing destination fails", async () => {
|
|
3442
3442
|
const { ctx, lastResponse } = createMockCtx();
|
|
3443
|
-
handleGuardianVerification(
|
|
3443
|
+
await handleGuardianVerification(
|
|
3444
3444
|
{
|
|
3445
3445
|
type: "guardian_verification",
|
|
3446
3446
|
action: "start_outbound",
|
|
@@ -3456,10 +3456,10 @@ describe("outbound Telegram verification", () => {
|
|
|
3456
3456
|
expect(resp!.error).toBe("missing_destination");
|
|
3457
3457
|
});
|
|
3458
3458
|
|
|
3459
|
-
test("rate limits apply to telegram outbound (per-session send cap)", () => {
|
|
3459
|
+
test("rate limits apply to telegram outbound (per-session send cap)", async () => {
|
|
3460
3460
|
// Start an outbound session with a known chat ID
|
|
3461
3461
|
const { ctx: startCtx } = createMockCtx();
|
|
3462
|
-
handleGuardianVerification(
|
|
3462
|
+
await handleGuardianVerification(
|
|
3463
3463
|
{
|
|
3464
3464
|
type: "guardian_verification",
|
|
3465
3465
|
action: "start_outbound",
|
|
@@ -3482,7 +3482,7 @@ describe("outbound Telegram verification", () => {
|
|
|
3482
3482
|
|
|
3483
3483
|
// Resend should be rejected due to max sends
|
|
3484
3484
|
const { ctx, lastResponse } = createMockCtx();
|
|
3485
|
-
handleGuardianVerification(
|
|
3485
|
+
await handleGuardianVerification(
|
|
3486
3486
|
{
|
|
3487
3487
|
type: "guardian_verification",
|
|
3488
3488
|
action: "resend_outbound",
|
|
@@ -3498,10 +3498,10 @@ describe("outbound Telegram verification", () => {
|
|
|
3498
3498
|
expect(resp!.error).toBe("max_sends_exceeded");
|
|
3499
3499
|
});
|
|
3500
3500
|
|
|
3501
|
-
test("rate limits apply to telegram outbound (cooldown)", () => {
|
|
3501
|
+
test("rate limits apply to telegram outbound (cooldown)", async () => {
|
|
3502
3502
|
// Start an outbound session with a known chat ID
|
|
3503
3503
|
const { ctx: startCtx } = createMockCtx();
|
|
3504
|
-
handleGuardianVerification(
|
|
3504
|
+
await handleGuardianVerification(
|
|
3505
3505
|
{
|
|
3506
3506
|
type: "guardian_verification",
|
|
3507
3507
|
action: "start_outbound",
|
|
@@ -3514,7 +3514,7 @@ describe("outbound Telegram verification", () => {
|
|
|
3514
3514
|
|
|
3515
3515
|
// Immediately try to resend (before cooldown)
|
|
3516
3516
|
const { ctx, lastResponse } = createMockCtx();
|
|
3517
|
-
handleGuardianVerification(
|
|
3517
|
+
await handleGuardianVerification(
|
|
3518
3518
|
{
|
|
3519
3519
|
type: "guardian_verification",
|
|
3520
3520
|
action: "resend_outbound",
|
|
@@ -3542,7 +3542,7 @@ describe("outbound voice verification", () => {
|
|
|
3542
3542
|
|
|
3543
3543
|
test("start_outbound for voice creates session with 6-digit code and initiates call", async () => {
|
|
3544
3544
|
const { ctx, lastResponse } = createMockCtx();
|
|
3545
|
-
handleGuardianVerification(
|
|
3545
|
+
await handleGuardianVerification(
|
|
3546
3546
|
{
|
|
3547
3547
|
type: "guardian_verification",
|
|
3548
3548
|
action: "start_outbound",
|
|
@@ -3584,9 +3584,9 @@ describe("outbound voice verification", () => {
|
|
|
3584
3584
|
);
|
|
3585
3585
|
});
|
|
3586
3586
|
|
|
3587
|
-
test("start_outbound for voice rejects unparseable phone number", () => {
|
|
3587
|
+
test("start_outbound for voice rejects unparseable phone number", async () => {
|
|
3588
3588
|
const { ctx, lastResponse } = createMockCtx();
|
|
3589
|
-
handleGuardianVerification(
|
|
3589
|
+
await handleGuardianVerification(
|
|
3590
3590
|
{
|
|
3591
3591
|
type: "guardian_verification",
|
|
3592
3592
|
action: "start_outbound",
|
|
@@ -3605,7 +3605,7 @@ describe("outbound voice verification", () => {
|
|
|
3605
3605
|
|
|
3606
3606
|
test("start_outbound for voice normalizes formatted phone number", async () => {
|
|
3607
3607
|
const { ctx, lastResponse } = createMockCtx();
|
|
3608
|
-
handleGuardianVerification(
|
|
3608
|
+
await handleGuardianVerification(
|
|
3609
3609
|
{
|
|
3610
3610
|
type: "guardian_verification",
|
|
3611
3611
|
action: "start_outbound",
|
|
@@ -3639,7 +3639,7 @@ describe("outbound voice verification", () => {
|
|
|
3639
3639
|
expect(lastCall.phoneNumber).toBe("+15551234567");
|
|
3640
3640
|
});
|
|
3641
3641
|
|
|
3642
|
-
test("start_outbound for voice rejects when binding exists (rebind=false)", () => {
|
|
3642
|
+
test("start_outbound for voice rejects when binding exists (rebind=false)", async () => {
|
|
3643
3643
|
createGuardianBinding({
|
|
3644
3644
|
channel: "voice",
|
|
3645
3645
|
guardianExternalUserId: "+15551234567",
|
|
@@ -3648,7 +3648,7 @@ describe("outbound voice verification", () => {
|
|
|
3648
3648
|
});
|
|
3649
3649
|
|
|
3650
3650
|
const { ctx, lastResponse } = createMockCtx();
|
|
3651
|
-
handleGuardianVerification(
|
|
3651
|
+
await handleGuardianVerification(
|
|
3652
3652
|
{
|
|
3653
3653
|
type: "guardian_verification",
|
|
3654
3654
|
action: "start_outbound",
|
|
@@ -3669,7 +3669,7 @@ describe("outbound voice verification", () => {
|
|
|
3669
3669
|
test("resend_outbound for voice initiates a new call with cooldown check", async () => {
|
|
3670
3670
|
// Start an outbound session first
|
|
3671
3671
|
const { ctx: startCtx } = createMockCtx();
|
|
3672
|
-
handleGuardianVerification(
|
|
3672
|
+
await handleGuardianVerification(
|
|
3673
3673
|
{
|
|
3674
3674
|
type: "guardian_verification",
|
|
3675
3675
|
action: "start_outbound",
|
|
@@ -3682,7 +3682,7 @@ describe("outbound voice verification", () => {
|
|
|
3682
3682
|
|
|
3683
3683
|
// Immediately try to resend (before cooldown)
|
|
3684
3684
|
const { ctx, lastResponse } = createMockCtx();
|
|
3685
|
-
handleGuardianVerification(
|
|
3685
|
+
await handleGuardianVerification(
|
|
3686
3686
|
{
|
|
3687
3687
|
type: "guardian_verification",
|
|
3688
3688
|
action: "resend_outbound",
|
|
@@ -3698,10 +3698,10 @@ describe("outbound voice verification", () => {
|
|
|
3698
3698
|
expect(resp!.error).toBe("rate_limited");
|
|
3699
3699
|
});
|
|
3700
3700
|
|
|
3701
|
-
test("cancel_outbound for voice cancels session", () => {
|
|
3701
|
+
test("cancel_outbound for voice cancels session", async () => {
|
|
3702
3702
|
// Start an outbound session first
|
|
3703
3703
|
const { ctx: startCtx } = createMockCtx();
|
|
3704
|
-
handleGuardianVerification(
|
|
3704
|
+
await handleGuardianVerification(
|
|
3705
3705
|
{
|
|
3706
3706
|
type: "guardian_verification",
|
|
3707
3707
|
action: "start_outbound",
|
|
@@ -3714,7 +3714,7 @@ describe("outbound voice verification", () => {
|
|
|
3714
3714
|
|
|
3715
3715
|
// Cancel the session
|
|
3716
3716
|
const { ctx, lastResponse } = createMockCtx();
|
|
3717
|
-
handleGuardianVerification(
|
|
3717
|
+
await handleGuardianVerification(
|
|
3718
3718
|
{
|
|
3719
3719
|
type: "guardian_verification",
|
|
3720
3720
|
action: "cancel_outbound",
|
|
@@ -3733,7 +3733,7 @@ describe("outbound voice verification", () => {
|
|
|
3733
3733
|
expect(session).toBeNull();
|
|
3734
3734
|
});
|
|
3735
3735
|
|
|
3736
|
-
test("rate limit enforcement: destination rate limit applies to voice", () => {
|
|
3736
|
+
test("rate limit enforcement: destination rate limit applies to voice", async () => {
|
|
3737
3737
|
// Exhaust the per-destination rate limit by creating many sessions
|
|
3738
3738
|
const db = getDb();
|
|
3739
3739
|
const now = Date.now();
|
|
@@ -3756,7 +3756,7 @@ describe("outbound voice verification", () => {
|
|
|
3756
3756
|
}
|
|
3757
3757
|
|
|
3758
3758
|
const { ctx, lastResponse } = createMockCtx();
|
|
3759
|
-
handleGuardianVerification(
|
|
3759
|
+
await handleGuardianVerification(
|
|
3760
3760
|
{
|
|
3761
3761
|
type: "guardian_verification",
|
|
3762
3762
|
action: "start_outbound",
|
|
@@ -3773,9 +3773,9 @@ describe("outbound voice verification", () => {
|
|
|
3773
3773
|
expect(resp!.error).toBe("rate_limited");
|
|
3774
3774
|
});
|
|
3775
3775
|
|
|
3776
|
-
test("start_outbound for voice requires destination", () => {
|
|
3776
|
+
test("start_outbound for voice requires destination", async () => {
|
|
3777
3777
|
const { ctx, lastResponse } = createMockCtx();
|
|
3778
|
-
handleGuardianVerification(
|
|
3778
|
+
await handleGuardianVerification(
|
|
3779
3779
|
{
|
|
3780
3780
|
type: "guardian_verification",
|
|
3781
3781
|
action: "start_outbound",
|
|
@@ -3809,9 +3809,9 @@ describe("M1–M4 hardening coverage", () => {
|
|
|
3809
3809
|
|
|
3810
3810
|
// ── M2: start_outbound for SMS returns secret in response ──
|
|
3811
3811
|
|
|
3812
|
-
test("start_outbound for SMS response includes secret", () => {
|
|
3812
|
+
test("start_outbound for SMS response includes secret", async () => {
|
|
3813
3813
|
const { ctx, lastResponse } = createMockCtx();
|
|
3814
|
-
handleGuardianVerification(
|
|
3814
|
+
await handleGuardianVerification(
|
|
3815
3815
|
{
|
|
3816
3816
|
type: "guardian_verification",
|
|
3817
3817
|
action: "start_outbound",
|
|
@@ -3832,10 +3832,10 @@ describe("M1–M4 hardening coverage", () => {
|
|
|
3832
3832
|
|
|
3833
3833
|
// ── M2: resend_outbound for SMS returns secret in response ──
|
|
3834
3834
|
|
|
3835
|
-
test("resend_outbound for SMS response includes secret", () => {
|
|
3835
|
+
test("resend_outbound for SMS response includes secret", async () => {
|
|
3836
3836
|
// Start a session first
|
|
3837
3837
|
const { ctx: startCtx } = createMockCtx();
|
|
3838
|
-
handleGuardianVerification(
|
|
3838
|
+
await handleGuardianVerification(
|
|
3839
3839
|
{
|
|
3840
3840
|
type: "guardian_verification",
|
|
3841
3841
|
action: "start_outbound",
|
|
@@ -3858,7 +3858,7 @@ describe("M1–M4 hardening coverage", () => {
|
|
|
3858
3858
|
|
|
3859
3859
|
// Resend
|
|
3860
3860
|
const { ctx, lastResponse } = createMockCtx();
|
|
3861
|
-
handleGuardianVerification(
|
|
3861
|
+
await handleGuardianVerification(
|
|
3862
3862
|
{
|
|
3863
3863
|
type: "guardian_verification",
|
|
3864
3864
|
action: "resend_outbound",
|
|
@@ -3878,9 +3878,9 @@ describe("M1–M4 hardening coverage", () => {
|
|
|
3878
3878
|
|
|
3879
3879
|
// ── M2: start_outbound for Telegram bootstrap does NOT return secret ──
|
|
3880
3880
|
|
|
3881
|
-
test("start_outbound for Telegram bootstrap (handle) does NOT return secret", () => {
|
|
3881
|
+
test("start_outbound for Telegram bootstrap (handle) does NOT return secret", async () => {
|
|
3882
3882
|
const { ctx, lastResponse } = createMockCtx();
|
|
3883
|
-
handleGuardianVerification(
|
|
3883
|
+
await handleGuardianVerification(
|
|
3884
3884
|
{
|
|
3885
3885
|
type: "guardian_verification",
|
|
3886
3886
|
action: "start_outbound",
|