@rubytech/create-sitedesk-code 0.1.512 → 0.1.514

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 (194) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/docs/superpowers/plans/2026-07-27-task-2028-declared-file-write-deny.md +303 -0
  3. package/payload/platform/docs/superpowers/plans/2026-07-27-task-2052-account-machinery-write-fence.md +250 -0
  4. package/payload/platform/docs/superpowers/specs/2026-07-27-task-2028-declared-file-write-deny-design.md +127 -0
  5. package/payload/platform/docs/superpowers/specs/2026-07-27-task-2052-account-machinery-write-fence-design.md +150 -0
  6. package/payload/platform/lib/account-schema-regions/dist/index.d.ts +5 -0
  7. package/payload/platform/lib/account-schema-regions/dist/index.d.ts.map +1 -1
  8. package/payload/platform/lib/account-schema-regions/dist/index.js +5 -0
  9. package/payload/platform/lib/account-schema-regions/dist/index.js.map +1 -1
  10. package/payload/platform/lib/account-schema-regions/src/index.ts +5 -0
  11. package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard-bash.test.sh +14 -0
  12. package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard.test.sh +79 -0
  13. package/payload/platform/plugins/admin/hooks/fs-schema-guard-bash-post.sh +19 -0
  14. package/payload/platform/plugins/admin/hooks/fs-schema-guard.sh +64 -1
  15. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +12 -0
  16. package/payload/platform/plugins/cloudflare/PLUGIN.md +1 -1
  17. package/payload/platform/plugins/cloudflare/bin/schema-exposed-dirs.mjs +1 -1
  18. package/payload/platform/plugins/scheduling/PLUGIN.md +1 -1
  19. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +1 -1
  20. package/payload/platform/scripts/__tests__/account-schema-owned-dirs.test.sh +26 -0
  21. package/payload/platform/scripts/lib/account-schema-owned-dirs.py +40 -4
  22. package/payload/platform/scripts/logs-read.sh +47 -24
  23. package/payload/platform/scripts/logs-read.test.sh +73 -31
  24. package/payload/platform/scripts/provision-worktree.sh +80 -0
  25. package/payload/platform/templates/account-schema/SCHEMA.md +17 -0
  26. package/payload/server/{chunk-2WAXM5N2.js → chunk-S6HYTIU3.js} +2 -3
  27. package/payload/server/maxy-edge.js +1 -1
  28. package/payload/server/public/activity.html +5 -5
  29. package/payload/server/public/agents.html +4 -4
  30. package/payload/server/public/assets/{AdminLoginScreens-bksN0XPe.js → AdminLoginScreens-Cs1jSnOF.js} +1 -1
  31. package/payload/server/public/assets/AdminLoginScreens-Cs1jSnOF.js.br +0 -0
  32. package/payload/server/public/assets/AdminLoginScreens-Cs1jSnOF.js.gz +0 -0
  33. package/payload/server/public/assets/{AdminShell-BMPEWNZk.js → AdminShell-DkrURZnF.js} +1 -1
  34. package/payload/server/public/assets/AdminShell-DkrURZnF.js.br +0 -0
  35. package/payload/server/public/assets/AdminShell-DkrURZnF.js.gz +0 -0
  36. package/payload/server/public/assets/{activity-ByWYF5dC.js → activity-BgZISMuE.js} +1 -1
  37. package/payload/server/public/assets/activity-BgZISMuE.js.br +0 -0
  38. package/payload/server/public/assets/activity-BgZISMuE.js.gz +0 -0
  39. package/payload/server/public/assets/{admin-6QN-k3zQ.js → admin-DjFysc3-.js} +1 -1
  40. package/payload/server/public/assets/admin-DjFysc3-.js.br +0 -0
  41. package/payload/server/public/assets/admin-DjFysc3-.js.gz +0 -0
  42. package/payload/server/public/assets/{agents-C0rTfrYd.js → agents-Bx-MSZW6.js} +1 -1
  43. package/payload/server/public/assets/agents-Bx-MSZW6.js.br +0 -0
  44. package/payload/server/public/assets/agents-Bx-MSZW6.js.gz +0 -0
  45. package/payload/server/public/assets/{browser-4tTaem8N.js → browser-1I7syhHu.js} +1 -1
  46. package/payload/server/public/assets/browser-1I7syhHu.js.br +0 -0
  47. package/payload/server/public/assets/browser-1I7syhHu.js.gz +0 -0
  48. package/payload/server/public/assets/{calendar-BEjnkKG1.js → calendar-D_04JIo1.js} +1 -1
  49. package/payload/server/public/assets/calendar-D_04JIo1.js.br +0 -0
  50. package/payload/server/public/assets/calendar-D_04JIo1.js.gz +0 -0
  51. package/payload/server/public/assets/chat-BFH3FM5a.js +1 -0
  52. package/payload/server/public/assets/chat-BFH3FM5a.js.br +0 -0
  53. package/payload/server/public/assets/chat-BFH3FM5a.js.gz +0 -0
  54. package/payload/server/public/assets/chevron-left-Ux9-qLkk.js +1 -0
  55. package/payload/server/public/assets/chevron-right-BwIuCfyG.js +1 -0
  56. package/payload/server/public/assets/chevron-right-BwIuCfyG.js.br +0 -0
  57. package/payload/server/public/assets/clock-DhJdZRhC.js +1 -0
  58. package/payload/server/public/assets/clock-DhJdZRhC.js.br +0 -0
  59. package/payload/server/public/assets/data-ChY_uSIk.js +1 -0
  60. package/payload/server/public/assets/data-ChY_uSIk.js.br +0 -0
  61. package/payload/server/public/assets/data-ChY_uSIk.js.gz +0 -0
  62. package/payload/server/public/assets/{file-text-DMKw3nIk.js → file-text-DkvKqHMx.js} +1 -1
  63. package/payload/server/public/assets/file-text-DkvKqHMx.js.br +0 -0
  64. package/payload/server/public/assets/file-text-DkvKqHMx.js.gz +0 -0
  65. package/payload/server/public/assets/{graph-C3vW8lvw.js → graph-CCZhrwZX.js} +1 -1
  66. package/payload/server/public/assets/graph-CCZhrwZX.js.br +0 -0
  67. package/payload/server/public/assets/graph-CCZhrwZX.js.gz +0 -0
  68. package/payload/server/public/assets/{graph-labels-BZgd0L6n.js → graph-labels-BJ7puQkX.js} +1 -1
  69. package/payload/server/public/assets/graph-labels-BJ7puQkX.js.br +0 -0
  70. package/payload/server/public/assets/graph-labels-BJ7puQkX.js.gz +0 -0
  71. package/payload/server/public/assets/{maximize-2-la3IBA3M.js → maximize-2-Xdj804U1.js} +1 -1
  72. package/payload/server/public/assets/maximize-2-Xdj804U1.js.br +0 -0
  73. package/payload/server/public/assets/maximize-2-Xdj804U1.js.gz +0 -0
  74. package/payload/server/public/assets/{operator-D9NgVL9_.js → operator-BkfNpBs7.js} +1 -1
  75. package/payload/server/public/assets/operator-BkfNpBs7.js.br +0 -0
  76. package/payload/server/public/assets/operator-BkfNpBs7.js.gz +0 -0
  77. package/payload/server/public/assets/{page-DC11gesX.js → page-BoYc9c4a.js} +1 -1
  78. package/payload/server/public/assets/page-BoYc9c4a.js.br +0 -0
  79. package/payload/server/public/assets/page-BoYc9c4a.js.gz +0 -0
  80. package/payload/server/public/assets/{page-BWFHRIAH.js → page-D5n8ShE7.js} +1 -1
  81. package/payload/server/public/assets/page-D5n8ShE7.js.br +0 -0
  82. package/payload/server/public/assets/page-D5n8ShE7.js.gz +0 -0
  83. package/payload/server/public/assets/{public-DQbbLHQN.js → public-CX5XSrxD.js} +1 -1
  84. package/payload/server/public/assets/public-CX5XSrxD.js.br +0 -0
  85. package/payload/server/public/assets/public-CX5XSrxD.js.gz +0 -0
  86. package/payload/server/public/assets/{rotate-ccw-OQD5si8N.js → rotate-ccw-dh_OhL23.js} +1 -1
  87. package/payload/server/public/assets/rotate-ccw-dh_OhL23.js.br +0 -0
  88. package/payload/server/public/assets/rotate-ccw-dh_OhL23.js.gz +0 -0
  89. package/payload/server/public/assets/{routines-asrBGZUR.js → routines-bb7dxcrr.js} +1 -1
  90. package/payload/server/public/assets/routines-bb7dxcrr.js.br +0 -0
  91. package/payload/server/public/assets/routines-bb7dxcrr.js.gz +0 -0
  92. package/payload/server/public/assets/{skills-D4ECwoxa.js → skills-TeMwxXmJ.js} +1 -1
  93. package/payload/server/public/assets/skills-TeMwxXmJ.js.br +0 -0
  94. package/payload/server/public/assets/skills-TeMwxXmJ.js.gz +0 -0
  95. package/payload/server/public/assets/{tasks-U3QdbUsO.js → tasks-BqBBJlkg.js} +1 -1
  96. package/payload/server/public/assets/tasks-BqBBJlkg.js.br +0 -0
  97. package/payload/server/public/assets/tasks-BqBBJlkg.js.gz +0 -0
  98. package/payload/server/public/assets/{time-entry-format-BgdTKgYr.js → time-entry-format-Cy_T-wiD.js} +1 -1
  99. package/payload/server/public/assets/time-entry-format-Cy_T-wiD.js.br +3 -0
  100. package/payload/server/public/assets/time-entry-format-Cy_T-wiD.js.gz +0 -0
  101. package/payload/server/public/assets/{triangle-alert-Ck_3VhT9.js → triangle-alert-D-bSbPnX.js} +1 -1
  102. package/payload/server/public/assets/triangle-alert-D-bSbPnX.js.br +1 -0
  103. package/payload/server/public/assets/triangle-alert-D-bSbPnX.js.gz +0 -0
  104. package/payload/server/public/assets/{useCopyFeedback-BdUwyNpa.js → useCopyFeedback-L7L55nFl.js} +1 -1
  105. package/payload/server/public/assets/useCopyFeedback-L7L55nFl.js.br +0 -0
  106. package/payload/server/public/assets/useCopyFeedback-L7L55nFl.js.gz +0 -0
  107. package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css +1 -0
  108. package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css.br +0 -0
  109. package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css.gz +0 -0
  110. package/payload/server/public/assets/{useVoiceRecorder-ChnBrzbZ.js → useVoiceRecorder-MuZ7lpet.js} +1 -1
  111. package/payload/server/public/assets/useVoiceRecorder-MuZ7lpet.js.br +0 -0
  112. package/payload/server/public/assets/useVoiceRecorder-MuZ7lpet.js.gz +0 -0
  113. package/payload/server/public/assets/{wrench-Cpee3C3J.js → wrench-DUG1SZQB.js} +1 -1
  114. package/payload/server/public/assets/wrench-DUG1SZQB.js.br +0 -0
  115. package/payload/server/public/assets/wrench-DUG1SZQB.js.gz +0 -0
  116. package/payload/server/public/brand-defaults.css +2 -0
  117. package/payload/server/public/browser.html +4 -4
  118. package/payload/server/public/calendar.html +7 -7
  119. package/payload/server/public/chat.html +13 -13
  120. package/payload/server/public/data.html +11 -11
  121. package/payload/server/public/graph.html +9 -9
  122. package/payload/server/public/index.html +14 -14
  123. package/payload/server/public/operator.html +14 -14
  124. package/payload/server/public/public.html +13 -13
  125. package/payload/server/public/routines.html +6 -6
  126. package/payload/server/public/skills.html +5 -5
  127. package/payload/server/public/tasks.html +6 -6
  128. package/payload/server/server.js +126 -47
  129. package/payload/server/public/assets/AdminLoginScreens-bksN0XPe.js.br +0 -0
  130. package/payload/server/public/assets/AdminLoginScreens-bksN0XPe.js.gz +0 -0
  131. package/payload/server/public/assets/AdminShell-BMPEWNZk.js.br +0 -0
  132. package/payload/server/public/assets/AdminShell-BMPEWNZk.js.gz +0 -0
  133. package/payload/server/public/assets/activity-ByWYF5dC.js.br +0 -0
  134. package/payload/server/public/assets/activity-ByWYF5dC.js.gz +0 -0
  135. package/payload/server/public/assets/admin-6QN-k3zQ.js.br +0 -0
  136. package/payload/server/public/assets/admin-6QN-k3zQ.js.gz +0 -0
  137. package/payload/server/public/assets/agents-C0rTfrYd.js.br +0 -0
  138. package/payload/server/public/assets/agents-C0rTfrYd.js.gz +0 -0
  139. package/payload/server/public/assets/browser-4tTaem8N.js.br +0 -0
  140. package/payload/server/public/assets/browser-4tTaem8N.js.gz +0 -0
  141. package/payload/server/public/assets/calendar-BEjnkKG1.js.br +0 -0
  142. package/payload/server/public/assets/calendar-BEjnkKG1.js.gz +0 -0
  143. package/payload/server/public/assets/chat-DBgzjDIE.js +0 -1
  144. package/payload/server/public/assets/chat-DBgzjDIE.js.br +0 -0
  145. package/payload/server/public/assets/chat-DBgzjDIE.js.gz +0 -0
  146. package/payload/server/public/assets/chevron-left-DqYv3oFh.js +0 -1
  147. package/payload/server/public/assets/chevron-right-CQfPGsFb.js +0 -1
  148. package/payload/server/public/assets/chevron-right-CQfPGsFb.js.br +0 -0
  149. package/payload/server/public/assets/clock-Dn6FHB51.js +0 -1
  150. package/payload/server/public/assets/clock-Dn6FHB51.js.br +0 -0
  151. package/payload/server/public/assets/clock-Dn6FHB51.js.gz +0 -0
  152. package/payload/server/public/assets/data-D_e6Vdfd.js +0 -1
  153. package/payload/server/public/assets/data-D_e6Vdfd.js.br +0 -0
  154. package/payload/server/public/assets/data-D_e6Vdfd.js.gz +0 -0
  155. package/payload/server/public/assets/file-text-DMKw3nIk.js.br +0 -0
  156. package/payload/server/public/assets/file-text-DMKw3nIk.js.gz +0 -0
  157. package/payload/server/public/assets/graph-C3vW8lvw.js.br +0 -0
  158. package/payload/server/public/assets/graph-C3vW8lvw.js.gz +0 -0
  159. package/payload/server/public/assets/graph-labels-BZgd0L6n.js.br +0 -0
  160. package/payload/server/public/assets/graph-labels-BZgd0L6n.js.gz +0 -0
  161. package/payload/server/public/assets/maximize-2-la3IBA3M.js.br +0 -0
  162. package/payload/server/public/assets/maximize-2-la3IBA3M.js.gz +0 -0
  163. package/payload/server/public/assets/operator-D9NgVL9_.js.br +0 -0
  164. package/payload/server/public/assets/operator-D9NgVL9_.js.gz +0 -0
  165. package/payload/server/public/assets/page-BWFHRIAH.js.br +0 -0
  166. package/payload/server/public/assets/page-BWFHRIAH.js.gz +0 -0
  167. package/payload/server/public/assets/page-DC11gesX.js.br +0 -0
  168. package/payload/server/public/assets/page-DC11gesX.js.gz +0 -0
  169. package/payload/server/public/assets/public-DQbbLHQN.js.br +0 -0
  170. package/payload/server/public/assets/public-DQbbLHQN.js.gz +0 -0
  171. package/payload/server/public/assets/rotate-ccw-OQD5si8N.js.br +0 -0
  172. package/payload/server/public/assets/rotate-ccw-OQD5si8N.js.gz +0 -0
  173. package/payload/server/public/assets/routines-asrBGZUR.js.br +0 -0
  174. package/payload/server/public/assets/routines-asrBGZUR.js.gz +0 -0
  175. package/payload/server/public/assets/skills-D4ECwoxa.js.br +0 -0
  176. package/payload/server/public/assets/skills-D4ECwoxa.js.gz +0 -0
  177. package/payload/server/public/assets/tasks-U3QdbUsO.js.br +0 -0
  178. package/payload/server/public/assets/tasks-U3QdbUsO.js.gz +0 -0
  179. package/payload/server/public/assets/time-entry-format-BgdTKgYr.js.br +0 -0
  180. package/payload/server/public/assets/time-entry-format-BgdTKgYr.js.gz +0 -0
  181. package/payload/server/public/assets/triangle-alert-Ck_3VhT9.js.br +0 -0
  182. package/payload/server/public/assets/triangle-alert-Ck_3VhT9.js.gz +0 -0
  183. package/payload/server/public/assets/useCopyFeedback-BdUwyNpa.js.br +0 -0
  184. package/payload/server/public/assets/useCopyFeedback-BdUwyNpa.js.gz +0 -0
  185. package/payload/server/public/assets/useSubAccountSwitcher-DOWQXDT8.css +0 -1
  186. package/payload/server/public/assets/useSubAccountSwitcher-DOWQXDT8.css.br +0 -0
  187. package/payload/server/public/assets/useSubAccountSwitcher-DOWQXDT8.css.gz +0 -0
  188. package/payload/server/public/assets/useVoiceRecorder-ChnBrzbZ.js.br +0 -0
  189. package/payload/server/public/assets/useVoiceRecorder-ChnBrzbZ.js.gz +0 -0
  190. package/payload/server/public/assets/wrench-Cpee3C3J.js.br +0 -2
  191. package/payload/server/public/assets/wrench-Cpee3C3J.js.gz +0 -0
  192. /package/payload/server/public/assets/{useSubAccountSwitcher-CJKjEPNN.js → useSubAccountSwitcher-DH0P6QMV.js} +0 -0
  193. /package/payload/server/public/assets/{useSubAccountSwitcher-CJKjEPNN.js.br → useSubAccountSwitcher-DH0P6QMV.js.br} +0 -0
  194. /package/payload/server/public/assets/{useSubAccountSwitcher-CJKjEPNN.js.gz → useSubAccountSwitcher-DH0P6QMV.js.gz} +0 -0
@@ -118,7 +118,7 @@ import {
118
118
  vncLog,
119
119
  walkPremiumBundles,
120
120
  writeAdminUserAndPerson
121
- } from "./chunk-2WAXM5N2.js";
121
+ } from "./chunk-S6HYTIU3.js";
122
122
  import {
123
123
  D1_MAX_SQL_STATEMENT_BYTES,
124
124
  D1_QUERY_MAX_BODY_BYTES,
@@ -5104,6 +5104,21 @@ function resolvePlatformAccountId(accountsDir = ACCOUNTS_DIR) {
5104
5104
  const routed = readChannelRoutingOverride(accountsDir, houseId);
5105
5105
  return routed ?? houseId;
5106
5106
  }
5107
+ function resolveHouseAccountId(accountsDir = ACCOUNTS_DIR) {
5108
+ return resolveHouseId(accountsDir);
5109
+ }
5110
+
5111
+ // app/lib/whatsapp/account-id-shape.ts
5112
+ var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
5113
+ function isUuidAccountId(id) {
5114
+ return UUID_RE2.test(id);
5115
+ }
5116
+ function warnNonUuidAccount(caller2, accountId) {
5117
+ if (isUuidAccountId(accountId)) return;
5118
+ console.error(
5119
+ `[whatsapp-account-scope] op=non-uuid-account caller=${caller2} accountId=${accountId}`
5120
+ );
5121
+ }
5107
5122
 
5108
5123
  // app/lib/managed-service.ts
5109
5124
  import { join as join7 } from "path";
@@ -6221,8 +6236,9 @@ function buildSelfChatDispatch(input) {
6221
6236
  isGroup: false
6222
6237
  }),
6223
6238
  media: [],
6224
- // Self-chat is the owner: the session scopes to the house account (Task 1383).
6225
- effectiveAccountId: input.accountId,
6239
+ // Self-chat is the owner: the session scopes to the house account (Task 1383),
6240
+ // named by its platform UUID (Task 1850).
6241
+ effectiveAccountId: input.platformAccountId,
6226
6242
  // Task 1575 — self-chat is unambiguously the owner, so attribute the spawn
6227
6243
  // to the owner userId even when the owner phone is unbound in users.json.
6228
6244
  ownerSelfPhone: true
@@ -6264,10 +6280,12 @@ async function startConnection(accountId) {
6264
6280
  return;
6265
6281
  }
6266
6282
  let platformAccountId;
6283
+ let houseAccountId;
6267
6284
  try {
6268
6285
  platformAccountId = resolvePlatformAccountId();
6286
+ houseAccountId = resolveHouseAccountId();
6269
6287
  console.error(
6270
- `[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${platformAccountId}`
6288
+ `[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${platformAccountId} house=${houseAccountId}`
6271
6289
  );
6272
6290
  } catch (err) {
6273
6291
  const reason = err instanceof Error ? err.message : String(err);
@@ -6280,6 +6298,7 @@ async function startConnection(accountId) {
6280
6298
  const conn = {
6281
6299
  accountId,
6282
6300
  platformAccountId,
6301
+ houseAccountId,
6283
6302
  accountName: whatsAppConfig.accounts?.[accountId]?.name,
6284
6303
  authDir,
6285
6304
  sock: null,
@@ -6353,20 +6372,30 @@ function resolveReadStoreKey(accountId) {
6353
6372
  }
6354
6373
  function resolveInboundPersistAccount(args) {
6355
6374
  const result = args.accessResult;
6356
- if (result?.allowed && result.reason === "account-manager" && result.effectiveAccountId) {
6357
- return result.effectiveAccountId;
6358
- }
6359
- return args.connPlatformAccountId;
6375
+ const account = result?.allowed && result.reason === "account-manager" && result.effectiveAccountId ? result.effectiveAccountId : args.connPlatformAccountId;
6376
+ warnNonUuidAccount("inbound-persist", account);
6377
+ return account;
6378
+ }
6379
+ function isManagerRoutedToHouse(args) {
6380
+ const result = args.accessResult;
6381
+ return result?.allowed === true && result.reason === "account-manager" && result.effectiveAccountId === args.houseAccountId;
6360
6382
  }
6361
6383
  function resolveConversationPersistAccount(sendAccountId, counterpartyPhone) {
6362
6384
  const conn = findConnectionByKey(Array.from(connections2.values()), sendAccountId);
6363
- if (!conn) return sendAccountId;
6385
+ if (!conn) {
6386
+ warnNonUuidAccount("reply-append-no-connection", sendAccountId);
6387
+ return sendAccountId;
6388
+ }
6364
6389
  const access = checkDmAccess({
6365
6390
  senderPhone: counterpartyPhone,
6366
6391
  selfPhone: conn.selfPhone ?? "",
6367
6392
  config: whatsAppConfig,
6393
+ // The per-number sub-config is keyed by the credential DIRNAME.
6368
6394
  accountConfig: whatsAppConfig.accounts?.[conn.accountId],
6369
- accountId: conn.accountId,
6395
+ // Task 1850 — the account SCOPE is the platform UUID. The gate assigns this
6396
+ // to `effectiveAccountId` for every non-manager admit, and that value reaches
6397
+ // the graph and the spawn; the dirname is a credential path, not an account.
6398
+ accountId: conn.platformAccountId,
6370
6399
  isValidAccount: (id) => isValidAccountId(id)
6371
6400
  });
6372
6401
  return resolveInboundPersistAccount({
@@ -6380,10 +6409,12 @@ function listConnectionPlatformAccountIds() {
6380
6409
  async function registerLoginSocket(accountId, sock, authDir) {
6381
6410
  if (!configDir) throw new Error("WhatsApp manager not initialized");
6382
6411
  let platformAccountId;
6412
+ let houseAccountId;
6383
6413
  try {
6384
6414
  platformAccountId = resolvePlatformAccountId();
6415
+ houseAccountId = resolveHouseAccountId();
6385
6416
  console.error(
6386
- `[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${platformAccountId}`
6417
+ `[whatsapp-persist] resolved-account-id waname=${accountId} uuid=${platformAccountId} house=${houseAccountId}`
6387
6418
  );
6388
6419
  } catch (err) {
6389
6420
  const reason = err instanceof Error ? err.message : String(err);
@@ -6396,6 +6427,7 @@ async function registerLoginSocket(accountId, sock, authDir) {
6396
6427
  const conn = {
6397
6428
  accountId,
6398
6429
  platformAccountId,
6430
+ houseAccountId,
6399
6431
  accountName: whatsAppConfig.accounts?.[accountId]?.name,
6400
6432
  authDir,
6401
6433
  sock,
@@ -6700,8 +6732,11 @@ function monitorInbound(conn) {
6700
6732
  senderPhone,
6701
6733
  selfPhone: conn.selfPhone ?? "",
6702
6734
  config: whatsAppConfig,
6735
+ // Keyed by the credential DIRNAME — a per-number sub-config.
6703
6736
  accountConfig: whatsAppConfig.accounts?.[conn.accountId],
6704
- accountId: conn.accountId,
6737
+ // Task 1850 — the account SCOPE is the platform UUID, never the
6738
+ // dirname. See resolveConversationPersistAccount.
6739
+ accountId: conn.platformAccountId,
6705
6740
  isValidAccount: (id) => isValidAccountId(id)
6706
6741
  });
6707
6742
  const persistAccountId = resolveInboundPersistAccount({
@@ -6894,6 +6929,7 @@ function monitorInbound(conn) {
6894
6929
  };
6895
6930
  dispatchInboundPayload(conn, buildSelfChatDispatch({
6896
6931
  accountId: conn.accountId,
6932
+ platformAccountId: conn.platformAccountId,
6897
6933
  selfPhone: conn.selfPhone,
6898
6934
  remoteJid,
6899
6935
  text: decision.text,
@@ -7043,7 +7079,7 @@ async function handleInboundMessage(conn, msg) {
7043
7079
  selfPhone,
7044
7080
  config: whatsAppConfig,
7045
7081
  accountConfig: whatsAppConfig.accounts?.[conn.accountId],
7046
- accountId: conn.accountId,
7082
+ accountId: conn.platformAccountId,
7047
7083
  isValidAccount: (id) => isValidAccountId(id),
7048
7084
  resolvePersonByPhone
7049
7085
  });
@@ -7056,7 +7092,10 @@ async function handleInboundMessage(conn, msg) {
7056
7092
  `[whatsapp-native] op=account-manager-reject senderId=${senderPhone} reason=unresolved-effective-account`
7057
7093
  );
7058
7094
  }
7059
- if (accessResult.allowed && accessResult.reason === "account-manager" && accessResult.effectiveAccountId === conn.accountId) {
7095
+ if (isManagerRoutedToHouse({
7096
+ accessResult,
7097
+ houseAccountId: conn.houseAccountId
7098
+ })) {
7060
7099
  console.error(
7061
7100
  `[whatsapp-native] op=escalation-tripwire senderId=${senderPhone} reason=account-manager-routed-to-house effectiveAccount=${accessResult.effectiveAccountId}`
7062
7101
  );
@@ -8152,6 +8191,11 @@ function createScheduleInjectRoutes(deps) {
8152
8191
  // server/index.ts
8153
8192
  var import_dist9 = __toESM(require_dist(), 1);
8154
8193
 
8194
+ // app/lib/whatsapp/gateway/manages-account.ts
8195
+ function managesAccountFor(effectiveAccountId, connPlatformAccountId) {
8196
+ return effectiveAccountId === connPlatformAccountId ? "none" : effectiveAccountId;
8197
+ }
8198
+
8155
8199
  // app/lib/whatsapp/socket-resolution-error.ts
8156
8200
  function formatPresentKeys(presentKeys) {
8157
8201
  return presentKeys.join(",") || "none";
@@ -8415,6 +8459,20 @@ function setAccountManager(accountDir, phone, subAccountId, mode = "active") {
8415
8459
  if (!validIds.includes(sub)) {
8416
8460
  return { ok: false, error: `Sub-account "${sub}" is not in this install's account registry. Check the sub-account id and try again.` };
8417
8461
  }
8462
+ let houseId;
8463
+ try {
8464
+ houseId = resolveHouseOrSoleAccountId(dirname2(resolve9(accountDir)));
8465
+ } catch (err) {
8466
+ return { ok: false, error: `Could not resolve the house account to validate the binding: ${err instanceof Error ? err.message : String(err)}. Try again.` };
8467
+ }
8468
+ if (sub === houseId) {
8469
+ console.error(`${TAG22} set-account-manager rejected phone=${normalized} reason=house-account-binding`);
8470
+ return {
8471
+ ok: false,
8472
+ reason: "house-account-binding",
8473
+ error: `${sub} is the house account, not a sub-account. An account manager bound to it would get house-owner admin scope. To make ${normalized} a house admin, add it to admin phones instead.`
8474
+ };
8475
+ }
8418
8476
  try {
8419
8477
  const config = readConfig(accountDir);
8420
8478
  if (!config.whatsapp || typeof config.whatsapp !== "object") {
@@ -9594,7 +9652,8 @@ app2.post("/config", async (c) => {
9594
9652
  }
9595
9653
  const managerMode = mode === "passive" ? "passive" : "active";
9596
9654
  const result = setAccountManager(account.accountDir, phone, managesAccount, managerMode);
9597
- console.error(`${TAG26} config action=add-account-manager phone=${phone} managesAccount=${managesAccount} mode=${managerMode} ok=${result.ok}`);
9655
+ const managerReasonTail = !result.ok && result.reason ? ` reason=${result.reason}` : "";
9656
+ console.error(`${TAG26} config action=add-account-manager phone=${phone} managesAccount=${managesAccount} mode=${managerMode} ok=${result.ok}${managerReasonTail}`);
9598
9657
  return c.json(result, result.ok ? 200 : 400);
9599
9658
  }
9600
9659
  case "remove-account-manager": {
@@ -11569,13 +11628,13 @@ async function runPortalIndexPush(root) {
11569
11628
  import { existsSync as existsSync12, readdirSync as readdirSync9, statSync as statSync5 } from "fs";
11570
11629
  import { join as join17 } from "path";
11571
11630
  var GOOGLE_PENDING_LIFETIME_SEC = 600;
11572
- var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11631
+ var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11573
11632
  function runGooglePendingAudit(accountsDir, nowMs, emit, readMtimeMs = (path3) => statSync5(path3).mtimeMs) {
11574
11633
  let scanned = 0;
11575
11634
  let stranded = 0;
11576
11635
  if (existsSync12(accountsDir)) {
11577
11636
  for (const accountId of readdirSync9(accountsDir)) {
11578
- if (!UUID_RE2.test(accountId)) continue;
11637
+ if (!UUID_RE3.test(accountId)) continue;
11579
11638
  const pendingPath2 = join17(accountsDir, accountId, "secrets", "google", "pending-oauth.enc");
11580
11639
  try {
11581
11640
  if (!existsSync12(pendingPath2)) continue;
@@ -11721,8 +11780,8 @@ async function loadTitleCacheOutcome(accountDir) {
11721
11780
  async function loadTitleCache(accountDir) {
11722
11781
  return (await loadTitleCacheOutcome(accountDir)).cache;
11723
11782
  }
11724
- async function saveTitleCacheMerged(accountDir, updates) {
11725
- if (updates.size === 0) return;
11783
+ async function saveTitleCacheMerged(accountDir, updates, evict) {
11784
+ if (updates.size === 0 && (evict === void 0 || evict.size === 0)) return 0;
11726
11785
  const path3 = titleCachePath(accountDir);
11727
11786
  let merged;
11728
11787
  try {
@@ -11732,6 +11791,12 @@ async function saveTitleCacheMerged(accountDir, updates) {
11732
11791
  merged = /* @__PURE__ */ new Map();
11733
11792
  }
11734
11793
  for (const [sessionId, entry] of updates) merged.set(sessionId, entry);
11794
+ let evicted = 0;
11795
+ if (evict !== void 0) {
11796
+ for (const sessionId of evict) {
11797
+ if (merged.delete(sessionId)) evicted += 1;
11798
+ }
11799
+ }
11735
11800
  const tmp = `${path3}.tmp.${process.pid}.${Date.now()}.${nextTmpSeq()}`;
11736
11801
  try {
11737
11802
  await writeFile5(tmp, serializeTitleCache(merged), "utf8");
@@ -11747,6 +11812,7 @@ async function saveTitleCacheMerged(accountDir, updates) {
11747
11812
  }
11748
11813
  throw err;
11749
11814
  }
11815
+ return evicted;
11750
11816
  }
11751
11817
  function lastAiTitleIn(text, initial) {
11752
11818
  let aiTitle = initial;
@@ -11986,13 +12052,14 @@ function findSessionProjectDir(sessionId) {
11986
12052
  const jsonlPath = findExistingJsonlForSessionId(cfg, sessionId);
11987
12053
  return jsonlPath ? dirname5(jsonlPath) : null;
11988
12054
  }
11989
- function enumerateJsonls(projectsRoot) {
12055
+ function enumerateJsonlsWithSkips(projectsRoot) {
11990
12056
  const out = [];
12057
+ let skipped = 0;
11991
12058
  let slugs;
11992
12059
  try {
11993
12060
  slugs = readdirSync12(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
11994
12061
  } catch (err) {
11995
- if (err.code === "ENOENT") return out;
12062
+ if (err.code === "ENOENT") return { files: out, skipped };
11996
12063
  throw err;
11997
12064
  }
11998
12065
  for (const slug of slugs) {
@@ -12003,6 +12070,7 @@ function enumerateJsonls(projectsRoot) {
12003
12070
  } catch (err) {
12004
12071
  const code = err.code ?? "unknown";
12005
12072
  console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
12073
+ skipped += 1;
12006
12074
  continue;
12007
12075
  }
12008
12076
  for (const entry of entries2) {
@@ -12016,6 +12084,7 @@ function enumerateJsonls(projectsRoot) {
12016
12084
  } catch (err) {
12017
12085
  const code = err.code ?? "unknown";
12018
12086
  console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
12087
+ skipped += 1;
12019
12088
  continue;
12020
12089
  }
12021
12090
  for (const sub of subEntries) {
@@ -12031,6 +12100,7 @@ function enumerateJsonls(projectsRoot) {
12031
12100
  } catch (err) {
12032
12101
  const code = err.code ?? "unknown";
12033
12102
  console.error(`[admin-sessions-list] archive-skipped slug=${slug} code=${code}`);
12103
+ skipped += 1;
12034
12104
  continue;
12035
12105
  }
12036
12106
  for (const arc of archiveEntries) {
@@ -12041,7 +12111,10 @@ function enumerateJsonls(projectsRoot) {
12041
12111
  }
12042
12112
  }
12043
12113
  }
12044
- return out;
12114
+ return { files: out, skipped };
12115
+ }
12116
+ function enumerateJsonls(projectsRoot) {
12117
+ return enumerateJsonlsWithSkips(projectsRoot).files;
12045
12118
  }
12046
12119
  async function fetchLiveSessions() {
12047
12120
  const out = /* @__PURE__ */ new Map();
@@ -12182,7 +12255,6 @@ async function computeSessionList(scopeAccountId) {
12182
12255
  return { sessions: [], accountId: scopeAccountId };
12183
12256
  }
12184
12257
  const projectsRoot = join21(configDir2, "projects");
12185
- const jsonls = enumerateJsonls(projectsRoot);
12186
12258
  const liveSessions = await fetchLiveSessions();
12187
12259
  const accountDir = scopeAccountId ? resolve15(ACCOUNTS_DIR, scopeAccountId) : null;
12188
12260
  const userTitles = await loadUserTitlesAsync(accountDir);
@@ -12216,6 +12288,7 @@ async function computeSessionList(scopeAccountId) {
12216
12288
  const cacheLoad = await loadTitleCacheOutcome(titleCacheDir);
12217
12289
  const titleCache = cacheLoad.cache;
12218
12290
  const cacheUpdates = /* @__PURE__ */ new Map();
12291
+ const { files: jsonls, skipped: enumSkipped } = enumerateJsonlsWithSkips(projectsRoot);
12219
12292
  let enumeratedCount = 0;
12220
12293
  let scopedCount = 0;
12221
12294
  let titleCacheHits = 0;
@@ -12227,6 +12300,7 @@ async function computeSessionList(scopeAccountId) {
12227
12300
  let tailReadFails = 0;
12228
12301
  let tailBytes = 0;
12229
12302
  let cacheWriteFails = 0;
12303
+ let evicted = 0;
12230
12304
  const walkStartedAt = Date.now();
12231
12305
  for (const { path: path3, isSubagent, archived } of jsonls) {
12232
12306
  const lastSlash = path3.lastIndexOf("/");
@@ -12389,9 +12463,13 @@ async function computeSessionList(scopeAccountId) {
12389
12463
  console.error(`[admin-sessions-list] op=channel-name-unresolved sessionId=${m.sessionId.slice(0, 8)} channel=${m.channel} senderId= reason=no-senderId`);
12390
12464
  }
12391
12465
  rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
12392
- if (titleCacheDir && cacheUpdates.size > 0) {
12466
+ const evictIds = /* @__PURE__ */ new Set();
12467
+ if (enumSkipped === 0 && seenIds.size > 0) {
12468
+ for (const sessionId of titleCache.keys()) if (!seenIds.has(sessionId)) evictIds.add(sessionId);
12469
+ }
12470
+ if (titleCacheDir && (cacheUpdates.size > 0 || evictIds.size > 0)) {
12393
12471
  try {
12394
- await saveTitleCacheMerged(titleCacheDir, cacheUpdates);
12472
+ evicted = await saveTitleCacheMerged(titleCacheDir, cacheUpdates, evictIds);
12395
12473
  } catch (err) {
12396
12474
  cacheWriteFails += 1;
12397
12475
  console.error(
@@ -12401,7 +12479,7 @@ async function computeSessionList(scopeAccountId) {
12401
12479
  }
12402
12480
  const bytesMB = (titleBytes + tailBytes) / (1024 * 1024);
12403
12481
  console.log(
12404
- `[admin-sessions-list] op=list-walk enumerated=${enumeratedCount} scoped=${scopedCount} cacheLoad=${cacheLoad.state} cacheEntries=${titleCache.size} cacheDropped=${cacheLoad.dropped} titleCacheHits=${titleCacheHits} bodyScans=${bodyScans} titleReadFails=${titleReadFails} tailReads=${tailReads} tailModelMiss=${tailModelMiss} tailReadFails=${tailReadFails} titleBytesMB=${(titleBytes / (1024 * 1024)).toFixed(3)} bytesMB=${bytesMB.toFixed(3)} cacheWriteFails=${cacheWriteFails} ms=${Date.now() - walkStartedAt}`
12482
+ `[admin-sessions-list] op=list-walk enumerated=${enumeratedCount} scoped=${scopedCount} cacheLoad=${cacheLoad.state} cacheEntries=${titleCache.size} cacheDropped=${cacheLoad.dropped} titleCacheHits=${titleCacheHits} bodyScans=${bodyScans} titleReadFails=${titleReadFails} tailReads=${tailReads} tailModelMiss=${tailModelMiss} tailReadFails=${tailReadFails} titleBytesMB=${(titleBytes / (1024 * 1024)).toFixed(3)} bytesMB=${bytesMB.toFixed(3)} cacheWriteFails=${cacheWriteFails} evicted=${evicted} enumSkipped=${enumSkipped} ms=${Date.now() - walkStartedAt}`
12405
12483
  );
12406
12484
  console.log(
12407
12485
  `[admin-sessions-list] rows=${rows.length} live=${liveCount} subagents=${subagentCount} archived=${archivedCount} channelInList=whatsapp:${channelInList.whatsapp},telegram:${channelInList.telegram},webchat:${channelInList.webchat} channelNameCandidates=${channelNameCandidates} channelNamesResolved=${channelNamesResolved} (operator=${operatorResolvedCount} store=${storeResolvedCount}) unknownChannel=${unknownChannelCount} excludedPublicWebchat=${excludedPublicWebchatCount} titles user=${titleSourceCounts.user} ai=${titleSourceCounts.ai} first=${titleSourceCounts["first-message"]} prefix=${titleSourceCounts.prefix} personNames=${personNameCount} adminNames=${adminNameCount} accountId=${scopeAccountId ? scopeAccountId.slice(0, 8) : "unset"}`
@@ -19460,7 +19538,7 @@ async function restoreNode(params) {
19460
19538
  }
19461
19539
 
19462
19540
  // app/lib/file-delete-cascade.ts
19463
- var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
19541
+ var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
19464
19542
  function parseAttachmentPath(relPath) {
19465
19543
  const segments = relPath.split("/").filter(Boolean);
19466
19544
  if (segments.length !== 5) return null;
@@ -19468,7 +19546,7 @@ function parseAttachmentPath(relPath) {
19468
19546
  const accountId = segments[1];
19469
19547
  const attachmentId = segments[3];
19470
19548
  const filename = segments[4];
19471
- if (!UUID_RE3.test(accountId) || !UUID_RE3.test(attachmentId)) return null;
19549
+ if (!UUID_RE4.test(accountId) || !UUID_RE4.test(attachmentId)) return null;
19472
19550
  const dot = filename.lastIndexOf(".");
19473
19551
  if (dot === -1) return null;
19474
19552
  const stem = filename.slice(0, dot);
@@ -20076,7 +20154,7 @@ function classifyAccountRoot(schemaMd, rootEntries) {
20076
20154
 
20077
20155
  // server/routes/admin/files.ts
20078
20156
  var UPLOAD_TMP_DIR = ".uploads-tmp";
20079
- var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
20157
+ var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
20080
20158
  async function readMeta(absDir, baseName) {
20081
20159
  try {
20082
20160
  const raw = await readFile9(join38(absDir, `${baseName}.meta.json`), "utf8");
@@ -20098,7 +20176,7 @@ async function readAccountNames() {
20098
20176
  return map;
20099
20177
  }
20100
20178
  for (const name of names) {
20101
- if (!UUID_RE4.test(name)) continue;
20179
+ if (!UUID_RE5.test(name)) continue;
20102
20180
  const configPath2 = resolve27(accountsDir, name, "account.json");
20103
20181
  try {
20104
20182
  const raw = await readFile9(configPath2, "utf8");
@@ -20133,7 +20211,7 @@ async function servableFilesIn(dirAbs, uuid) {
20133
20211
  return out;
20134
20212
  }
20135
20213
  async function enrich(absolute, entry, accountNames) {
20136
- if (entry.kind === "directory" && UUID_RE4.test(entry.name)) {
20214
+ if (entry.kind === "directory" && UUID_RE5.test(entry.name)) {
20137
20215
  const dirAbs = join38(absolute, entry.name);
20138
20216
  const meta = await readMeta(dirAbs, entry.name);
20139
20217
  if (meta?.filename) {
@@ -20168,7 +20246,7 @@ async function enrich(absolute, entry, accountNames) {
20168
20246
  if (entry.kind === "file") {
20169
20247
  const dot = entry.name.lastIndexOf(".");
20170
20248
  const base = dot === -1 ? entry.name : entry.name.slice(0, dot);
20171
- if (UUID_RE4.test(base)) {
20249
+ if (UUID_RE5.test(base)) {
20172
20250
  const meta = await readMeta(absolute, base);
20173
20251
  if (meta?.filename) {
20174
20252
  entry.displayName = meta.filename;
@@ -20181,7 +20259,7 @@ async function enrich(absolute, entry, accountNames) {
20181
20259
  function buildDisplayPath(relPath, accountNames) {
20182
20260
  if (relPath === "." || relPath === "") return [];
20183
20261
  return relPath.split("/").filter(Boolean).map((seg) => {
20184
- const dn = UUID_RE4.test(seg) ? accountNames.get(seg) : void 0;
20262
+ const dn = UUID_RE5.test(seg) ? accountNames.get(seg) : void 0;
20185
20263
  return dn ? { name: seg, displayName: dn } : { name: seg };
20186
20264
  });
20187
20265
  }
@@ -20193,13 +20271,13 @@ function parseGroupPath(raw, sessionAccountId) {
20193
20271
  }
20194
20272
  const segs = trimmed.split("/").filter(Boolean);
20195
20273
  if (segs.length !== 3) return null;
20196
- if (segs[0] !== "accounts" || !UUID_RE4.test(segs[1])) return null;
20274
+ if (segs[0] !== "accounts" || !UUID_RE5.test(segs[1])) return null;
20197
20275
  if (segs[2] !== "@home" && segs[2] !== "@system") return null;
20198
20276
  return { view: segs[2].slice(1), accountRel: `accounts/${segs[1]}` };
20199
20277
  }
20200
20278
  function isAccountRoot(relPath) {
20201
20279
  const segs = relPath.split("/").filter(Boolean);
20202
- return segs.length === 2 && segs[0] === "accounts" && UUID_RE4.test(segs[1]);
20280
+ return segs.length === 2 && segs[0] === "accounts" && UUID_RE5.test(segs[1]);
20203
20281
  }
20204
20282
  function sortDirEntries(entries2) {
20205
20283
  entries2.sort((a, b) => {
@@ -20247,11 +20325,11 @@ function isProtectedFromRename(relPath) {
20247
20325
  if (segments.length === 3 && segments[0] === "accounts" && segments[2] === "uploads") {
20248
20326
  return true;
20249
20327
  }
20250
- if (segments.length === 4 && segments[0] === "accounts" && segments[2] === "uploads" && UUID_RE4.test(segments[3])) {
20328
+ if (segments.length === 4 && segments[0] === "accounts" && segments[2] === "uploads" && UUID_RE5.test(segments[3])) {
20251
20329
  return true;
20252
20330
  }
20253
20331
  if (parseAttachmentPath(relPath) !== null) return true;
20254
- if (UUID_RE4.test(base.replace(/\.meta\.json$/, "")) && base.endsWith(".meta.json")) {
20332
+ if (UUID_RE5.test(base.replace(/\.meta\.json$/, "")) && base.endsWith(".meta.json")) {
20255
20333
  return true;
20256
20334
  }
20257
20335
  return false;
@@ -20327,10 +20405,10 @@ app23.get("/", requireAdminSession, async (c) => {
20327
20405
  const isAccountParent = segs.length === 1 && segs[0] === "accounts";
20328
20406
  const entries2 = [];
20329
20407
  for (const name of names) {
20330
- if (UUID_RE4.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
20408
+ if (UUID_RE5.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
20331
20409
  continue;
20332
20410
  }
20333
- if (isAccountParent && UUID_RE4.test(name) && name !== accountId) {
20411
+ if (isAccountParent && UUID_RE5.test(name) && name !== accountId) {
20334
20412
  continue;
20335
20413
  }
20336
20414
  const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
@@ -21050,8 +21128,8 @@ app23.delete("/", requireAdminSession, async (c) => {
21050
21128
  const dot = base.lastIndexOf(".");
21051
21129
  const stem = dot === -1 ? base : base.slice(0, dot);
21052
21130
  const containerDir = dirname13(absolute);
21053
- const sidecarPath = UUID_RE4.test(stem) && base !== `${stem}.meta.json` ? join38(containerDir, `${stem}.meta.json`) : null;
21054
- const isAttachmentContainer = UUID_RE4.test(stem) && basename11(containerDir) === stem;
21131
+ const sidecarPath = UUID_RE5.test(stem) && base !== `${stem}.meta.json` ? join38(containerDir, `${stem}.meta.json`) : null;
21132
+ const isAttachmentContainer = UUID_RE5.test(stem) && basename11(containerDir) === stem;
21055
21133
  await unlink4(absolute);
21056
21134
  if (sidecarPath) {
21057
21135
  try {
@@ -26508,7 +26586,7 @@ var admin_users_list_default = app56;
26508
26586
  import { readdirSync as readdirSync27 } from "fs";
26509
26587
  var app57 = new Hono();
26510
26588
  var TAG47 = "[activity]";
26511
- function resolveHouseAccountId(accounts) {
26589
+ function resolveHouseAccountId2(accounts) {
26512
26590
  const houses = accounts.filter((a) => a.config.role === "house");
26513
26591
  if (houses.length === 1) return { accountId: houses[0].accountId, reason: "house" };
26514
26592
  if (houses.length > 1) return { accountId: null, reason: "multiple-houses" };
@@ -26533,7 +26611,7 @@ app57.get("/", requireAdminSession, async (c) => {
26533
26611
  const cacheKey = c.var.cacheKey;
26534
26612
  const caller2 = getAccountIdForSession(cacheKey) ?? null;
26535
26613
  const valid = listValidAccounts();
26536
- const house = resolveHouseAccountId(valid);
26614
+ const house = resolveHouseAccountId2(valid);
26537
26615
  const isHouse = caller2 !== null && house.accountId !== null && caller2 === house.accountId;
26538
26616
  console.log(
26539
26617
  `${TAG47} op=request req=${req} caller=${short(caller2)} house=${isHouse} houseVia=${house.reason}`
@@ -27652,7 +27730,7 @@ var visitor_event_default = app65;
27652
27730
  // server/routes/session.ts
27653
27731
  import { resolve as resolve37 } from "path";
27654
27732
  import { existsSync as existsSync43, writeFileSync as writeFileSync16, mkdirSync as mkdirSync10 } from "fs";
27655
- var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
27733
+ var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
27656
27734
  function writeBrandingCache(accountId, agentSlug, branding) {
27657
27735
  try {
27658
27736
  const cacheDir = resolve37(MAXY_DIR, "branding-cache", accountId);
@@ -27667,7 +27745,7 @@ function parseVisitorCookie2(cookieHeader) {
27667
27745
  const match = cookieHeader.match(/(?:^|;\s*)maxy_visitor=([^;]*)/);
27668
27746
  if (!match) return null;
27669
27747
  const value = decodeURIComponent(match[1]).trim();
27670
- return UUID_RE5.test(value) ? value : null;
27748
+ return UUID_RE6.test(value) ? value : null;
27671
27749
  }
27672
27750
  function parseAccessSessionId2(cookieHeader) {
27673
27751
  if (!cookieHeader) return null;
@@ -27765,7 +27843,7 @@ app66.post("/", async (c) => {
27765
27843
  );
27766
27844
  }
27767
27845
  }
27768
- if (body.session_key && typeof body.session_key === "string" && UUID_RE5.test(body.session_key)) {
27846
+ if (body.session_key && typeof body.session_key === "string" && UUID_RE6.test(body.session_key)) {
27769
27847
  if (visitorId) {
27770
27848
  const recent = await findRecentConversation(visitorId, accountId, agentSlug).catch(() => null);
27771
27849
  if (recent) {
@@ -32126,6 +32204,7 @@ var waGateway = new WaGateway({
32126
32204
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
32127
32205
  },
32128
32206
  ensureChannelSession: async ({ accountId, effectiveAccountId, senderId, role, personId, gatewayUrl, serverPath, passive, text, msgId, ownerSelfPhone, replyContext }) => {
32207
+ warnNonUuidAccount("channel-spawn", effectiveAccountId);
32129
32208
  if (passive) {
32130
32209
  const phoneHash = createHash8("sha256").update(senderId).digest("hex").slice(0, 12);
32131
32210
  const prompt = (text ?? "").trim();
@@ -32174,7 +32253,7 @@ var waGateway = new WaGateway({
32174
32253
  return;
32175
32254
  }
32176
32255
  if (role === "admin") {
32177
- const managesAccount = effectiveAccountId !== accountId ? effectiveAccountId : "none";
32256
+ const managesAccount = managesAccountFor(effectiveAccountId, resolveReadStoreKey(accountId));
32178
32257
  console.error(`[whatsapp-native] op=account-manager-route senderId=${senderId} managesAccount=${managesAccount} effectiveAccount=${effectiveAccountId} source=gate`);
32179
32258
  }
32180
32259
  const req = buildWaSpawnRequest({
@@ -1 +0,0 @@
1
- import{B as e,W as t}from"./useSubAccountSwitcher-CJKjEPNN.js";import"./useVoiceRecorder-ChnBrzbZ.js";import"./AdminShell-BMPEWNZk.js";import{n}from"./page-DC11gesX.js";import"./useCopyFeedback-BdUwyNpa.js";var r=t(),i=e();(0,r.createRoot)(document.getElementById(`root`)).render((0,i.jsx)(n,{}));
@@ -1 +0,0 @@
1
- import{P as e}from"./useSubAccountSwitcher-CJKjEPNN.js";var t=e(`chevron-left`,[[`path`,{d:`m15 18-6-6 6-6`,key:`1wnfg3`}]]);export{t};
@@ -1 +0,0 @@
1
- import{P as e}from"./useSubAccountSwitcher-CJKjEPNN.js";var t=e(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]);export{t};
@@ -1 +0,0 @@
1
- import{P as e}from"./useSubAccountSwitcher-CJKjEPNN.js";var t=e(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6l4 2`,key:`mmk7yg`}]]);export{t};
@@ -1 +0,0 @@
1
- import{B as e,W as t}from"./useSubAccountSwitcher-CJKjEPNN.js";import"./useVoiceRecorder-ChnBrzbZ.js";import{t as n}from"./page-BWFHRIAH.js";import"./graph-labels-BZgd0L6n.js";var r=t(),i=e();(0,r.createRoot)(document.getElementById(`root`)).render((0,i.jsx)(n,{}));