@rubytech/create-maxy-code 0.1.409 → 0.1.411

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.
Files changed (54) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/scheduling/PLUGIN.md +2 -2
  3. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/agent-dispatch-manager-grounding.test.js +5 -5
  4. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/agent-dispatch-manager-grounding.test.js.map +1 -1
  5. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/agent-dispatch.test.js +103 -34
  6. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/agent-dispatch.test.js.map +1 -1
  7. package/payload/platform/plugins/scheduling/mcp/dist/lib/agent-dispatch.d.ts +45 -11
  8. package/payload/platform/plugins/scheduling/mcp/dist/lib/agent-dispatch.d.ts.map +1 -1
  9. package/payload/platform/plugins/scheduling/mcp/dist/lib/agent-dispatch.js +74 -23
  10. package/payload/platform/plugins/scheduling/mcp/dist/lib/agent-dispatch.js.map +1 -1
  11. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/standing-audit.test.js +48 -9
  12. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/standing-audit.test.js.map +1 -1
  13. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +9 -5
  14. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
  15. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +53 -18
  16. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
  17. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-agent.test.js +24 -4
  18. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-agent.test.js.map +1 -1
  19. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-agent.test.js +6 -4
  20. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-agent.test.js.map +1 -1
  21. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +2 -0
  22. package/payload/server/public/assets/{AdminLoginScreens-D36zz_SY.js → AdminLoginScreens-BRQgI2lW.js} +1 -1
  23. package/payload/server/public/assets/AdminShell-By9n5icG.js +2 -0
  24. package/payload/server/public/assets/{Checkbox-54KtArF3.js → Checkbox-DjEWgYu1.js} +1 -1
  25. package/payload/server/public/assets/{Transcript-BCpiXt4J.js → Transcript-BejWvOaO.js} +1 -1
  26. package/payload/server/public/assets/{admin-C0FCHcJj.js → admin-BFEMryQm.js} +1 -1
  27. package/payload/server/public/assets/{browser-bKeZ5iLx.js → browser-CMJMEUz6.js} +1 -1
  28. package/payload/server/public/assets/{calendar-BDPBArFA.js → calendar-C6ZGlHEP.js} +1 -1
  29. package/payload/server/public/assets/chat-B7s62Nnp.js +1 -0
  30. package/payload/server/public/assets/chevron-left-Dfjcaiyr.js +1 -0
  31. package/payload/server/public/assets/data-741ZbBwR.js +1 -0
  32. package/payload/server/public/assets/{graph-Dvru9CW9.js → graph-DIrXtPLv.js} +1 -1
  33. package/payload/server/public/assets/{graph-labels-DLhR6Rit.js → graph-labels-BtPf1Jom.js} +1 -1
  34. package/payload/server/public/assets/{maximize-2-CyPKq7HZ.js → maximize-2-DeJ4K8kL.js} +1 -1
  35. package/payload/server/public/assets/{operator-Ql5iQXB-.js → operator-B8QhqzLI.js} +1 -1
  36. package/payload/server/public/assets/{page-YsTtZsn6.js → page-Df6KYkf4.js} +1 -1
  37. package/payload/server/public/assets/{page-ClJOW2fk.js → page-iFOy0dFx.js} +1 -1
  38. package/payload/server/public/assets/{public-BlDxwcmS.js → public-BrUIRQZd.js} +1 -1
  39. package/payload/server/public/assets/{rotate-ccw-DSynJPZX.js → rotate-ccw-CYfntpwu.js} +1 -1
  40. package/payload/server/public/assets/useSubAccountSwitcher-Cvnc_fwQ.css +1 -0
  41. package/payload/server/public/browser.html +4 -4
  42. package/payload/server/public/calendar.html +5 -5
  43. package/payload/server/public/chat.html +9 -9
  44. package/payload/server/public/data.html +8 -8
  45. package/payload/server/public/graph.html +9 -9
  46. package/payload/server/public/index.html +11 -11
  47. package/payload/server/public/operator.html +11 -11
  48. package/payload/server/public/public.html +9 -9
  49. package/payload/server/public/assets/AdminShell-DH6Lcj-d.js +0 -1
  50. package/payload/server/public/assets/chat-Cp_1ebzU.js +0 -1
  51. package/payload/server/public/assets/chevron-left-S7Nk-se6.js +0 -1
  52. package/payload/server/public/assets/data-BshlTgIW.js +0 -1
  53. package/payload/server/public/assets/useSubAccountSwitcher-CJelLQK-.css +0 -1
  54. /package/payload/server/public/assets/{useSubAccountSwitcher-DGKQxXDD.js → useSubAccountSwitcher-BK_KfOLC.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.409",
3
+ "version": "0.1.411",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -124,14 +124,14 @@ An `action` invokes one pre-encoded MCP tool with no reasoning. When a due event
124
124
  ```
125
125
 
126
126
  - `channel` — `whatsapp` or `telegram`.
127
- - `destination` — the E.164 phone (WhatsApp) or chat id (Telegram) to run the turn for and reply to. It **must already be a registered admin or account-manager** on that channel; a destination that is not is rejected when the event is created.
127
+ - `destination` — the E.164 phone (WhatsApp) or chat id (Telegram) to run the turn for and reply to. It **must already be a registered admin or account-manager** on that channel; a destination that is not is rejected when the event is created. For WhatsApp the authoritative admin/manager lists are read from the socket-owning **house** account (never the event's own account), and the destination's registered account must match the account that created the schedule: an admin belongs to the house, a manager to its bound sub-account. The house/owner account may target any registered admin or manager; a sub-account is locked to its own manager(s). A refusal names the true reason — `not-registered` (in no house list) or `cross-account` (registered to a different account, naming both accounts).
128
128
  - `prompt` — the instruction the agent runs.
129
129
 
130
130
  An event carries **either** an `action` **or** an `agentDispatch`, never both — setting one clears the other. Agent dispatch is stored as `agentChannel`, `agentDestination`, `agentPrompt`. Use `schedule-update` with `agentDispatch` to modify or `agentDispatch: null` to clear. On WhatsApp, a destination bound as an account-manager scopes the spawned session to its sub-account; on Telegram the session runs on the house account.
131
131
 
132
132
  A WhatsApp `agentDispatch` destination may therefore be an account manager, not only an admin phone — this is the supported way to send a manager a proactive or scheduled WhatsApp message. The reply is delivered over the house's paired line regardless of which sub-account the session is scoped to; socket ownership never restricts which number the dispatch can reach.
133
133
 
134
- Dispatch results are recorded on the Event node (`lastDispatchResult`, `lastDispatchAt`) exactly as for tool actions. Every heartbeat tick also audits stored agent dispatches and logs `[schedule-audit] op=stale-dispatch` for any whose destination has stopped being an admin or whose bound sub-account is gone, so a binding that rots between scheduling and firing is surfaced before it mis-dispatches.
134
+ Dispatch results are recorded on the Event node (`lastDispatchResult`, `lastDispatchAt`) exactly as for tool actions. Every heartbeat tick also audits stored agent dispatches against the same house-authority rule used at creation, and logs `[schedule-audit] op=stale-dispatch` with the identical reason codes — `not-registered` (destination left the house lists), `cross-account` (rebound to a different account than the one that created the schedule), or `sub-account-missing` (bound sub-account deleted) so a binding that rots between scheduling and firing is surfaced with its true cause before it mis-dispatches.
135
135
 
136
136
  ## Reconciling public bookings (D1 → graph)
137
137
 
@@ -1,9 +1,9 @@
1
1
  // Task 1435 — content-presence gate for the scheduling side of the WhatsApp
2
- // deliverability grounding. `isValidAgentDestination` accepts an account
3
- // manager (adminPhones OR accountManagers), so scheduled dispatch is the
4
- // supported way to reach a manager. PLUGIN.md must say so plainly, and deliver-
5
- // over-the-house-line must be stated, so the agent cites it instead of inventing
6
- // a line-ownership restriction. Mirrors time-resolve-description.test.ts.
2
+ // deliverability grounding. `validateAgentDestination` accepts an account
3
+ // manager (the house's adminPhones OR accountManagers), so scheduled dispatch is
4
+ // the supported way to reach a manager. PLUGIN.md must say so plainly, and
5
+ // deliver-over-the-house-line must be stated, so the agent cites it instead of
6
+ // inventing a line-ownership restriction. Mirrors time-resolve-description.test.ts.
7
7
  import { describe, it, expect } from "vitest";
8
8
  import { readFileSync } from "fs";
9
9
  import { resolve } from "path";
@@ -1 +1 @@
1
- {"version":3,"file":"agent-dispatch-manager-grounding.test.js","sourceRoot":"","sources":["../../src/__tests__/agent-dispatch-manager-grounding.test.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,yEAAyE;AACzE,yEAAyE;AACzE,gFAAgF;AAChF,iFAAiF;AACjF,0EAA0E;AAC1E,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC;AAE9E,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACxD,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACpF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CACtB,4EAA4E,CAC7E,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CACtB,sEAAsE,CACvE,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"agent-dispatch-manager-grounding.test.js","sourceRoot":"","sources":["../../src/__tests__/agent-dispatch-manager-grounding.test.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,0EAA0E;AAC1E,iFAAiF;AACjF,2EAA2E;AAC3E,+EAA+E;AAC/E,oFAAoF;AACpF,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC;AAE9E,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACxD,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACpF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CACtB,4EAA4E,CAC7E,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CACtB,sEAAsE,CACvE,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,10 +1,27 @@
1
1
  import { describe, it, expect, afterEach } from "vitest";
2
- import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
2
+ import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
- import { normalizeE164, phonesMatch, isValidAgentDestination, boundSubAccountFor, } from "../agent-dispatch.js";
6
- function makeAccountDir(config) {
5
+ import { normalizeE164, phonesMatch, validateAgentDestination, boundSubAccountFor, } from "../agent-dispatch.js";
6
+ // The house-authority validator resolves the socket-owning house from the
7
+ // PARENT accounts dir (via account-enumeration), so fixtures must use
8
+ // UUID-named account dirs carrying role:"house" (the resolver's contract).
9
+ const HOUSE = "11111111-1111-4111-8111-111111111111";
10
+ const SUB_A = "22222222-2222-4222-8222-222222222222";
11
+ const SUB_B = "33333333-3333-4333-8333-333333333333";
12
+ function makeAccountsDir(seed) {
7
13
  const dir = mkdtempSync(join(tmpdir(), "agent-dispatch-"));
14
+ seed(dir);
15
+ return dir;
16
+ }
17
+ function seedAccount(accountsDir, id, cfg) {
18
+ const d = join(accountsDir, id);
19
+ mkdirSync(d, { recursive: true });
20
+ writeFileSync(join(d, "account.json"), JSON.stringify(cfg), "utf-8");
21
+ }
22
+ // A single account dir (for the direct-read helpers boundSubAccountFor tests).
23
+ function makeAccountDir(config) {
24
+ const dir = mkdtempSync(join(tmpdir(), "agent-dispatch-one-"));
8
25
  writeFileSync(join(dir, "account.json"), JSON.stringify(config), "utf-8");
9
26
  return dir;
10
27
  }
@@ -23,62 +40,114 @@ describe("normalizeE164 / phonesMatch (replica of platform normalize.ts)", () =>
23
40
  expect(phonesMatch("", "")).toBe(false);
24
41
  });
25
42
  });
26
- describe("isValidAgentDestination — whatsapp", () => {
43
+ describe("validateAgentDestination — whatsapp house-authority + creating-account match", () => {
27
44
  let dirs = [];
28
45
  afterEach(() => {
29
46
  for (const d of dirs)
30
47
  rmSync(d, { recursive: true, force: true });
31
48
  dirs = [];
32
49
  });
33
- it("accepts a destination present in adminPhones (phonesMatch)", () => {
34
- const dir = makeAccountDir({ whatsapp: { adminPhones: ["+447504472444"] } });
35
- dirs.push(dir);
36
- // spaced form must still match the stored bare form
37
- expect(isValidAgentDestination(dir, "whatsapp", "+44 7504 472444")).toEqual({ valid: true });
50
+ it("house-created dispatch to a house admin is valid (spaced form matches stored bare form)", () => {
51
+ const acc = makeAccountsDir((a) => seedAccount(a, HOUSE, { role: "house", whatsapp: { adminPhones: ["+447504472444"] } }));
52
+ dirs.push(acc);
53
+ expect(validateAgentDestination(acc, HOUSE, "whatsapp", "+44 7504 472444")).toEqual({ valid: true });
38
54
  });
39
- it("accepts a destination that is an accountManagers key", () => {
40
- const dir = makeAccountDir({
41
- whatsapp: { adminPhones: [], accountManagers: { "447504472444": "sub-abc" } },
55
+ it("sub-account-created dispatch to its own manager is valid", () => {
56
+ const acc = makeAccountsDir((a) => {
57
+ seedAccount(a, HOUSE, { role: "house", whatsapp: { accountManagers: { "447958391734": SUB_A } } });
58
+ seedAccount(a, SUB_A, {});
42
59
  });
43
- dirs.push(dir);
44
- expect(isValidAgentDestination(dir, "whatsapp", "+447504472444")).toEqual({ valid: true });
60
+ dirs.push(acc);
61
+ expect(validateAgentDestination(acc, SUB_A, "whatsapp", "+44 7958 391734")).toEqual({ valid: true });
45
62
  });
46
- it("rejects a destination absent from both lists", () => {
47
- const dir = makeAccountDir({ whatsapp: { adminPhones: ["+447504472444"] } });
48
- dirs.push(dir);
49
- expect(isValidAgentDestination(dir, "whatsapp", "+447999999999")).toEqual({
63
+ it("sub-account-created dispatch to ANOTHER sub-account's manager is cross-account", () => {
64
+ const acc = makeAccountsDir((a) => {
65
+ seedAccount(a, HOUSE, { role: "house", whatsapp: { accountManagers: { "447958391734": SUB_A } } });
66
+ seedAccount(a, SUB_A, {});
67
+ seedAccount(a, SUB_B, {});
68
+ });
69
+ dirs.push(acc);
70
+ expect(validateAgentDestination(acc, SUB_B, "whatsapp", "+447958391734")).toEqual({
50
71
  valid: false,
51
- reason: "destination-not-admin",
72
+ reason: "cross-account",
73
+ destinationAccount: SUB_A,
74
+ scheduleAccount: SUB_B,
52
75
  });
53
76
  });
54
- it("rejects when there is no whatsapp config at all", () => {
55
- const dir = makeAccountDir({});
56
- dirs.push(dir);
57
- expect(isValidAgentDestination(dir, "whatsapp", "+447504472444").valid).toBe(false);
77
+ it("sub-account-created dispatch to a house admin is cross-account (sub locked to own managers)", () => {
78
+ const acc = makeAccountsDir((a) => {
79
+ seedAccount(a, HOUSE, { role: "house", whatsapp: { adminPhones: ["+447504472444"] } });
80
+ seedAccount(a, SUB_A, {});
81
+ });
82
+ dirs.push(acc);
83
+ expect(validateAgentDestination(acc, SUB_A, "whatsapp", "+447504472444")).toEqual({
84
+ valid: false,
85
+ reason: "cross-account",
86
+ destinationAccount: HOUSE,
87
+ scheduleAccount: SUB_A,
88
+ });
89
+ });
90
+ it("house-created dispatch to any sub-account manager is valid (owner exception)", () => {
91
+ const acc = makeAccountsDir((a) => {
92
+ seedAccount(a, HOUSE, { role: "house", whatsapp: { accountManagers: { "447958391734": SUB_A } } });
93
+ seedAccount(a, SUB_A, {});
94
+ });
95
+ dirs.push(acc);
96
+ expect(validateAgentDestination(acc, HOUSE, "whatsapp", "+447958391734")).toEqual({ valid: true });
97
+ });
98
+ it("unregistered number is not-registered", () => {
99
+ const acc = makeAccountsDir((a) => seedAccount(a, HOUSE, { role: "house", whatsapp: { adminPhones: ["+447504472444"] } }));
100
+ dirs.push(acc);
101
+ expect(validateAgentDestination(acc, HOUSE, "whatsapp", "+447999999999")).toEqual({
102
+ valid: false,
103
+ reason: "not-registered",
104
+ });
105
+ });
106
+ it("reads the HOUSE list, not the creating sub-account's own account.json (the 1439 bug)", () => {
107
+ // The manager map lives ONLY on the house; the sub-account carries none.
108
+ // Pre-fix this read the sub-account and returned not-registered.
109
+ const acc = makeAccountsDir((a) => {
110
+ seedAccount(a, HOUSE, { role: "house", whatsapp: { accountManagers: { "447958391734": SUB_A } } });
111
+ seedAccount(a, SUB_A, { whatsapp: {} });
112
+ });
113
+ dirs.push(acc);
114
+ expect(validateAgentDestination(acc, SUB_A, "whatsapp", "+447958391734")).toEqual({ valid: true });
115
+ });
116
+ it("a number that is both a house admin and a sub-account's manager binds to the sub-account (manager wins)", () => {
117
+ const acc = makeAccountsDir((a) => {
118
+ seedAccount(a, HOUSE, {
119
+ role: "house",
120
+ whatsapp: { adminPhones: ["+447958391734"], accountManagers: { "447958391734": SUB_A } },
121
+ });
122
+ seedAccount(a, SUB_A, {});
123
+ });
124
+ dirs.push(acc);
125
+ // created in SUB_A → its own manager → valid
126
+ expect(validateAgentDestination(acc, SUB_A, "whatsapp", "+447958391734")).toEqual({ valid: true });
58
127
  });
59
128
  });
60
- describe("isValidAgentDestination — telegram", () => {
129
+ describe("validateAgentDestination — telegram unchanged (creating-account dir, house-only)", () => {
61
130
  let dirs = [];
62
131
  afterEach(() => {
63
132
  for (const d of dirs)
64
133
  rmSync(d, { recursive: true, force: true });
65
134
  dirs = [];
66
135
  });
67
- it("accepts a chat id in telegram.adminUsers", () => {
68
- const dir = makeAccountDir({ telegram: { adminUsers: [12345678] } });
69
- dirs.push(dir);
70
- expect(isValidAgentDestination(dir, "telegram", "12345678")).toEqual({ valid: true });
136
+ it("accepts a chat id in the creating account's telegram.adminUsers", () => {
137
+ const acc = makeAccountsDir((a) => seedAccount(a, HOUSE, { role: "house", telegram: { adminUsers: [12345678] } }));
138
+ dirs.push(acc);
139
+ expect(validateAgentDestination(acc, HOUSE, "telegram", "12345678")).toEqual({ valid: true });
71
140
  });
72
- it("rejects a chat id not in adminUsers", () => {
73
- const dir = makeAccountDir({ telegram: { adminUsers: [12345678] } });
74
- dirs.push(dir);
75
- expect(isValidAgentDestination(dir, "telegram", "99999999")).toEqual({
141
+ it("rejects a chat id absent from adminUsers as not-registered", () => {
142
+ const acc = makeAccountsDir((a) => seedAccount(a, HOUSE, { role: "house", telegram: { adminUsers: [12345678] } }));
143
+ dirs.push(acc);
144
+ expect(validateAgentDestination(acc, HOUSE, "telegram", "99999999")).toEqual({
76
145
  valid: false,
77
- reason: "destination-not-admin",
146
+ reason: "not-registered",
78
147
  });
79
148
  });
80
149
  });
81
- describe("boundSubAccountFor — whatsapp accountManagers only", () => {
150
+ describe("boundSubAccountFor — whatsapp accountManagers only (direct single-dir read)", () => {
82
151
  let dirs = [];
83
152
  afterEach(() => {
84
153
  for (const d of dirs)
@@ -1 +1 @@
1
- {"version":3,"file":"agent-dispatch.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/agent-dispatch.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-dispatch.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/agent-dispatch.test.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,23 @@
1
1
  export type AgentChannel = "whatsapp" | "telegram";
2
+ /**
3
+ * Reason codes are the true cause, not a symptom (Task 1439 observability):
4
+ * - `not-registered`: the destination is in no authoritative list (house's
5
+ * `adminPhones`/`accountManagers` for WhatsApp; the creating account's
6
+ * `telegram.adminUsers` for Telegram).
7
+ * - `cross-account`: the destination IS registered, but to an account other
8
+ * than the one that created the schedule (and the creator is not the house).
9
+ * Names both accounts so the mismatch is explained, not guessed.
10
+ */
2
11
  export type DestinationValidity = {
3
12
  valid: true;
4
13
  } | {
5
14
  valid: false;
6
- reason: "destination-not-admin";
15
+ reason: "not-registered";
16
+ } | {
17
+ valid: false;
18
+ reason: "cross-account";
19
+ destinationAccount: string;
20
+ scheduleAccount: string;
7
21
  };
8
22
  /**
9
23
  * Replica of `normalize.ts:normalizeE164` — strip whitespace/dashes/parens, a
@@ -24,20 +38,40 @@ export declare function readChannelAdmins(accountDir: string, channel: "telegram
24
38
  adminUsers: number[];
25
39
  };
26
40
  /**
27
- * A destination is valid iff it is a registered admin or account-manager on
28
- * that channel:
29
- * - whatsapp: `phonesMatch` against any `adminPhones` entry OR any
30
- * `accountManagers` key.
31
- * - telegram: an integer chat id present in `telegram.adminUsers`.
41
+ * The account a WhatsApp `destination` is registered to on the HOUSE's lists,
42
+ * or null if it is in neither list. A manager binding wins over an admin match:
43
+ * if the number is an `accountManagers` key its registered account is the bound
44
+ * sub-account (the isolation-relevant fact); otherwise if it is an `adminPhones`
45
+ * entry its registered account is the house. `houseDir` is the house account's
46
+ * directory; `houseAccountId` its id.
47
+ */
48
+ export declare function registeredAccountForDestination(houseDir: string, houseAccountId: string, destination: string): string | null;
49
+ /**
50
+ * Validate a dispatch destination under the Task 1439 two-part rule.
51
+ * `accountsDir` is the PARENT accounts directory
52
+ * (`$PLATFORM_ROOT/../data/accounts`); `creatingAccountId` is the account that
53
+ * created (or owns) the schedule.
54
+ *
55
+ * - whatsapp: resolve the socket-owning house, read ITS authoritative lists,
56
+ * and compute the destination's registered account. `not-registered` if it
57
+ * is in no house list. Otherwise valid iff the creator IS the house (owner
58
+ * exception: it owns the single line and may target any registered
59
+ * admin/manager) OR the registered account equals the creating account.
60
+ * Any other case is `cross-account`.
61
+ * - telegram: house-only (Task 1378; 1380 deferred). Reads the creating
62
+ * account's own `telegram.adminUsers`; there is no manager surface and thus
63
+ * no cross-account concept — an integer chat id present in the list is valid,
64
+ * anything else is `not-registered`.
32
65
  */
33
- export declare function isValidAgentDestination(accountDir: string, channel: AgentChannel, destination: string): DestinationValidity;
66
+ export declare function validateAgentDestination(accountsDir: string, creatingAccountId: string, channel: AgentChannel, destination: string): DestinationValidity;
34
67
  /**
35
68
  * Validate an `agentDispatch` at write time (shared by `schedule-event` and
36
69
  * `schedule-update` so the two write paths cannot drift on the rule): reject an
37
- * empty prompt, and reject a destination that is not a registered admin or
38
- * account-manager on the channel. Throws with a caller-facing message; returns
39
- * on success. `accountId` is the event's account; its `account.json` under
40
- * `$PLATFORM_ROOT/../data/accounts/<accountId>` holds the channel admin config.
70
+ * empty prompt, and reject a destination that fails the two-part house-authority
71
+ * rule. Throws with a caller-facing message naming the true reason; returns on
72
+ * success. `accountId` is the account that created the schedule — the authority
73
+ * lists are read from the house under `$PLATFORM_ROOT/../data/accounts`, and the
74
+ * destination's registered account must match `accountId` (house/owner aside).
41
75
  */
42
76
  export declare function validateAgentDispatch(accountId: string, agentDispatch: {
43
77
  channel: AgentChannel;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-dispatch.d.ts","sourceRoot":"","sources":["../../src/lib/agent-dispatch.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnD,MAAM,MAAM,mBAAmB,GAC3B;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED,UAAU,cAAc;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED;;uCAEuC;AACvC,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,UAAU,GAClB,cAAc,CAAC;AAClB,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,UAAU,GAClB;IAAE,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AA8B5B;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,MAAM,GAClB,mBAAmB,CAWrB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5E,IAAI,CAgBN;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMzF"}
1
+ {"version":3,"file":"agent-dispatch.d.ts","sourceRoot":"","sources":["../../src/lib/agent-dispatch.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnD;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC1C;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnG;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED,UAAU,cAAc;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED;;uCAEuC;AACvC,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,UAAU,GAClB,cAAc,CAAC;AAClB,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,UAAU,GAClB;IAAE,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AA8B5B;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAOf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,MAAM,GAClB,mBAAmB,CAmBrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5E,IAAI,CAsBN;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMzF"}
@@ -1,16 +1,23 @@
1
1
  /**
2
2
  * Task 1378 — agent-bearing scheduled dispatch: destination validation.
3
+ * Task 1439 — house single-authority + creating-account match.
3
4
  *
4
5
  * The scheduling MCP cannot import `platform/ui` (plugin boundary), so this
5
6
  * module replicates the minimal E.164 matching from
6
- * `platform/ui/app/lib/whatsapp/normalize.ts` and reads the channel admin
7
- * config straight out of the account's `account.json`. One implementation is
7
+ * `platform/ui/app/lib/whatsapp/normalize.ts`. For WhatsApp the authoritative
8
+ * `adminPhones` + `accountManagers` lists live ONLY on the socket-owning house
9
+ * account (Tasks 1377/1382), so the validator resolves the house via
10
+ * `resolveHouseOrSoleAccountId` — the same authority the inbound gate uses — and
11
+ * reads its config, NOT the event's own account. It then requires the
12
+ * destination's registered account to match the account that created the
13
+ * schedule (the house/owner account excepted), so a schedule created in account
14
+ * X cannot message another account's people. One `validateAgentDestination` is
8
15
  * shared by `schedule-event`, `schedule-update`, and the dispatcher's standing
9
- * audit so the "is this destination a valid admin/manager" decision cannot
10
- * drift between the write path and the audit.
16
+ * audit so create-time and fire-time cannot diverge on rule or reason codes.
11
17
  */
12
18
  import { readFileSync } from "node:fs";
13
19
  import { resolve } from "node:path";
20
+ import { resolveHouseOrSoleAccountId } from "../../../../../lib/account-enumeration/dist/index.js";
14
21
  /**
15
22
  * Replica of `normalize.ts:normalizeE164` — strip whitespace/dashes/parens, a
16
23
  * `whatsapp:` prefix, and a leading `+` or `00`; return digits-only or `''`.
@@ -60,31 +67,71 @@ export function readChannelAdmins(accountDir, channel) {
60
67
  return { adminUsers };
61
68
  }
62
69
  /**
63
- * A destination is valid iff it is a registered admin or account-manager on
64
- * that channel:
65
- * - whatsapp: `phonesMatch` against any `adminPhones` entry OR any
66
- * `accountManagers` key.
67
- * - telegram: an integer chat id present in `telegram.adminUsers`.
70
+ * The account a WhatsApp `destination` is registered to on the HOUSE's lists,
71
+ * or null if it is in neither list. A manager binding wins over an admin match:
72
+ * if the number is an `accountManagers` key its registered account is the bound
73
+ * sub-account (the isolation-relevant fact); otherwise if it is an `adminPhones`
74
+ * entry its registered account is the house. `houseDir` is the house account's
75
+ * directory; `houseAccountId` its id.
68
76
  */
69
- export function isValidAgentDestination(accountDir, channel, destination) {
77
+ export function registeredAccountForDestination(houseDir, houseAccountId, destination) {
78
+ const { adminPhones, accountManagers } = readChannelAdmins(houseDir, "whatsapp");
79
+ for (const [managerPhone, subAccountId] of Object.entries(accountManagers)) {
80
+ if (subAccountId && phonesMatch(managerPhone, destination))
81
+ return subAccountId;
82
+ }
83
+ if (adminPhones.some((p) => phonesMatch(p, destination)))
84
+ return houseAccountId;
85
+ return null;
86
+ }
87
+ /**
88
+ * Validate a dispatch destination under the Task 1439 two-part rule.
89
+ * `accountsDir` is the PARENT accounts directory
90
+ * (`$PLATFORM_ROOT/../data/accounts`); `creatingAccountId` is the account that
91
+ * created (or owns) the schedule.
92
+ *
93
+ * - whatsapp: resolve the socket-owning house, read ITS authoritative lists,
94
+ * and compute the destination's registered account. `not-registered` if it
95
+ * is in no house list. Otherwise valid iff the creator IS the house (owner
96
+ * exception: it owns the single line and may target any registered
97
+ * admin/manager) OR the registered account equals the creating account.
98
+ * Any other case is `cross-account`.
99
+ * - telegram: house-only (Task 1378; 1380 deferred). Reads the creating
100
+ * account's own `telegram.adminUsers`; there is no manager surface and thus
101
+ * no cross-account concept — an integer chat id present in the list is valid,
102
+ * anything else is `not-registered`.
103
+ */
104
+ export function validateAgentDestination(accountsDir, creatingAccountId, channel, destination) {
70
105
  if (channel === "whatsapp") {
71
- const { adminPhones, accountManagers } = readChannelAdmins(accountDir, "whatsapp");
72
- const inAdmins = adminPhones.some((p) => phonesMatch(p, destination));
73
- const inManagers = Object.keys(accountManagers).some((k) => phonesMatch(k, destination));
74
- return inAdmins || inManagers ? { valid: true } : { valid: false, reason: "destination-not-admin" };
106
+ const houseAccountId = resolveHouseOrSoleAccountId(accountsDir);
107
+ const houseDir = resolve(accountsDir, houseAccountId);
108
+ const registered = registeredAccountForDestination(houseDir, houseAccountId, destination);
109
+ if (registered === null)
110
+ return { valid: false, reason: "not-registered" };
111
+ if (creatingAccountId === houseAccountId)
112
+ return { valid: true };
113
+ if (registered === creatingAccountId)
114
+ return { valid: true };
115
+ return {
116
+ valid: false,
117
+ reason: "cross-account",
118
+ destinationAccount: registered,
119
+ scheduleAccount: creatingAccountId,
120
+ };
75
121
  }
76
- const { adminUsers } = readChannelAdmins(accountDir, "telegram");
122
+ const { adminUsers } = readChannelAdmins(resolve(accountsDir, creatingAccountId), "telegram");
77
123
  const asNumber = Number(destination);
78
124
  const ok = Number.isInteger(asNumber) && adminUsers.includes(asNumber);
79
- return ok ? { valid: true } : { valid: false, reason: "destination-not-admin" };
125
+ return ok ? { valid: true } : { valid: false, reason: "not-registered" };
80
126
  }
81
127
  /**
82
128
  * Validate an `agentDispatch` at write time (shared by `schedule-event` and
83
129
  * `schedule-update` so the two write paths cannot drift on the rule): reject an
84
- * empty prompt, and reject a destination that is not a registered admin or
85
- * account-manager on the channel. Throws with a caller-facing message; returns
86
- * on success. `accountId` is the event's account; its `account.json` under
87
- * `$PLATFORM_ROOT/../data/accounts/<accountId>` holds the channel admin config.
130
+ * empty prompt, and reject a destination that fails the two-part house-authority
131
+ * rule. Throws with a caller-facing message naming the true reason; returns on
132
+ * success. `accountId` is the account that created the schedule — the authority
133
+ * lists are read from the house under `$PLATFORM_ROOT/../data/accounts`, and the
134
+ * destination's registered account must match `accountId` (house/owner aside).
88
135
  */
89
136
  export function validateAgentDispatch(accountId, agentDispatch) {
90
137
  const { channel, destination, prompt } = agentDispatch;
@@ -95,10 +142,14 @@ export function validateAgentDispatch(accountId, agentDispatch) {
95
142
  if (!platformRoot) {
96
143
  throw new Error("PLATFORM_ROOT environment variable is required to validate the agentDispatch destination");
97
144
  }
98
- const accountDir = resolve(platformRoot, "..", "data/accounts", accountId);
99
- const check = isValidAgentDestination(accountDir, channel, destination);
145
+ const accountsDir = resolve(platformRoot, "..", "data/accounts");
146
+ const check = validateAgentDestination(accountsDir, accountId, channel, destination);
100
147
  if (!check.valid) {
101
- throw new Error(`agentDispatch destination "${destination}" is not a registered admin/account-manager on ${channel} — reason=${check.reason}`);
148
+ if (check.reason === "cross-account") {
149
+ throw new Error(`agentDispatch destination "${destination}" belongs to a different account on ${channel} — ` +
150
+ `reason=cross-account destinationAccount=${check.destinationAccount} scheduleAccount=${check.scheduleAccount}`);
151
+ }
152
+ throw new Error(`agentDispatch destination "${destination}" is not a registered admin/account-manager on ${channel} — reason=not-registered`);
102
153
  }
103
154
  }
104
155
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"agent-dispatch.js","sourceRoot":"","sources":["../../src/lib/agent-dispatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-dispatch.js","sourceRoot":"","sources":["../../src/lib/agent-dispatch.ts"],"names":[],"mappings":"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"}
@@ -13,12 +13,16 @@ function driverReturning(rows) {
13
13
  }),
14
14
  };
15
15
  }
16
+ // The audit now reads the authoritative lists from the socket-owning house, so
17
+ // the house dir must be UUID-named and carry role:"house" (resolver contract).
16
18
  let accountsDir;
17
- const HOUSE = "acct-house";
19
+ const HOUSE = "11111111-1111-4111-8111-111111111111";
20
+ const SUB_OK = "44444444-4444-4444-8444-444444444444";
21
+ const SUB_OTHER = "55555555-5555-4555-8555-555555555555";
18
22
  function seedHouse(waConfig) {
19
23
  const dir = join(accountsDir, HOUSE);
20
24
  mkdirSync(dir, { recursive: true });
21
- writeFileSync(join(dir, "account.json"), JSON.stringify({ whatsapp: waConfig }), "utf-8");
25
+ writeFileSync(join(dir, "account.json"), JSON.stringify({ role: "house", whatsapp: waConfig }), "utf-8");
22
26
  }
23
27
  let errSpy;
24
28
  function auditLines() {
@@ -36,18 +40,31 @@ afterEach(() => {
36
40
  vi.clearAllMocks();
37
41
  });
38
42
  describe("runStandingAudit", () => {
39
- it("emits destination-not-admin when the destination left adminPhones", async () => {
43
+ it("emits not-registered when the destination is in no house list", async () => {
40
44
  seedHouse({ adminPhones: ["+447111111111"] }); // destination not present
41
45
  const driver = driverReturning([
42
46
  { eventId: "e1", accountId: HOUSE, agentChannel: "whatsapp", agentDestination: "+447504472444" },
43
47
  ]);
44
48
  await runStandingAudit(driver, [HOUSE], accountsDir);
45
49
  expect(auditLines()).toEqual([
46
- expect.stringContaining("op=stale-dispatch eventId=e1 reason=destination-not-admin"),
50
+ expect.stringContaining("op=stale-dispatch eventId=e1 reason=not-registered"),
51
+ ]);
52
+ });
53
+ it("emits cross-account when a house event targets a manager bound to a different sub-account", async () => {
54
+ // The manager is bound to SUB_OK, but the event was created in SUB_OTHER.
55
+ seedHouse({ accountManagers: { "447504472444": SUB_OK } });
56
+ mkdirSync(join(accountsDir, SUB_OK), { recursive: true });
57
+ mkdirSync(join(accountsDir, SUB_OTHER), { recursive: true });
58
+ const driver = driverReturning([
59
+ { eventId: "e5", accountId: SUB_OTHER, agentChannel: "whatsapp", agentDestination: "+447504472444" },
60
+ ]);
61
+ await runStandingAudit(driver, [SUB_OTHER], accountsDir);
62
+ expect(auditLines()).toEqual([
63
+ expect.stringContaining(`op=stale-dispatch eventId=e5 reason=cross-account destinationAccount=${SUB_OK} scheduleAccount=${SUB_OTHER}`),
47
64
  ]);
48
65
  });
49
66
  it("emits sub-account-missing when a manager binding points at a deleted sub-account", async () => {
50
- seedHouse({ accountManagers: { "447504472444": "sub-gone" } }); // sub dir never created
67
+ seedHouse({ accountManagers: { "447504472444": "66666666-6666-4666-8666-666666666666" } }); // sub dir never created
51
68
  const driver = driverReturning([
52
69
  { eventId: "e2", accountId: HOUSE, agentChannel: "whatsapp", agentDestination: "+447504472444" },
53
70
  ]);
@@ -56,16 +73,16 @@ describe("runStandingAudit", () => {
56
73
  expect.stringContaining("op=stale-dispatch eventId=e2 reason=sub-account-missing"),
57
74
  ]);
58
75
  });
59
- it("emits nothing for a healthy binding (manager + present sub-account)", async () => {
60
- seedHouse({ accountManagers: { "447504472444": "sub-ok" } });
61
- mkdirSync(join(accountsDir, "sub-ok"), { recursive: true });
76
+ it("emits nothing for a healthy binding (house event, manager + present sub-account)", async () => {
77
+ seedHouse({ accountManagers: { "447504472444": SUB_OK } });
78
+ mkdirSync(join(accountsDir, SUB_OK), { recursive: true });
62
79
  const driver = driverReturning([
63
80
  { eventId: "e3", accountId: HOUSE, agentChannel: "whatsapp", agentDestination: "+447504472444" },
64
81
  ]);
65
82
  await runStandingAudit(driver, [HOUSE], accountsDir);
66
83
  expect(auditLines()).toEqual([]);
67
84
  });
68
- it("emits nothing for a healthy plain admin destination", async () => {
85
+ it("emits nothing for a healthy plain admin destination (house event)", async () => {
69
86
  seedHouse({ adminPhones: ["+447504472444"] });
70
87
  const driver = driverReturning([
71
88
  { eventId: "e4", accountId: HOUSE, agentChannel: "whatsapp", agentDestination: "+447504472444" },
@@ -73,5 +90,27 @@ describe("runStandingAudit", () => {
73
90
  await runStandingAudit(driver, [HOUSE], accountsDir);
74
91
  expect(auditLines()).toEqual([]);
75
92
  });
93
+ it("emits nothing when a sub-account event targets its OWN manager", async () => {
94
+ seedHouse({ accountManagers: { "447504472444": SUB_OK } });
95
+ mkdirSync(join(accountsDir, SUB_OK), { recursive: true });
96
+ const driver = driverReturning([
97
+ { eventId: "e6", accountId: SUB_OK, agentChannel: "whatsapp", agentDestination: "+447504472444" },
98
+ ]);
99
+ await runStandingAudit(driver, [SUB_OK], accountsDir);
100
+ expect(auditLines()).toEqual([]);
101
+ });
102
+ it("never throws on house drift (multi-house): returns with op=house-unresolved", async () => {
103
+ // Two role:"house" dirs — the resolver loud-fails. The audit must not throw
104
+ // into the sweep; it emits one diagnostic and returns.
105
+ seedHouse({ adminPhones: ["+447504472444"] });
106
+ const secondHouse = "77777777-7777-4777-8777-777777777777";
107
+ mkdirSync(join(accountsDir, secondHouse), { recursive: true });
108
+ writeFileSync(join(accountsDir, secondHouse, "account.json"), JSON.stringify({ role: "house", whatsapp: {} }), "utf-8");
109
+ const driver = driverReturning([
110
+ { eventId: "e7", accountId: HOUSE, agentChannel: "whatsapp", agentDestination: "+447504472444" },
111
+ ]);
112
+ await expect(runStandingAudit(driver, [HOUSE], accountsDir)).resolves.toBeUndefined();
113
+ expect(auditLines().some((l) => l.includes("op=house-unresolved"))).toBe(true);
114
+ });
76
115
  });
77
116
  //# sourceMappingURL=standing-audit.test.js.map