@vellumai/assistant 0.4.32 → 0.4.34
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/docs/architecture/memory.md +1 -1
- package/package.json +1 -1
- package/src/__tests__/access-request-decision.test.ts +85 -4
- package/src/__tests__/actor-token-service.test.ts +4 -12
- package/src/__tests__/approval-primitive.test.ts +0 -45
- package/src/__tests__/approval-routes-http.test.ts +0 -1
- package/src/__tests__/assistant-id-boundary-guard.test.ts +150 -0
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/call-routes-http.test.ts +0 -1
- package/src/__tests__/callback-handoff-copy.test.ts +0 -1
- package/src/__tests__/channel-approval-routes.test.ts +5 -45
- package/src/__tests__/channel-guardian.test.ts +122 -346
- package/src/__tests__/channel-invite-transport.test.ts +52 -40
- package/src/__tests__/commit-message-enrichment-service.test.ts +4 -38
- package/src/__tests__/computer-use-session-working-dir.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +4 -3
- package/src/__tests__/contacts-tools.test.ts +4 -5
- package/src/__tests__/conversation-attention-store.test.ts +2 -65
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -2
- package/src/__tests__/conversation-pairing.test.ts +0 -1
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -3
- package/src/__tests__/guardian-action-conversation-turn.test.ts +1 -7
- package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -74
- package/src/__tests__/guardian-action-late-reply.test.ts +1 -8
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/guardian-grant-minting.test.ts +0 -1
- package/src/__tests__/guardian-outbound-http.test.ts +0 -1
- package/src/__tests__/guardian-routing-state.test.ts +0 -3
- package/src/__tests__/handlers-telegram-config.test.ts +0 -1
- package/src/__tests__/inbound-invite-redemption.test.ts +1 -7
- package/src/__tests__/ingress-reconcile.test.ts +3 -36
- package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1
- package/src/__tests__/migration-export-http.test.ts +0 -1
- package/src/__tests__/migration-import-commit-http.test.ts +0 -1
- package/src/__tests__/migration-import-preflight-http.test.ts +0 -1
- package/src/__tests__/migration-validate-http.test.ts +0 -1
- package/src/__tests__/non-member-access-request.test.ts +0 -8
- package/src/__tests__/notification-broadcaster.test.ts +1 -2
- package/src/__tests__/notification-decision-fallback.test.ts +0 -2
- package/src/__tests__/notification-decision-strategy.test.ts +0 -1
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/notification-telegram-adapter.test.ts +0 -4
- package/src/__tests__/relay-server.test.ts +151 -80
- package/src/__tests__/sandbox-host-parity.test.ts +5 -2
- package/src/__tests__/scoped-approval-grants.test.ts +9 -40
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -36
- package/src/__tests__/send-endpoint-busy.test.ts +0 -1
- package/src/__tests__/send-notification-tool.test.ts +0 -1
- package/src/__tests__/session-init.benchmark.test.ts +0 -2
- package/src/__tests__/slack-channel-config.test.ts +0 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -5
- package/src/__tests__/sms-messaging-provider.test.ts +0 -4
- package/src/__tests__/terminal-tools.test.ts +5 -2
- package/src/__tests__/thread-seed-composer.test.ts +0 -1
- package/src/__tests__/tool-approval-handler.test.ts +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +0 -4
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +65 -77
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +1 -18
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -14
- package/src/__tests__/trusted-contact-verification.test.ts +3 -16
- package/src/__tests__/twilio-routes.test.ts +2 -3
- package/src/__tests__/update-bulletin.test.ts +0 -2
- package/src/__tests__/user-reference.test.ts +47 -1
- package/src/__tests__/voice-invite-redemption.test.ts +0 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -38
- package/src/__tests__/workspace-git-service.test.ts +2 -2
- package/src/approvals/approval-primitive.ts +0 -15
- package/src/approvals/guardian-decision-primitive.ts +0 -3
- package/src/approvals/guardian-request-resolvers.ts +0 -5
- package/src/calls/call-domain.ts +0 -3
- package/src/calls/call-store.ts +0 -3
- package/src/calls/guardian-action-sweep.ts +2 -1
- package/src/calls/guardian-dispatch.ts +1 -2
- package/src/calls/relay-access-wait.ts +0 -4
- package/src/calls/relay-server.ts +8 -66
- package/src/calls/relay-setup-router.ts +1 -2
- package/src/calls/relay-verification.ts +0 -1
- package/src/calls/twilio-routes.ts +0 -3
- package/src/calls/types.ts +0 -1
- package/src/calls/voice-session-bridge.ts +0 -1
- package/src/channels/config.ts +41 -2
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +0 -1
- package/src/config/bundled-skills/slack/SKILL.md +2 -0
- package/src/config/bundled-skills/slack-digest-setup/SKILL.md +164 -0
- package/src/config/env.ts +0 -4
- package/src/config/feature-flag-registry.json +4 -4
- package/src/config/user-reference.ts +47 -9
- package/src/contacts/contact-store.ts +13 -88
- package/src/contacts/contacts-write.ts +3 -11
- package/src/contacts/types.ts +0 -1
- package/src/daemon/handlers/config-channels.ts +19 -44
- package/src/daemon/handlers/config-inbox.ts +6 -6
- package/src/daemon/handlers/contacts.ts +8 -12
- package/src/daemon/handlers/index.ts +0 -2
- package/src/daemon/lifecycle.ts +18 -26
- package/src/daemon/session-process.ts +0 -4
- package/src/memory/channel-delivery-store.ts +1 -0
- package/src/memory/conversation-attention-store.ts +4 -19
- package/src/memory/conversation-crud.ts +0 -2
- package/src/memory/db-init.ts +8 -0
- package/src/memory/delivery-crud.ts +13 -0
- package/src/memory/guardian-action-store.ts +0 -12
- package/src/memory/guardian-approvals.ts +35 -80
- package/src/memory/guardian-rate-limits.ts +1 -14
- package/src/memory/guardian-verification.ts +6 -34
- package/src/memory/invite-store.ts +76 -15
- package/src/memory/migrations/040-invite-code-hash-column.ts +16 -0
- package/src/memory/migrations/134-contacts-notes-column.ts +64 -45
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +263 -0
- package/src/memory/migrations/index.ts +2 -0
- package/src/memory/migrations/registry.ts +14 -1
- package/src/memory/schema/calls.ts +0 -7
- package/src/memory/schema/contacts.ts +2 -8
- package/src/memory/schema/guardian.ts +0 -5
- package/src/memory/schema/infrastructure.ts +0 -2
- package/src/memory/schema/notifications.ts +3 -17
- package/src/memory/scoped-approval-grants.ts +2 -24
- package/src/notifications/adapters/sms.ts +2 -1
- package/src/notifications/broadcaster.ts +1 -6
- package/src/notifications/decision-engine.ts +3 -4
- package/src/notifications/deliveries-store.ts +0 -4
- package/src/notifications/destination-resolver.ts +4 -6
- package/src/notifications/deterministic-checks.ts +1 -6
- package/src/notifications/emit-signal.ts +4 -11
- package/src/notifications/events-store.ts +7 -17
- package/src/notifications/preference-summary.ts +2 -2
- package/src/notifications/preferences-store.ts +2 -9
- package/src/notifications/signal.ts +0 -1
- package/src/notifications/thread-candidates.ts +1 -11
- package/src/notifications/types.ts +0 -3
- package/src/runtime/access-request-helper.ts +3 -10
- package/src/runtime/actor-refresh-token-store.ts +0 -6
- package/src/runtime/actor-token-store.ts +3 -16
- package/src/runtime/actor-trust-resolver.ts +1 -4
- package/src/runtime/auth/__tests__/credential-service.test.ts +0 -9
- package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -3
- package/src/runtime/auth/credential-service.ts +1 -15
- package/src/runtime/auth/require-bound-guardian.ts +1 -4
- package/src/runtime/auth/token-service.ts +50 -0
- package/src/runtime/channel-guardian-service.ts +16 -49
- package/src/runtime/channel-invite-transport.ts +129 -34
- package/src/runtime/channel-invite-transports/email.ts +54 -0
- package/src/runtime/channel-invite-transports/slack.ts +87 -0
- package/src/runtime/channel-invite-transports/sms.ts +74 -0
- package/src/runtime/channel-invite-transports/telegram.ts +35 -11
- package/src/runtime/channel-invite-transports/voice.ts +12 -12
- package/src/runtime/confirmation-request-guardian-bridge.ts +0 -1
- package/src/runtime/guardian-action-followup-executor.ts +3 -2
- package/src/runtime/guardian-action-grant-minter.ts +0 -1
- package/src/runtime/guardian-outbound-actions.ts +2 -12
- package/src/runtime/guardian-vellum-migration.ts +2 -3
- package/src/runtime/http-server.ts +0 -1
- package/src/runtime/invite-redemption-service.ts +191 -11
- package/src/runtime/invite-redemption-templates.ts +6 -6
- package/src/runtime/invite-service.ts +81 -11
- package/src/runtime/local-actor-identity.ts +2 -5
- package/src/runtime/routes/access-request-decision.ts +52 -7
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +6 -9
- package/src/runtime/routes/channel-readiness-routes.ts +29 -18
- package/src/runtime/routes/contact-routes.ts +48 -46
- package/src/runtime/routes/conversation-attention-routes.ts +0 -2
- package/src/runtime/routes/global-search-routes.ts +0 -2
- package/src/runtime/routes/guardian-bootstrap-routes.ts +6 -12
- package/src/runtime/routes/guardian-expiry-sweep.ts +3 -2
- package/src/runtime/routes/inbound-message-handler.ts +1 -6
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +296 -47
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +6 -42
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +1 -6
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +10 -0
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +0 -1
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +0 -1
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +3 -7
- package/src/runtime/routes/invite-routes.ts +1 -0
- package/src/runtime/routes/pairing-routes.ts +4 -4
- package/src/runtime/tool-grant-request-helper.ts +0 -1
- package/src/tools/browser/browser-manager.ts +22 -12
- package/src/tools/browser/runtime-check.ts +110 -3
- package/src/tools/calls/call-start.ts +1 -3
- package/src/tools/followups/followup_create.ts +1 -2
- package/src/tools/shared/shell-output.ts +7 -2
- package/src/tools/tool-approval-handler.ts +0 -2
- package/src/util/platform.ts +0 -4
- package/src/workspace/git-service.ts +10 -4
|
@@ -151,7 +151,6 @@ describe("guardian-action-late-reply", () => {
|
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
const deliveries = getExpiredDeliveriesByDestination(
|
|
154
|
-
"self",
|
|
155
154
|
"telegram",
|
|
156
155
|
"chat-abc",
|
|
157
156
|
);
|
|
@@ -163,11 +162,7 @@ describe("guardian-action-late-reply", () => {
|
|
|
163
162
|
test("getExpiredDeliveriesByDestination returns empty for non-matching channel", () => {
|
|
164
163
|
createExpiredRequest("conv-late-2", { chatId: "chat-abc" });
|
|
165
164
|
|
|
166
|
-
const deliveries = getExpiredDeliveriesByDestination(
|
|
167
|
-
"self",
|
|
168
|
-
"sms",
|
|
169
|
-
"chat-abc",
|
|
170
|
-
);
|
|
165
|
+
const deliveries = getExpiredDeliveriesByDestination("sms", "chat-abc");
|
|
171
166
|
expect(deliveries).toHaveLength(0);
|
|
172
167
|
});
|
|
173
168
|
|
|
@@ -180,7 +175,6 @@ describe("guardian-action-late-reply", () => {
|
|
|
180
175
|
startFollowupFromExpiredRequest(request.id, "late answer text");
|
|
181
176
|
|
|
182
177
|
const deliveries = getExpiredDeliveriesByDestination(
|
|
183
|
-
"self",
|
|
184
178
|
"telegram",
|
|
185
179
|
"chat-started",
|
|
186
180
|
);
|
|
@@ -311,7 +305,6 @@ describe("guardian-action-late-reply", () => {
|
|
|
311
305
|
|
|
312
306
|
// Should not appear in expired queries
|
|
313
307
|
const expiredByDest = getExpiredDeliveriesByDestination(
|
|
314
|
-
"self",
|
|
315
308
|
"telegram",
|
|
316
309
|
"chat-answered",
|
|
317
310
|
);
|
|
@@ -104,7 +104,6 @@ function createTestGuardianApproval(
|
|
|
104
104
|
runId: `run-${requestId}`,
|
|
105
105
|
requestId,
|
|
106
106
|
conversationId: CONVERSATION_ID,
|
|
107
|
-
assistantId: ASSISTANT_ID,
|
|
108
107
|
channel: "telegram",
|
|
109
108
|
requesterExternalUserId: REQUESTER_USER,
|
|
110
109
|
requesterChatId: REQUESTER_CHAT,
|
|
@@ -34,7 +34,6 @@ mock.module("../util/platform.js", () => ({
|
|
|
34
34
|
getDbPath: () => join(testDir, "test.db"),
|
|
35
35
|
getLogPath: () => join(testDir, "test.log"),
|
|
36
36
|
ensureDataDir: () => {},
|
|
37
|
-
readHttpToken: () => "test-bearer-token",
|
|
38
37
|
}));
|
|
39
38
|
|
|
40
39
|
mock.module("../util/logger.js", () => ({
|
|
@@ -185,7 +185,6 @@ describe("inbound-message-handler trusted-contact interactivity", () => {
|
|
|
185
185
|
// Insert a test contact so the contacts-based ACL lookup passes
|
|
186
186
|
upsertContact({
|
|
187
187
|
displayName: "Test User",
|
|
188
|
-
assistantId: "self",
|
|
189
188
|
channels: [
|
|
190
189
|
{
|
|
191
190
|
type: "telegram",
|
|
@@ -225,7 +224,6 @@ describe("inbound-message-handler trusted-contact interactivity", () => {
|
|
|
225
224
|
test("trusted contact with guardian binding gets interactive turn", async () => {
|
|
226
225
|
// Create guardian binding in contacts table so the trust resolver finds it
|
|
227
226
|
createGuardianBinding({
|
|
228
|
-
assistantId: "self",
|
|
229
227
|
channel: "telegram",
|
|
230
228
|
guardianExternalUserId: "guardian-user-for-tc",
|
|
231
229
|
guardianDeliveryChatId: "guardian-chat-for-tc",
|
|
@@ -326,7 +324,6 @@ describe("inbound-message-handler trusted-contact interactivity", () => {
|
|
|
326
324
|
test("guardian actors remain interactive regardless", async () => {
|
|
327
325
|
// Guardian binding matches the sender — use contacts-first so trust resolver finds it
|
|
328
326
|
createGuardianBinding({
|
|
329
|
-
assistantId: "self",
|
|
330
327
|
channel: "telegram",
|
|
331
328
|
guardianExternalUserId: "telegram-user-default",
|
|
332
329
|
guardianDeliveryChatId: "chat-123",
|
|
@@ -27,7 +27,6 @@ mock.module("../util/platform.js", () => ({
|
|
|
27
27
|
getDbPath: () => join(testDir, "test.db"),
|
|
28
28
|
getLogPath: () => join(testDir, "test.log"),
|
|
29
29
|
ensureDataDir: () => {},
|
|
30
|
-
readHttpToken: () => "test-bearer-token",
|
|
31
30
|
}));
|
|
32
31
|
|
|
33
32
|
mock.module("../util/logger.js", () => ({
|
|
@@ -204,9 +203,7 @@ describe("inbound invite redemption intercept", () => {
|
|
|
204
203
|
expect(deliverReplyCalls.length).toBe(1);
|
|
205
204
|
const replyText = (deliverReplyCalls[0].payload as Record<string, unknown>)
|
|
206
205
|
.text;
|
|
207
|
-
expect(replyText).toContain(
|
|
208
|
-
"Welcome! You've been granted access via invite link.",
|
|
209
|
-
);
|
|
206
|
+
expect(replyText).toContain("Welcome! You've been granted access.");
|
|
210
207
|
});
|
|
211
208
|
|
|
212
209
|
test("non-member with invalid token gets refusal text", async () => {
|
|
@@ -332,7 +329,6 @@ describe("inbound invite redemption intercept", () => {
|
|
|
332
329
|
test("existing active member sending normal message is unaffected", async () => {
|
|
333
330
|
// Pre-create an active member
|
|
334
331
|
upsertMember({
|
|
335
|
-
assistantId: "self",
|
|
336
332
|
sourceChannel: "telegram",
|
|
337
333
|
externalUserId: "user-active-member",
|
|
338
334
|
externalChatId: "chat-active",
|
|
@@ -382,7 +378,6 @@ describe("inbound invite redemption intercept", () => {
|
|
|
382
378
|
|
|
383
379
|
// Pre-create an active member that will click the invite link
|
|
384
380
|
upsertMember({
|
|
385
|
-
assistantId: "self",
|
|
386
381
|
sourceChannel: "telegram",
|
|
387
382
|
externalUserId: "user-already-active",
|
|
388
383
|
externalChatId: "chat-invite-test",
|
|
@@ -409,7 +404,6 @@ describe("inbound invite redemption intercept", () => {
|
|
|
409
404
|
});
|
|
410
405
|
|
|
411
406
|
upsertMember({
|
|
412
|
-
assistantId: "self",
|
|
413
407
|
sourceChannel: "telegram",
|
|
414
408
|
externalUserId: "user-invite-123",
|
|
415
409
|
externalChatId: "chat-invite-test",
|
|
@@ -24,9 +24,6 @@ mock.module("../config/loader.js", () => ({
|
|
|
24
24
|
invalidateConfigCache: () => {},
|
|
25
25
|
}));
|
|
26
26
|
|
|
27
|
-
// readHttpToken return value — controlled per test
|
|
28
|
-
let httpTokenValue: string | null = null;
|
|
29
|
-
|
|
30
27
|
mock.module("../util/platform.js", () => ({
|
|
31
28
|
getRootDir: () => testDir,
|
|
32
29
|
getDataDir: () => testDir,
|
|
@@ -39,7 +36,6 @@ mock.module("../util/platform.js", () => ({
|
|
|
39
36
|
getDbPath: () => join(testDir, "test.db"),
|
|
40
37
|
getLogPath: () => join(testDir, "test.log"),
|
|
41
38
|
ensureDataDir: () => {},
|
|
42
|
-
readHttpToken: () => httpTokenValue,
|
|
43
39
|
}));
|
|
44
40
|
|
|
45
41
|
mock.module("../util/logger.js", () => ({
|
|
@@ -66,8 +62,8 @@ mock.module("../providers/registry.js", () => ({
|
|
|
66
62
|
initializeProviders: () => {},
|
|
67
63
|
}));
|
|
68
64
|
|
|
69
|
-
// Mock token service — triggerGatewayReconcile
|
|
70
|
-
//
|
|
65
|
+
// Mock token service — triggerGatewayReconcile uses mintDaemonDeliveryToken
|
|
66
|
+
// for the Bearer token.
|
|
71
67
|
let mintedToken: string | null = null;
|
|
72
68
|
mock.module("../runtime/auth/token-service.js", () => ({
|
|
73
69
|
mintDaemonDeliveryToken: () => mintedToken ?? "test-delivery-token",
|
|
@@ -127,7 +123,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
127
123
|
|
|
128
124
|
beforeEach(() => {
|
|
129
125
|
rawConfigStore = {};
|
|
130
|
-
httpTokenValue = null;
|
|
131
126
|
mintedToken = null;
|
|
132
127
|
reconcileCalls = [];
|
|
133
128
|
fetchShouldFail = false;
|
|
@@ -194,9 +189,7 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
194
189
|
|
|
195
190
|
// ── Token present/missing behavior ──────────────────────────────────────
|
|
196
191
|
|
|
197
|
-
test("always triggers reconcile
|
|
198
|
-
httpTokenValue = null;
|
|
199
|
-
|
|
192
|
+
test("always triggers reconcile using mintDaemonDeliveryToken", async () => {
|
|
200
193
|
const msg: IngressConfigRequest = {
|
|
201
194
|
type: "ingress_config",
|
|
202
195
|
action: "set",
|
|
@@ -243,8 +236,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
243
236
|
// ── Request payload normalization ───────────────────────────────────────
|
|
244
237
|
|
|
245
238
|
test("sends ingressPublicBaseUrl in reconcile body when URL is set", async () => {
|
|
246
|
-
httpTokenValue = "test-token";
|
|
247
|
-
|
|
248
239
|
const msg: IngressConfigRequest = {
|
|
249
240
|
type: "ingress_config",
|
|
250
241
|
action: "set",
|
|
@@ -263,8 +254,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
263
254
|
});
|
|
264
255
|
|
|
265
256
|
test("sends POST to /internal/telegram/reconcile with correct content type", async () => {
|
|
266
|
-
httpTokenValue = "test-token";
|
|
267
|
-
|
|
268
257
|
const msg: IngressConfigRequest = {
|
|
269
258
|
type: "ingress_config",
|
|
270
259
|
action: "set",
|
|
@@ -283,8 +272,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
283
272
|
});
|
|
284
273
|
|
|
285
274
|
test("normalizes trailing slashes in publicBaseUrl before sending reconcile", async () => {
|
|
286
|
-
httpTokenValue = "test-token";
|
|
287
|
-
|
|
288
275
|
const msg: IngressConfigRequest = {
|
|
289
276
|
type: "ingress_config",
|
|
290
277
|
action: "set",
|
|
@@ -304,7 +291,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
304
291
|
});
|
|
305
292
|
|
|
306
293
|
test("uses GATEWAY_INTERNAL_BASE_URL when set", async () => {
|
|
307
|
-
httpTokenValue = "test-token";
|
|
308
294
|
process.env.GATEWAY_INTERNAL_BASE_URL = "http://custom-gateway:9999";
|
|
309
295
|
|
|
310
296
|
const msg: IngressConfigRequest = {
|
|
@@ -326,8 +312,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
326
312
|
});
|
|
327
313
|
|
|
328
314
|
test("defaults to localhost:7830 when no GATEWAY env vars set", async () => {
|
|
329
|
-
httpTokenValue = "test-token";
|
|
330
|
-
|
|
331
315
|
const msg: IngressConfigRequest = {
|
|
332
316
|
type: "ingress_config",
|
|
333
317
|
action: "set",
|
|
@@ -347,7 +331,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
347
331
|
});
|
|
348
332
|
|
|
349
333
|
test("uses GATEWAY_PORT when GATEWAY_INTERNAL_BASE_URL is not set", async () => {
|
|
350
|
-
httpTokenValue = "test-token";
|
|
351
334
|
process.env.GATEWAY_PORT = "8888";
|
|
352
335
|
|
|
353
336
|
const msg: IngressConfigRequest = {
|
|
@@ -371,7 +354,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
371
354
|
// ── Non-fatal failure behavior ──────────────────────────────────────────
|
|
372
355
|
|
|
373
356
|
test("reconcile failure does not cause handleIngressConfig to fail", async () => {
|
|
374
|
-
httpTokenValue = "test-token";
|
|
375
357
|
fetchShouldFail = true;
|
|
376
358
|
|
|
377
359
|
const msg: IngressConfigRequest = {
|
|
@@ -404,8 +386,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
404
386
|
});
|
|
405
387
|
|
|
406
388
|
test("response is sent before reconcile fetch completes", async () => {
|
|
407
|
-
httpTokenValue = "test-token";
|
|
408
|
-
|
|
409
389
|
// Track timing: response should be sent before fetch resolves
|
|
410
390
|
let fetchResolved = false;
|
|
411
391
|
const originalMockFetch = globalThis.fetch;
|
|
@@ -456,8 +436,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
456
436
|
// ── Set flow ────────────────────────────────────────────────────────────
|
|
457
437
|
|
|
458
438
|
test("set action with enabled=true and URL triggers reconcile with the URL", async () => {
|
|
459
|
-
httpTokenValue = "test-token";
|
|
460
|
-
|
|
461
439
|
const msg: IngressConfigRequest = {
|
|
462
440
|
type: "ingress_config",
|
|
463
441
|
action: "set",
|
|
@@ -483,8 +461,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
483
461
|
// ── Clear flow ──────────────────────────────────────────────────────────
|
|
484
462
|
|
|
485
463
|
test("set action with empty URL and enabled=true (clear URL) still triggers reconcile", async () => {
|
|
486
|
-
httpTokenValue = "test-token";
|
|
487
|
-
|
|
488
464
|
const msg: IngressConfigRequest = {
|
|
489
465
|
type: "ingress_config",
|
|
490
466
|
action: "set",
|
|
@@ -512,8 +488,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
512
488
|
// ── Disable flow ────────────────────────────────────────────────────────
|
|
513
489
|
|
|
514
490
|
test("set action with enabled=false triggers reconcile with empty URL", async () => {
|
|
515
|
-
httpTokenValue = "test-token";
|
|
516
|
-
|
|
517
491
|
const msg: IngressConfigRequest = {
|
|
518
492
|
type: "ingress_config",
|
|
519
493
|
action: "set",
|
|
@@ -539,8 +513,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
539
513
|
});
|
|
540
514
|
|
|
541
515
|
test("disabling ingress removes INGRESS_PUBLIC_BASE_URL env var", () => {
|
|
542
|
-
httpTokenValue = "test-token";
|
|
543
|
-
|
|
544
516
|
// First set ingress to populate env var
|
|
545
517
|
process.env.INGRESS_PUBLIC_BASE_URL =
|
|
546
518
|
"https://should-be-removed.example.com";
|
|
@@ -562,7 +534,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
562
534
|
// ── Get action does not trigger reconcile ───────────────────────────────
|
|
563
535
|
|
|
564
536
|
test("get action does not trigger reconcile", async () => {
|
|
565
|
-
httpTokenValue = "test-token";
|
|
566
537
|
rawConfigStore = {
|
|
567
538
|
ingress: { publicBaseUrl: "https://existing.example.com", enabled: true },
|
|
568
539
|
};
|
|
@@ -593,8 +564,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
593
564
|
// ── Env var propagation ─────────────────────────────────────────────────
|
|
594
565
|
|
|
595
566
|
test("set action propagates URL to process.env when enabled", () => {
|
|
596
|
-
httpTokenValue = "test-token";
|
|
597
|
-
|
|
598
567
|
const msg: IngressConfigRequest = {
|
|
599
568
|
type: "ingress_config",
|
|
600
569
|
action: "set",
|
|
@@ -611,8 +580,6 @@ describe("Ingress reconcile trigger in handleIngressConfig", () => {
|
|
|
611
580
|
});
|
|
612
581
|
|
|
613
582
|
test("reconcile uses effective URL from process.env (not raw value)", async () => {
|
|
614
|
-
httpTokenValue = "test-token";
|
|
615
|
-
|
|
616
583
|
const msg: IngressConfigRequest = {
|
|
617
584
|
type: "ingress_config",
|
|
618
585
|
action: "set",
|
|
@@ -98,7 +98,6 @@ mock.module("../config/env.js", () => ({
|
|
|
98
98
|
getGatewayPort: () => 7830,
|
|
99
99
|
getRuntimeHttpPort: () => 7821,
|
|
100
100
|
getRuntimeHttpHost: () => "127.0.0.1",
|
|
101
|
-
getRuntimeProxyBearerToken: () => undefined,
|
|
102
101
|
getRuntimeGatewayOriginSecret: () => undefined,
|
|
103
102
|
getIngressPublicBaseUrl: () => undefined,
|
|
104
103
|
setIngressPublicBaseUrl: () => {},
|
|
@@ -72,7 +72,6 @@ mock.module("../config/env.js", () => ({
|
|
|
72
72
|
getGatewayPort: () => 7830,
|
|
73
73
|
getRuntimeHttpPort: () => 7821,
|
|
74
74
|
getRuntimeHttpHost: () => "127.0.0.1",
|
|
75
|
-
getRuntimeProxyBearerToken: () => undefined,
|
|
76
75
|
getRuntimeGatewayOriginSecret: () => undefined,
|
|
77
76
|
getIngressPublicBaseUrl: () => undefined,
|
|
78
77
|
setIngressPublicBaseUrl: () => {},
|
|
@@ -93,7 +93,6 @@ mock.module("../config/env.js", () => ({
|
|
|
93
93
|
getGatewayPort: () => 7830,
|
|
94
94
|
getRuntimeHttpPort: () => 7821,
|
|
95
95
|
getRuntimeHttpHost: () => "127.0.0.1",
|
|
96
|
-
getRuntimeProxyBearerToken: () => undefined,
|
|
97
96
|
getRuntimeGatewayOriginSecret: () => undefined,
|
|
98
97
|
getIngressPublicBaseUrl: () => undefined,
|
|
99
98
|
setIngressPublicBaseUrl: () => {},
|
|
@@ -79,7 +79,6 @@ mock.module("../config/env.js", () => ({
|
|
|
79
79
|
getGatewayPort: () => 7830,
|
|
80
80
|
getRuntimeHttpPort: () => 7821,
|
|
81
81
|
getRuntimeHttpHost: () => "127.0.0.1",
|
|
82
|
-
getRuntimeProxyBearerToken: () => undefined,
|
|
83
82
|
getRuntimeGatewayOriginSecret: () => undefined,
|
|
84
83
|
getIngressPublicBaseUrl: () => undefined,
|
|
85
84
|
setIngressPublicBaseUrl: () => {},
|
|
@@ -68,7 +68,6 @@ mock.module("../config/env.js", () => ({
|
|
|
68
68
|
getGatewayPort: () => 7830,
|
|
69
69
|
getRuntimeHttpPort: () => 7821,
|
|
70
70
|
getRuntimeHttpHost: () => "127.0.0.1",
|
|
71
|
-
getRuntimeProxyBearerToken: () => undefined,
|
|
72
71
|
getRuntimeGatewayOriginSecret: () => undefined,
|
|
73
72
|
getIngressPublicBaseUrl: () => undefined,
|
|
74
73
|
setIngressPublicBaseUrl: () => {},
|
|
@@ -29,7 +29,6 @@ mock.module("../util/platform.js", () => ({
|
|
|
29
29
|
getDbPath: () => join(testDir, "test.db"),
|
|
30
30
|
getLogPath: () => join(testDir, "test.log"),
|
|
31
31
|
ensureDataDir: () => {},
|
|
32
|
-
readHttpToken: () => "test-bearer-token",
|
|
33
32
|
}));
|
|
34
33
|
|
|
35
34
|
mock.module("../util/logger.js", () => ({
|
|
@@ -190,7 +189,6 @@ describe("non-member access request notification", () => {
|
|
|
190
189
|
test("guardian is notified when a non-member messages and a guardian binding exists", async () => {
|
|
191
190
|
// Set up a guardian binding for this channel
|
|
192
191
|
createGuardianBinding({
|
|
193
|
-
assistantId: "self",
|
|
194
192
|
channel: "telegram",
|
|
195
193
|
guardianExternalUserId: "guardian-user-789",
|
|
196
194
|
guardianDeliveryChatId: "guardian-chat-789",
|
|
@@ -236,7 +234,6 @@ describe("non-member access request notification", () => {
|
|
|
236
234
|
|
|
237
235
|
test("no duplicate approval requests for repeated messages from same non-member", async () => {
|
|
238
236
|
createGuardianBinding({
|
|
239
|
-
assistantId: "self",
|
|
240
237
|
channel: "telegram",
|
|
241
238
|
guardianExternalUserId: "guardian-user-789",
|
|
242
239
|
guardianDeliveryChatId: "guardian-chat-789",
|
|
@@ -307,7 +304,6 @@ describe("non-member access request notification", () => {
|
|
|
307
304
|
test("cross-channel fallback: SMS guardian binding resolves for Telegram access request", async () => {
|
|
308
305
|
// Only an SMS guardian binding exists — no Telegram binding
|
|
309
306
|
createGuardianBinding({
|
|
310
|
-
assistantId: "self",
|
|
311
307
|
channel: "sms",
|
|
312
308
|
guardianExternalUserId: "guardian-sms-user",
|
|
313
309
|
guardianDeliveryChatId: "guardian-sms-chat",
|
|
@@ -343,7 +339,6 @@ describe("non-member access request notification", () => {
|
|
|
343
339
|
|
|
344
340
|
test("no notification when actorExternalId is absent", async () => {
|
|
345
341
|
createGuardianBinding({
|
|
346
|
-
assistantId: "self",
|
|
347
342
|
channel: "telegram",
|
|
348
343
|
guardianExternalUserId: "guardian-user-789",
|
|
349
344
|
guardianDeliveryChatId: "guardian-chat-789",
|
|
@@ -420,7 +415,6 @@ describe("access-request-helper unit tests", () => {
|
|
|
420
415
|
test("notifyGuardianOfAccessRequest uses cross-channel binding when source-channel binding is missing", () => {
|
|
421
416
|
// Only SMS binding exists
|
|
422
417
|
createGuardianBinding({
|
|
423
|
-
assistantId: "self",
|
|
424
418
|
channel: "sms",
|
|
425
419
|
guardianExternalUserId: "guardian-sms",
|
|
426
420
|
guardianDeliveryChatId: "sms-chat",
|
|
@@ -456,7 +450,6 @@ describe("access-request-helper unit tests", () => {
|
|
|
456
450
|
test("notifyGuardianOfAccessRequest prefers source-channel binding over cross-channel fallback", () => {
|
|
457
451
|
// Both Telegram and SMS bindings exist
|
|
458
452
|
createGuardianBinding({
|
|
459
|
-
assistantId: "self",
|
|
460
453
|
channel: "telegram",
|
|
461
454
|
guardianExternalUserId: "guardian-tg",
|
|
462
455
|
guardianDeliveryChatId: "tg-chat",
|
|
@@ -464,7 +457,6 @@ describe("access-request-helper unit tests", () => {
|
|
|
464
457
|
verifiedVia: "test",
|
|
465
458
|
});
|
|
466
459
|
createGuardianBinding({
|
|
467
|
-
assistantId: "self",
|
|
468
460
|
channel: "sms",
|
|
469
461
|
guardianExternalUserId: "guardian-sms",
|
|
470
462
|
guardianDeliveryChatId: "sms-chat",
|
|
@@ -23,7 +23,7 @@ mock.module("../util/logger.js", () => ({
|
|
|
23
23
|
|
|
24
24
|
// Mock destination-resolver to return a destination for every requested channel
|
|
25
25
|
mock.module("../notifications/destination-resolver.js", () => ({
|
|
26
|
-
resolveDestinations: (
|
|
26
|
+
resolveDestinations: (channels: string[]) => {
|
|
27
27
|
const m = new Map();
|
|
28
28
|
for (const ch of channels) {
|
|
29
29
|
m.set(ch, { channel: ch, endpoint: `mock-${ch}` });
|
|
@@ -84,7 +84,6 @@ function makeSignal(
|
|
|
84
84
|
): NotificationSignal {
|
|
85
85
|
return {
|
|
86
86
|
signalId: "sig-broadcast-001",
|
|
87
|
-
assistantId: "self",
|
|
88
87
|
createdAt: Date.now(),
|
|
89
88
|
sourceChannel: "scheduler",
|
|
90
89
|
sourceSessionId: "sess-001",
|
|
@@ -63,7 +63,6 @@ function makeSignal(
|
|
|
63
63
|
): NotificationSignal {
|
|
64
64
|
return {
|
|
65
65
|
signalId: "sig-fallback-guardian-1",
|
|
66
|
-
assistantId: "self",
|
|
67
66
|
createdAt: Date.now(),
|
|
68
67
|
sourceChannel: "voice",
|
|
69
68
|
sourceSessionId: "call-session-1",
|
|
@@ -307,7 +306,6 @@ describe("access-request instruction enforcement", () => {
|
|
|
307
306
|
): NotificationSignal {
|
|
308
307
|
return {
|
|
309
308
|
signalId: "sig-access-req-1",
|
|
310
|
-
assistantId: "self",
|
|
311
309
|
createdAt: Date.now(),
|
|
312
310
|
sourceChannel: "telegram",
|
|
313
311
|
sourceSessionId: "tg-session-1",
|
|
@@ -21,10 +21,6 @@ mock.module("../runtime/gateway-client.js", () => ({
|
|
|
21
21
|
},
|
|
22
22
|
}));
|
|
23
23
|
|
|
24
|
-
mock.module("../util/platform.js", () => ({
|
|
25
|
-
readHttpToken: () => "test-http-token",
|
|
26
|
-
}));
|
|
27
|
-
|
|
28
24
|
mock.module("../util/logger.js", () => ({
|
|
29
25
|
getLogger: () =>
|
|
30
26
|
new Proxy({} as Record<string, unknown>, {
|