@rubytech/create-sitedesk-code 0.1.512 → 0.1.513

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 (24) 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/specs/2026-07-27-task-2028-declared-file-write-deny-design.md +126 -0
  4. package/payload/platform/lib/account-schema-regions/dist/index.d.ts +5 -0
  5. package/payload/platform/lib/account-schema-regions/dist/index.d.ts.map +1 -1
  6. package/payload/platform/lib/account-schema-regions/dist/index.js +5 -0
  7. package/payload/platform/lib/account-schema-regions/dist/index.js.map +1 -1
  8. package/payload/platform/lib/account-schema-regions/src/index.ts +5 -0
  9. package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard-bash.test.sh +14 -0
  10. package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard.test.sh +38 -0
  11. package/payload/platform/plugins/admin/hooks/fs-schema-guard-bash-post.sh +11 -0
  12. package/payload/platform/plugins/admin/hooks/fs-schema-guard.sh +25 -1
  13. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
  14. package/payload/platform/plugins/cloudflare/PLUGIN.md +1 -1
  15. package/payload/platform/plugins/cloudflare/bin/schema-exposed-dirs.mjs +1 -1
  16. package/payload/platform/plugins/scheduling/PLUGIN.md +1 -1
  17. package/payload/platform/scripts/__tests__/account-schema-owned-dirs.test.sh +26 -0
  18. package/payload/platform/scripts/lib/account-schema-owned-dirs.py +40 -4
  19. package/payload/platform/scripts/logs-read.sh +47 -24
  20. package/payload/platform/scripts/logs-read.test.sh +73 -31
  21. package/payload/platform/scripts/provision-worktree.sh +80 -0
  22. package/payload/server/{chunk-2WAXM5N2.js → chunk-S6HYTIU3.js} +2 -3
  23. package/payload/server/maxy-edge.js +1 -1
  24. package/payload/server/server.js +89 -41
@@ -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,
@@ -5105,6 +5105,18 @@ function resolvePlatformAccountId(accountsDir = ACCOUNTS_DIR) {
5105
5105
  return routed ?? houseId;
5106
5106
  }
5107
5107
 
5108
+ // app/lib/whatsapp/account-id-shape.ts
5109
+ var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
5110
+ function isUuidAccountId(id) {
5111
+ return UUID_RE2.test(id);
5112
+ }
5113
+ function warnNonUuidAccount(caller2, accountId) {
5114
+ if (isUuidAccountId(accountId)) return;
5115
+ console.error(
5116
+ `[whatsapp-account-scope] op=non-uuid-account caller=${caller2} accountId=${accountId}`
5117
+ );
5118
+ }
5119
+
5108
5120
  // app/lib/managed-service.ts
5109
5121
  import { join as join7 } from "path";
5110
5122
  import { readFileSync as readFileSync9 } from "fs";
@@ -6221,8 +6233,9 @@ function buildSelfChatDispatch(input) {
6221
6233
  isGroup: false
6222
6234
  }),
6223
6235
  media: [],
6224
- // Self-chat is the owner: the session scopes to the house account (Task 1383).
6225
- effectiveAccountId: input.accountId,
6236
+ // Self-chat is the owner: the session scopes to the house account (Task 1383),
6237
+ // named by its platform UUID (Task 1850).
6238
+ effectiveAccountId: input.platformAccountId,
6226
6239
  // Task 1575 — self-chat is unambiguously the owner, so attribute the spawn
6227
6240
  // to the owner userId even when the owner phone is unbound in users.json.
6228
6241
  ownerSelfPhone: true
@@ -6353,20 +6366,26 @@ function resolveReadStoreKey(accountId) {
6353
6366
  }
6354
6367
  function resolveInboundPersistAccount(args) {
6355
6368
  const result = args.accessResult;
6356
- if (result?.allowed && result.reason === "account-manager" && result.effectiveAccountId) {
6357
- return result.effectiveAccountId;
6358
- }
6359
- return args.connPlatformAccountId;
6369
+ const account = result?.allowed && result.reason === "account-manager" && result.effectiveAccountId ? result.effectiveAccountId : args.connPlatformAccountId;
6370
+ warnNonUuidAccount("inbound-persist", account);
6371
+ return account;
6360
6372
  }
6361
6373
  function resolveConversationPersistAccount(sendAccountId, counterpartyPhone) {
6362
6374
  const conn = findConnectionByKey(Array.from(connections2.values()), sendAccountId);
6363
- if (!conn) return sendAccountId;
6375
+ if (!conn) {
6376
+ warnNonUuidAccount("reply-append-no-connection", sendAccountId);
6377
+ return sendAccountId;
6378
+ }
6364
6379
  const access = checkDmAccess({
6365
6380
  senderPhone: counterpartyPhone,
6366
6381
  selfPhone: conn.selfPhone ?? "",
6367
6382
  config: whatsAppConfig,
6383
+ // The per-number sub-config is keyed by the credential DIRNAME.
6368
6384
  accountConfig: whatsAppConfig.accounts?.[conn.accountId],
6369
- accountId: conn.accountId,
6385
+ // Task 1850 — the account SCOPE is the platform UUID. The gate assigns this
6386
+ // to `effectiveAccountId` for every non-manager admit, and that value reaches
6387
+ // the graph and the spawn; the dirname is a credential path, not an account.
6388
+ accountId: conn.platformAccountId,
6370
6389
  isValidAccount: (id) => isValidAccountId(id)
6371
6390
  });
6372
6391
  return resolveInboundPersistAccount({
@@ -6700,8 +6719,11 @@ function monitorInbound(conn) {
6700
6719
  senderPhone,
6701
6720
  selfPhone: conn.selfPhone ?? "",
6702
6721
  config: whatsAppConfig,
6722
+ // Keyed by the credential DIRNAME — a per-number sub-config.
6703
6723
  accountConfig: whatsAppConfig.accounts?.[conn.accountId],
6704
- accountId: conn.accountId,
6724
+ // Task 1850 — the account SCOPE is the platform UUID, never the
6725
+ // dirname. See resolveConversationPersistAccount.
6726
+ accountId: conn.platformAccountId,
6705
6727
  isValidAccount: (id) => isValidAccountId(id)
6706
6728
  });
6707
6729
  const persistAccountId = resolveInboundPersistAccount({
@@ -6894,6 +6916,7 @@ function monitorInbound(conn) {
6894
6916
  };
6895
6917
  dispatchInboundPayload(conn, buildSelfChatDispatch({
6896
6918
  accountId: conn.accountId,
6919
+ platformAccountId: conn.platformAccountId,
6897
6920
  selfPhone: conn.selfPhone,
6898
6921
  remoteJid,
6899
6922
  text: decision.text,
@@ -7043,7 +7066,7 @@ async function handleInboundMessage(conn, msg) {
7043
7066
  selfPhone,
7044
7067
  config: whatsAppConfig,
7045
7068
  accountConfig: whatsAppConfig.accounts?.[conn.accountId],
7046
- accountId: conn.accountId,
7069
+ accountId: conn.platformAccountId,
7047
7070
  isValidAccount: (id) => isValidAccountId(id),
7048
7071
  resolvePersonByPhone
7049
7072
  });
@@ -8152,6 +8175,11 @@ function createScheduleInjectRoutes(deps) {
8152
8175
  // server/index.ts
8153
8176
  var import_dist9 = __toESM(require_dist(), 1);
8154
8177
 
8178
+ // app/lib/whatsapp/gateway/manages-account.ts
8179
+ function managesAccountFor(effectiveAccountId, connPlatformAccountId) {
8180
+ return effectiveAccountId === connPlatformAccountId ? "none" : effectiveAccountId;
8181
+ }
8182
+
8155
8183
  // app/lib/whatsapp/socket-resolution-error.ts
8156
8184
  function formatPresentKeys(presentKeys) {
8157
8185
  return presentKeys.join(",") || "none";
@@ -11569,13 +11597,13 @@ async function runPortalIndexPush(root) {
11569
11597
  import { existsSync as existsSync12, readdirSync as readdirSync9, statSync as statSync5 } from "fs";
11570
11598
  import { join as join17 } from "path";
11571
11599
  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;
11600
+ 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
11601
  function runGooglePendingAudit(accountsDir, nowMs, emit, readMtimeMs = (path3) => statSync5(path3).mtimeMs) {
11574
11602
  let scanned = 0;
11575
11603
  let stranded = 0;
11576
11604
  if (existsSync12(accountsDir)) {
11577
11605
  for (const accountId of readdirSync9(accountsDir)) {
11578
- if (!UUID_RE2.test(accountId)) continue;
11606
+ if (!UUID_RE3.test(accountId)) continue;
11579
11607
  const pendingPath2 = join17(accountsDir, accountId, "secrets", "google", "pending-oauth.enc");
11580
11608
  try {
11581
11609
  if (!existsSync12(pendingPath2)) continue;
@@ -11721,8 +11749,8 @@ async function loadTitleCacheOutcome(accountDir) {
11721
11749
  async function loadTitleCache(accountDir) {
11722
11750
  return (await loadTitleCacheOutcome(accountDir)).cache;
11723
11751
  }
11724
- async function saveTitleCacheMerged(accountDir, updates) {
11725
- if (updates.size === 0) return;
11752
+ async function saveTitleCacheMerged(accountDir, updates, evict) {
11753
+ if (updates.size === 0 && (evict === void 0 || evict.size === 0)) return 0;
11726
11754
  const path3 = titleCachePath(accountDir);
11727
11755
  let merged;
11728
11756
  try {
@@ -11732,6 +11760,12 @@ async function saveTitleCacheMerged(accountDir, updates) {
11732
11760
  merged = /* @__PURE__ */ new Map();
11733
11761
  }
11734
11762
  for (const [sessionId, entry] of updates) merged.set(sessionId, entry);
11763
+ let evicted = 0;
11764
+ if (evict !== void 0) {
11765
+ for (const sessionId of evict) {
11766
+ if (merged.delete(sessionId)) evicted += 1;
11767
+ }
11768
+ }
11735
11769
  const tmp = `${path3}.tmp.${process.pid}.${Date.now()}.${nextTmpSeq()}`;
11736
11770
  try {
11737
11771
  await writeFile5(tmp, serializeTitleCache(merged), "utf8");
@@ -11747,6 +11781,7 @@ async function saveTitleCacheMerged(accountDir, updates) {
11747
11781
  }
11748
11782
  throw err;
11749
11783
  }
11784
+ return evicted;
11750
11785
  }
11751
11786
  function lastAiTitleIn(text, initial) {
11752
11787
  let aiTitle = initial;
@@ -11986,13 +12021,14 @@ function findSessionProjectDir(sessionId) {
11986
12021
  const jsonlPath = findExistingJsonlForSessionId(cfg, sessionId);
11987
12022
  return jsonlPath ? dirname5(jsonlPath) : null;
11988
12023
  }
11989
- function enumerateJsonls(projectsRoot) {
12024
+ function enumerateJsonlsWithSkips(projectsRoot) {
11990
12025
  const out = [];
12026
+ let skipped = 0;
11991
12027
  let slugs;
11992
12028
  try {
11993
12029
  slugs = readdirSync12(projectsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
11994
12030
  } catch (err) {
11995
- if (err.code === "ENOENT") return out;
12031
+ if (err.code === "ENOENT") return { files: out, skipped };
11996
12032
  throw err;
11997
12033
  }
11998
12034
  for (const slug of slugs) {
@@ -12003,6 +12039,7 @@ function enumerateJsonls(projectsRoot) {
12003
12039
  } catch (err) {
12004
12040
  const code = err.code ?? "unknown";
12005
12041
  console.error(`[admin-sessions-list] slug-skipped slug=${slug} code=${code}`);
12042
+ skipped += 1;
12006
12043
  continue;
12007
12044
  }
12008
12045
  for (const entry of entries2) {
@@ -12016,6 +12053,7 @@ function enumerateJsonls(projectsRoot) {
12016
12053
  } catch (err) {
12017
12054
  const code = err.code ?? "unknown";
12018
12055
  console.error(`[admin-sessions-list] subagents-skipped slug=${slug} code=${code}`);
12056
+ skipped += 1;
12019
12057
  continue;
12020
12058
  }
12021
12059
  for (const sub of subEntries) {
@@ -12031,6 +12069,7 @@ function enumerateJsonls(projectsRoot) {
12031
12069
  } catch (err) {
12032
12070
  const code = err.code ?? "unknown";
12033
12071
  console.error(`[admin-sessions-list] archive-skipped slug=${slug} code=${code}`);
12072
+ skipped += 1;
12034
12073
  continue;
12035
12074
  }
12036
12075
  for (const arc of archiveEntries) {
@@ -12041,7 +12080,10 @@ function enumerateJsonls(projectsRoot) {
12041
12080
  }
12042
12081
  }
12043
12082
  }
12044
- return out;
12083
+ return { files: out, skipped };
12084
+ }
12085
+ function enumerateJsonls(projectsRoot) {
12086
+ return enumerateJsonlsWithSkips(projectsRoot).files;
12045
12087
  }
12046
12088
  async function fetchLiveSessions() {
12047
12089
  const out = /* @__PURE__ */ new Map();
@@ -12182,7 +12224,6 @@ async function computeSessionList(scopeAccountId) {
12182
12224
  return { sessions: [], accountId: scopeAccountId };
12183
12225
  }
12184
12226
  const projectsRoot = join21(configDir2, "projects");
12185
- const jsonls = enumerateJsonls(projectsRoot);
12186
12227
  const liveSessions = await fetchLiveSessions();
12187
12228
  const accountDir = scopeAccountId ? resolve15(ACCOUNTS_DIR, scopeAccountId) : null;
12188
12229
  const userTitles = await loadUserTitlesAsync(accountDir);
@@ -12216,6 +12257,7 @@ async function computeSessionList(scopeAccountId) {
12216
12257
  const cacheLoad = await loadTitleCacheOutcome(titleCacheDir);
12217
12258
  const titleCache = cacheLoad.cache;
12218
12259
  const cacheUpdates = /* @__PURE__ */ new Map();
12260
+ const { files: jsonls, skipped: enumSkipped } = enumerateJsonlsWithSkips(projectsRoot);
12219
12261
  let enumeratedCount = 0;
12220
12262
  let scopedCount = 0;
12221
12263
  let titleCacheHits = 0;
@@ -12227,6 +12269,7 @@ async function computeSessionList(scopeAccountId) {
12227
12269
  let tailReadFails = 0;
12228
12270
  let tailBytes = 0;
12229
12271
  let cacheWriteFails = 0;
12272
+ let evicted = 0;
12230
12273
  const walkStartedAt = Date.now();
12231
12274
  for (const { path: path3, isSubagent, archived } of jsonls) {
12232
12275
  const lastSlash = path3.lastIndexOf("/");
@@ -12389,9 +12432,13 @@ async function computeSessionList(scopeAccountId) {
12389
12432
  console.error(`[admin-sessions-list] op=channel-name-unresolved sessionId=${m.sessionId.slice(0, 8)} channel=${m.channel} senderId= reason=no-senderId`);
12390
12433
  }
12391
12434
  rows.sort((a, b) => a.startedAt < b.startedAt ? 1 : -1);
12392
- if (titleCacheDir && cacheUpdates.size > 0) {
12435
+ const evictIds = /* @__PURE__ */ new Set();
12436
+ if (enumSkipped === 0 && seenIds.size > 0) {
12437
+ for (const sessionId of titleCache.keys()) if (!seenIds.has(sessionId)) evictIds.add(sessionId);
12438
+ }
12439
+ if (titleCacheDir && (cacheUpdates.size > 0 || evictIds.size > 0)) {
12393
12440
  try {
12394
- await saveTitleCacheMerged(titleCacheDir, cacheUpdates);
12441
+ evicted = await saveTitleCacheMerged(titleCacheDir, cacheUpdates, evictIds);
12395
12442
  } catch (err) {
12396
12443
  cacheWriteFails += 1;
12397
12444
  console.error(
@@ -12401,7 +12448,7 @@ async function computeSessionList(scopeAccountId) {
12401
12448
  }
12402
12449
  const bytesMB = (titleBytes + tailBytes) / (1024 * 1024);
12403
12450
  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}`
12451
+ `[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
12452
  );
12406
12453
  console.log(
12407
12454
  `[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 +19507,7 @@ async function restoreNode(params) {
19460
19507
  }
19461
19508
 
19462
19509
  // 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;
19510
+ 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
19511
  function parseAttachmentPath(relPath) {
19465
19512
  const segments = relPath.split("/").filter(Boolean);
19466
19513
  if (segments.length !== 5) return null;
@@ -19468,7 +19515,7 @@ function parseAttachmentPath(relPath) {
19468
19515
  const accountId = segments[1];
19469
19516
  const attachmentId = segments[3];
19470
19517
  const filename = segments[4];
19471
- if (!UUID_RE3.test(accountId) || !UUID_RE3.test(attachmentId)) return null;
19518
+ if (!UUID_RE4.test(accountId) || !UUID_RE4.test(attachmentId)) return null;
19472
19519
  const dot = filename.lastIndexOf(".");
19473
19520
  if (dot === -1) return null;
19474
19521
  const stem = filename.slice(0, dot);
@@ -20076,7 +20123,7 @@ function classifyAccountRoot(schemaMd, rootEntries) {
20076
20123
 
20077
20124
  // server/routes/admin/files.ts
20078
20125
  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;
20126
+ 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
20127
  async function readMeta(absDir, baseName) {
20081
20128
  try {
20082
20129
  const raw = await readFile9(join38(absDir, `${baseName}.meta.json`), "utf8");
@@ -20098,7 +20145,7 @@ async function readAccountNames() {
20098
20145
  return map;
20099
20146
  }
20100
20147
  for (const name of names) {
20101
- if (!UUID_RE4.test(name)) continue;
20148
+ if (!UUID_RE5.test(name)) continue;
20102
20149
  const configPath2 = resolve27(accountsDir, name, "account.json");
20103
20150
  try {
20104
20151
  const raw = await readFile9(configPath2, "utf8");
@@ -20133,7 +20180,7 @@ async function servableFilesIn(dirAbs, uuid) {
20133
20180
  return out;
20134
20181
  }
20135
20182
  async function enrich(absolute, entry, accountNames) {
20136
- if (entry.kind === "directory" && UUID_RE4.test(entry.name)) {
20183
+ if (entry.kind === "directory" && UUID_RE5.test(entry.name)) {
20137
20184
  const dirAbs = join38(absolute, entry.name);
20138
20185
  const meta = await readMeta(dirAbs, entry.name);
20139
20186
  if (meta?.filename) {
@@ -20168,7 +20215,7 @@ async function enrich(absolute, entry, accountNames) {
20168
20215
  if (entry.kind === "file") {
20169
20216
  const dot = entry.name.lastIndexOf(".");
20170
20217
  const base = dot === -1 ? entry.name : entry.name.slice(0, dot);
20171
- if (UUID_RE4.test(base)) {
20218
+ if (UUID_RE5.test(base)) {
20172
20219
  const meta = await readMeta(absolute, base);
20173
20220
  if (meta?.filename) {
20174
20221
  entry.displayName = meta.filename;
@@ -20181,7 +20228,7 @@ async function enrich(absolute, entry, accountNames) {
20181
20228
  function buildDisplayPath(relPath, accountNames) {
20182
20229
  if (relPath === "." || relPath === "") return [];
20183
20230
  return relPath.split("/").filter(Boolean).map((seg) => {
20184
- const dn = UUID_RE4.test(seg) ? accountNames.get(seg) : void 0;
20231
+ const dn = UUID_RE5.test(seg) ? accountNames.get(seg) : void 0;
20185
20232
  return dn ? { name: seg, displayName: dn } : { name: seg };
20186
20233
  });
20187
20234
  }
@@ -20193,13 +20240,13 @@ function parseGroupPath(raw, sessionAccountId) {
20193
20240
  }
20194
20241
  const segs = trimmed.split("/").filter(Boolean);
20195
20242
  if (segs.length !== 3) return null;
20196
- if (segs[0] !== "accounts" || !UUID_RE4.test(segs[1])) return null;
20243
+ if (segs[0] !== "accounts" || !UUID_RE5.test(segs[1])) return null;
20197
20244
  if (segs[2] !== "@home" && segs[2] !== "@system") return null;
20198
20245
  return { view: segs[2].slice(1), accountRel: `accounts/${segs[1]}` };
20199
20246
  }
20200
20247
  function isAccountRoot(relPath) {
20201
20248
  const segs = relPath.split("/").filter(Boolean);
20202
- return segs.length === 2 && segs[0] === "accounts" && UUID_RE4.test(segs[1]);
20249
+ return segs.length === 2 && segs[0] === "accounts" && UUID_RE5.test(segs[1]);
20203
20250
  }
20204
20251
  function sortDirEntries(entries2) {
20205
20252
  entries2.sort((a, b) => {
@@ -20247,11 +20294,11 @@ function isProtectedFromRename(relPath) {
20247
20294
  if (segments.length === 3 && segments[0] === "accounts" && segments[2] === "uploads") {
20248
20295
  return true;
20249
20296
  }
20250
- if (segments.length === 4 && segments[0] === "accounts" && segments[2] === "uploads" && UUID_RE4.test(segments[3])) {
20297
+ if (segments.length === 4 && segments[0] === "accounts" && segments[2] === "uploads" && UUID_RE5.test(segments[3])) {
20251
20298
  return true;
20252
20299
  }
20253
20300
  if (parseAttachmentPath(relPath) !== null) return true;
20254
- if (UUID_RE4.test(base.replace(/\.meta\.json$/, "")) && base.endsWith(".meta.json")) {
20301
+ if (UUID_RE5.test(base.replace(/\.meta\.json$/, "")) && base.endsWith(".meta.json")) {
20255
20302
  return true;
20256
20303
  }
20257
20304
  return false;
@@ -20327,10 +20374,10 @@ app23.get("/", requireAdminSession, async (c) => {
20327
20374
  const isAccountParent = segs.length === 1 && segs[0] === "accounts";
20328
20375
  const entries2 = [];
20329
20376
  for (const name of names) {
20330
- if (UUID_RE4.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
20377
+ if (UUID_RE5.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
20331
20378
  continue;
20332
20379
  }
20333
- if (isAccountParent && UUID_RE4.test(name) && name !== accountId) {
20380
+ if (isAccountParent && UUID_RE5.test(name) && name !== accountId) {
20334
20381
  continue;
20335
20382
  }
20336
20383
  const childRel = relPath === "" || relPath === "." ? name : `${relPath}/${name}`;
@@ -21050,8 +21097,8 @@ app23.delete("/", requireAdminSession, async (c) => {
21050
21097
  const dot = base.lastIndexOf(".");
21051
21098
  const stem = dot === -1 ? base : base.slice(0, dot);
21052
21099
  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;
21100
+ const sidecarPath = UUID_RE5.test(stem) && base !== `${stem}.meta.json` ? join38(containerDir, `${stem}.meta.json`) : null;
21101
+ const isAttachmentContainer = UUID_RE5.test(stem) && basename11(containerDir) === stem;
21055
21102
  await unlink4(absolute);
21056
21103
  if (sidecarPath) {
21057
21104
  try {
@@ -27652,7 +27699,7 @@ var visitor_event_default = app65;
27652
27699
  // server/routes/session.ts
27653
27700
  import { resolve as resolve37 } from "path";
27654
27701
  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;
27702
+ 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
27703
  function writeBrandingCache(accountId, agentSlug, branding) {
27657
27704
  try {
27658
27705
  const cacheDir = resolve37(MAXY_DIR, "branding-cache", accountId);
@@ -27667,7 +27714,7 @@ function parseVisitorCookie2(cookieHeader) {
27667
27714
  const match = cookieHeader.match(/(?:^|;\s*)maxy_visitor=([^;]*)/);
27668
27715
  if (!match) return null;
27669
27716
  const value = decodeURIComponent(match[1]).trim();
27670
- return UUID_RE5.test(value) ? value : null;
27717
+ return UUID_RE6.test(value) ? value : null;
27671
27718
  }
27672
27719
  function parseAccessSessionId2(cookieHeader) {
27673
27720
  if (!cookieHeader) return null;
@@ -27765,7 +27812,7 @@ app66.post("/", async (c) => {
27765
27812
  );
27766
27813
  }
27767
27814
  }
27768
- if (body.session_key && typeof body.session_key === "string" && UUID_RE5.test(body.session_key)) {
27815
+ if (body.session_key && typeof body.session_key === "string" && UUID_RE6.test(body.session_key)) {
27769
27816
  if (visitorId) {
27770
27817
  const recent = await findRecentConversation(visitorId, accountId, agentSlug).catch(() => null);
27771
27818
  if (recent) {
@@ -32126,6 +32173,7 @@ var waGateway = new WaGateway({
32126
32173
  return result.ok ? { ok: true, messageId: result.messageId } : { ok: false, error: result.error };
32127
32174
  },
32128
32175
  ensureChannelSession: async ({ accountId, effectiveAccountId, senderId, role, personId, gatewayUrl, serverPath, passive, text, msgId, ownerSelfPhone, replyContext }) => {
32176
+ warnNonUuidAccount("channel-spawn", effectiveAccountId);
32129
32177
  if (passive) {
32130
32178
  const phoneHash = createHash8("sha256").update(senderId).digest("hex").slice(0, 12);
32131
32179
  const prompt = (text ?? "").trim();
@@ -32174,7 +32222,7 @@ var waGateway = new WaGateway({
32174
32222
  return;
32175
32223
  }
32176
32224
  if (role === "admin") {
32177
- const managesAccount = effectiveAccountId !== accountId ? effectiveAccountId : "none";
32225
+ const managesAccount = managesAccountFor(effectiveAccountId, resolveReadStoreKey(accountId));
32178
32226
  console.error(`[whatsapp-native] op=account-manager-route senderId=${senderId} managesAccount=${managesAccount} effectiveAccount=${effectiveAccountId} source=gate`);
32179
32227
  }
32180
32228
  const req = buildWaSpawnRequest({