@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.
- package/package.json +1 -1
- package/payload/platform/docs/superpowers/plans/2026-07-27-task-2028-declared-file-write-deny.md +303 -0
- package/payload/platform/docs/superpowers/plans/2026-07-27-task-2052-account-machinery-write-fence.md +250 -0
- package/payload/platform/docs/superpowers/specs/2026-07-27-task-2028-declared-file-write-deny-design.md +127 -0
- package/payload/platform/docs/superpowers/specs/2026-07-27-task-2052-account-machinery-write-fence-design.md +150 -0
- package/payload/platform/lib/account-schema-regions/dist/index.d.ts +5 -0
- package/payload/platform/lib/account-schema-regions/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/account-schema-regions/dist/index.js +5 -0
- package/payload/platform/lib/account-schema-regions/dist/index.js.map +1 -1
- package/payload/platform/lib/account-schema-regions/src/index.ts +5 -0
- package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard-bash.test.sh +14 -0
- package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard.test.sh +79 -0
- package/payload/platform/plugins/admin/hooks/fs-schema-guard-bash-post.sh +19 -0
- package/payload/platform/plugins/admin/hooks/fs-schema-guard.sh +64 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +12 -0
- package/payload/platform/plugins/cloudflare/PLUGIN.md +1 -1
- package/payload/platform/plugins/cloudflare/bin/schema-exposed-dirs.mjs +1 -1
- package/payload/platform/plugins/scheduling/PLUGIN.md +1 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +1 -1
- package/payload/platform/scripts/__tests__/account-schema-owned-dirs.test.sh +26 -0
- package/payload/platform/scripts/lib/account-schema-owned-dirs.py +40 -4
- package/payload/platform/scripts/logs-read.sh +47 -24
- package/payload/platform/scripts/logs-read.test.sh +73 -31
- package/payload/platform/scripts/provision-worktree.sh +80 -0
- package/payload/platform/templates/account-schema/SCHEMA.md +17 -0
- package/payload/server/{chunk-2WAXM5N2.js → chunk-S6HYTIU3.js} +2 -3
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/{AdminLoginScreens-bksN0XPe.js → AdminLoginScreens-Cs1jSnOF.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-Cs1jSnOF.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-Cs1jSnOF.js.gz +0 -0
- package/payload/server/public/assets/{AdminShell-BMPEWNZk.js → AdminShell-DkrURZnF.js} +1 -1
- package/payload/server/public/assets/AdminShell-DkrURZnF.js.br +0 -0
- package/payload/server/public/assets/AdminShell-DkrURZnF.js.gz +0 -0
- package/payload/server/public/assets/{activity-ByWYF5dC.js → activity-BgZISMuE.js} +1 -1
- package/payload/server/public/assets/activity-BgZISMuE.js.br +0 -0
- package/payload/server/public/assets/activity-BgZISMuE.js.gz +0 -0
- package/payload/server/public/assets/{admin-6QN-k3zQ.js → admin-DjFysc3-.js} +1 -1
- package/payload/server/public/assets/admin-DjFysc3-.js.br +0 -0
- package/payload/server/public/assets/admin-DjFysc3-.js.gz +0 -0
- package/payload/server/public/assets/{agents-C0rTfrYd.js → agents-Bx-MSZW6.js} +1 -1
- package/payload/server/public/assets/agents-Bx-MSZW6.js.br +0 -0
- package/payload/server/public/assets/agents-Bx-MSZW6.js.gz +0 -0
- package/payload/server/public/assets/{browser-4tTaem8N.js → browser-1I7syhHu.js} +1 -1
- package/payload/server/public/assets/browser-1I7syhHu.js.br +0 -0
- package/payload/server/public/assets/browser-1I7syhHu.js.gz +0 -0
- package/payload/server/public/assets/{calendar-BEjnkKG1.js → calendar-D_04JIo1.js} +1 -1
- package/payload/server/public/assets/calendar-D_04JIo1.js.br +0 -0
- package/payload/server/public/assets/calendar-D_04JIo1.js.gz +0 -0
- package/payload/server/public/assets/chat-BFH3FM5a.js +1 -0
- package/payload/server/public/assets/chat-BFH3FM5a.js.br +0 -0
- package/payload/server/public/assets/chat-BFH3FM5a.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-Ux9-qLkk.js +1 -0
- package/payload/server/public/assets/chevron-right-BwIuCfyG.js +1 -0
- package/payload/server/public/assets/chevron-right-BwIuCfyG.js.br +0 -0
- package/payload/server/public/assets/clock-DhJdZRhC.js +1 -0
- package/payload/server/public/assets/clock-DhJdZRhC.js.br +0 -0
- package/payload/server/public/assets/data-ChY_uSIk.js +1 -0
- package/payload/server/public/assets/data-ChY_uSIk.js.br +0 -0
- package/payload/server/public/assets/data-ChY_uSIk.js.gz +0 -0
- package/payload/server/public/assets/{file-text-DMKw3nIk.js → file-text-DkvKqHMx.js} +1 -1
- package/payload/server/public/assets/file-text-DkvKqHMx.js.br +0 -0
- package/payload/server/public/assets/file-text-DkvKqHMx.js.gz +0 -0
- package/payload/server/public/assets/{graph-C3vW8lvw.js → graph-CCZhrwZX.js} +1 -1
- package/payload/server/public/assets/graph-CCZhrwZX.js.br +0 -0
- package/payload/server/public/assets/graph-CCZhrwZX.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-BZgd0L6n.js → graph-labels-BJ7puQkX.js} +1 -1
- package/payload/server/public/assets/graph-labels-BJ7puQkX.js.br +0 -0
- package/payload/server/public/assets/graph-labels-BJ7puQkX.js.gz +0 -0
- package/payload/server/public/assets/{maximize-2-la3IBA3M.js → maximize-2-Xdj804U1.js} +1 -1
- package/payload/server/public/assets/maximize-2-Xdj804U1.js.br +0 -0
- package/payload/server/public/assets/maximize-2-Xdj804U1.js.gz +0 -0
- package/payload/server/public/assets/{operator-D9NgVL9_.js → operator-BkfNpBs7.js} +1 -1
- package/payload/server/public/assets/operator-BkfNpBs7.js.br +0 -0
- package/payload/server/public/assets/operator-BkfNpBs7.js.gz +0 -0
- package/payload/server/public/assets/{page-DC11gesX.js → page-BoYc9c4a.js} +1 -1
- package/payload/server/public/assets/page-BoYc9c4a.js.br +0 -0
- package/payload/server/public/assets/page-BoYc9c4a.js.gz +0 -0
- package/payload/server/public/assets/{page-BWFHRIAH.js → page-D5n8ShE7.js} +1 -1
- package/payload/server/public/assets/page-D5n8ShE7.js.br +0 -0
- package/payload/server/public/assets/page-D5n8ShE7.js.gz +0 -0
- package/payload/server/public/assets/{public-DQbbLHQN.js → public-CX5XSrxD.js} +1 -1
- package/payload/server/public/assets/public-CX5XSrxD.js.br +0 -0
- package/payload/server/public/assets/public-CX5XSrxD.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-OQD5si8N.js → rotate-ccw-dh_OhL23.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-dh_OhL23.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-dh_OhL23.js.gz +0 -0
- package/payload/server/public/assets/{routines-asrBGZUR.js → routines-bb7dxcrr.js} +1 -1
- package/payload/server/public/assets/routines-bb7dxcrr.js.br +0 -0
- package/payload/server/public/assets/routines-bb7dxcrr.js.gz +0 -0
- package/payload/server/public/assets/{skills-D4ECwoxa.js → skills-TeMwxXmJ.js} +1 -1
- package/payload/server/public/assets/skills-TeMwxXmJ.js.br +0 -0
- package/payload/server/public/assets/skills-TeMwxXmJ.js.gz +0 -0
- package/payload/server/public/assets/{tasks-U3QdbUsO.js → tasks-BqBBJlkg.js} +1 -1
- package/payload/server/public/assets/tasks-BqBBJlkg.js.br +0 -0
- package/payload/server/public/assets/tasks-BqBBJlkg.js.gz +0 -0
- package/payload/server/public/assets/{time-entry-format-BgdTKgYr.js → time-entry-format-Cy_T-wiD.js} +1 -1
- package/payload/server/public/assets/time-entry-format-Cy_T-wiD.js.br +3 -0
- package/payload/server/public/assets/time-entry-format-Cy_T-wiD.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-Ck_3VhT9.js → triangle-alert-D-bSbPnX.js} +1 -1
- package/payload/server/public/assets/triangle-alert-D-bSbPnX.js.br +1 -0
- package/payload/server/public/assets/triangle-alert-D-bSbPnX.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-BdUwyNpa.js → useCopyFeedback-L7L55nFl.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-L7L55nFl.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-L7L55nFl.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css +1 -0
- package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css.gz +0 -0
- package/payload/server/public/assets/{useVoiceRecorder-ChnBrzbZ.js → useVoiceRecorder-MuZ7lpet.js} +1 -1
- package/payload/server/public/assets/useVoiceRecorder-MuZ7lpet.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-MuZ7lpet.js.gz +0 -0
- package/payload/server/public/assets/{wrench-Cpee3C3J.js → wrench-DUG1SZQB.js} +1 -1
- package/payload/server/public/assets/wrench-DUG1SZQB.js.br +0 -0
- package/payload/server/public/assets/wrench-DUG1SZQB.js.gz +0 -0
- package/payload/server/public/brand-defaults.css +2 -0
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +7 -7
- package/payload/server/public/chat.html +13 -13
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +13 -13
- package/payload/server/public/routines.html +6 -6
- package/payload/server/public/skills.html +5 -5
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +126 -47
- package/payload/server/public/assets/AdminLoginScreens-bksN0XPe.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-bksN0XPe.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-BMPEWNZk.js.br +0 -0
- package/payload/server/public/assets/AdminShell-BMPEWNZk.js.gz +0 -0
- package/payload/server/public/assets/activity-ByWYF5dC.js.br +0 -0
- package/payload/server/public/assets/activity-ByWYF5dC.js.gz +0 -0
- package/payload/server/public/assets/admin-6QN-k3zQ.js.br +0 -0
- package/payload/server/public/assets/admin-6QN-k3zQ.js.gz +0 -0
- package/payload/server/public/assets/agents-C0rTfrYd.js.br +0 -0
- package/payload/server/public/assets/agents-C0rTfrYd.js.gz +0 -0
- package/payload/server/public/assets/browser-4tTaem8N.js.br +0 -0
- package/payload/server/public/assets/browser-4tTaem8N.js.gz +0 -0
- package/payload/server/public/assets/calendar-BEjnkKG1.js.br +0 -0
- package/payload/server/public/assets/calendar-BEjnkKG1.js.gz +0 -0
- package/payload/server/public/assets/chat-DBgzjDIE.js +0 -1
- package/payload/server/public/assets/chat-DBgzjDIE.js.br +0 -0
- package/payload/server/public/assets/chat-DBgzjDIE.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-DqYv3oFh.js +0 -1
- package/payload/server/public/assets/chevron-right-CQfPGsFb.js +0 -1
- package/payload/server/public/assets/chevron-right-CQfPGsFb.js.br +0 -0
- package/payload/server/public/assets/clock-Dn6FHB51.js +0 -1
- package/payload/server/public/assets/clock-Dn6FHB51.js.br +0 -0
- package/payload/server/public/assets/clock-Dn6FHB51.js.gz +0 -0
- package/payload/server/public/assets/data-D_e6Vdfd.js +0 -1
- package/payload/server/public/assets/data-D_e6Vdfd.js.br +0 -0
- package/payload/server/public/assets/data-D_e6Vdfd.js.gz +0 -0
- package/payload/server/public/assets/file-text-DMKw3nIk.js.br +0 -0
- package/payload/server/public/assets/file-text-DMKw3nIk.js.gz +0 -0
- package/payload/server/public/assets/graph-C3vW8lvw.js.br +0 -0
- package/payload/server/public/assets/graph-C3vW8lvw.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-BZgd0L6n.js.br +0 -0
- package/payload/server/public/assets/graph-labels-BZgd0L6n.js.gz +0 -0
- package/payload/server/public/assets/maximize-2-la3IBA3M.js.br +0 -0
- package/payload/server/public/assets/maximize-2-la3IBA3M.js.gz +0 -0
- package/payload/server/public/assets/operator-D9NgVL9_.js.br +0 -0
- package/payload/server/public/assets/operator-D9NgVL9_.js.gz +0 -0
- package/payload/server/public/assets/page-BWFHRIAH.js.br +0 -0
- package/payload/server/public/assets/page-BWFHRIAH.js.gz +0 -0
- package/payload/server/public/assets/page-DC11gesX.js.br +0 -0
- package/payload/server/public/assets/page-DC11gesX.js.gz +0 -0
- package/payload/server/public/assets/public-DQbbLHQN.js.br +0 -0
- package/payload/server/public/assets/public-DQbbLHQN.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-OQD5si8N.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-OQD5si8N.js.gz +0 -0
- package/payload/server/public/assets/routines-asrBGZUR.js.br +0 -0
- package/payload/server/public/assets/routines-asrBGZUR.js.gz +0 -0
- package/payload/server/public/assets/skills-D4ECwoxa.js.br +0 -0
- package/payload/server/public/assets/skills-D4ECwoxa.js.gz +0 -0
- package/payload/server/public/assets/tasks-U3QdbUsO.js.br +0 -0
- package/payload/server/public/assets/tasks-U3QdbUsO.js.gz +0 -0
- package/payload/server/public/assets/time-entry-format-BgdTKgYr.js.br +0 -0
- package/payload/server/public/assets/time-entry-format-BgdTKgYr.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-Ck_3VhT9.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-Ck_3VhT9.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-BdUwyNpa.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-BdUwyNpa.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-DOWQXDT8.css +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-DOWQXDT8.css.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-DOWQXDT8.css.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-ChnBrzbZ.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-ChnBrzbZ.js.gz +0 -0
- package/payload/server/public/assets/wrench-Cpee3C3J.js.br +0 -2
- package/payload/server/public/assets/wrench-Cpee3C3J.js.gz +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-CJKjEPNN.js → useSubAccountSwitcher-DH0P6QMV.js} +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-CJKjEPNN.js.br → useSubAccountSwitcher-DH0P6QMV.js.br} +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-CJKjEPNN.js.gz → useSubAccountSwitcher-DH0P6QMV.js.gz} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -118,7 +118,7 @@ import {
|
|
|
118
118
|
vncLog,
|
|
119
119
|
walkPremiumBundles,
|
|
120
120
|
writeAdminUserAndPerson
|
|
121
|
-
} from "./chunk-
|
|
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
|
-
|
|
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
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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 (
|
|
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
|
-
|
|
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
|
|
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 (!
|
|
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
|
|
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
|
-
|
|
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
|
|
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 (!
|
|
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
|
|
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 (!
|
|
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" &&
|
|
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 (
|
|
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 =
|
|
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" || !
|
|
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" &&
|
|
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" &&
|
|
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 (
|
|
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 (
|
|
20408
|
+
if (UUID_RE5.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
|
|
20331
20409
|
continue;
|
|
20332
20410
|
}
|
|
20333
|
-
if (isAccountParent &&
|
|
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 =
|
|
21054
|
-
const isAttachmentContainer =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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" &&
|
|
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
|
|
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({
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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,{}));
|
|
Binary file
|
|
Binary file
|
|
@@ -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};
|
|
Binary file
|
|
@@ -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};
|
|
Binary file
|
|
Binary file
|
|
@@ -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,{}));
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|