feat/sites-1n
needs attentionviewing older commit8fa38b5 · incrementalpre-PRreviewed 2026-07-08 01:45 UTC2H · 4M · 5L · 1I- Purpose
- Fix the Site↔RPU relationship: stop fusing unrelated RPUs onto one site (dedup only when internal ID AND name match; never default site name to service name). Provide UX to see and manage the 1:N relationship.
- Goal
- Make the Site↔RPU relationship correct, visible, and manageable with a one-shot remediation script to fix existing merged sites post-merge.
- Sub-goals
- SG-1: Shared site-resolution decision + rewire both coordinators (composite dedup)
- SG-2: Site match/search extended with internal ID match + contractCount
- SG-3: createFromWizard accepts existingSitePublicId
- SG-4: Drawer match-driven Crear/Usar-existente with picker
- SG-5: Site cell pencil → SiteEditModal (edit/move/split)
- SG-6: Agrupar-por-sitio toggle with site rows
- SG-7: Batch preview grouped by (internal id + name) with existing-site flags
- SG-8: 4 typed analytics events + cross-domain CLAUDE.md
- Remediation: split-merged-sites.ts one-shot script (authored on-branch, executed post-merge)
- What
- This commit adds pre-execution validation to split-merged-sites.ts: (1) per-org census printout from the live DB, (2) durable JSON snapshot to CWD for audit/rollback, (3) interactive 'type split' confirmation gate with --yes bypass. Runbook doc updated to describe the snapshot artifact.
- Why
- Operators need to validate current DB state before executing the irreversible 1→N site split. The snapshot provides an audit trail and rollback complement (split_from complement field); the confirmation gate prevents accidental execution.
- Areas
- scripts+357−0apps/platform+1192−163domains/cross-domain+352−129domains/core+33−1domains/utility+61−5packages/api + analytics+63−4docs/development+324−1
- Blast
- 26 files, +2,228/−471 branch-wide. Incremental window (this commit): 2 files, +84/−1 in scripts + docs only.
Findings · 12
correctness2
Snapshot mode:'execute' written before confirmation — misleads on aborted runs
scripts/split-merged-sites.ts:280
Snapshot JSON written before the interactive prompt. If operator runs --execute but declines at 'type split', the file already has mode:'execute'. An auditor sees a misleading record.
Snapshot silently overwritten on same-second re-run
scripts/split-merged-sites.ts:274
Two invocations within the same second produce the same filename; writeFileSync overwrites without warning.
security3
Snapshot written to CWD — full org/site/RPU inventory may be exposed on shared hosts
scripts/split-merged-sites.ts:283
Relative path anchored to process.cwd(). On a shared EC2 host the file is world-readable by default. Fix: writeFileSync(path, data, { mode: 0o600 }).
--yes bypasses TTY check and confirmation with no audit trail in snapshot
scripts/split-merged-sites.ts:318
If injected into a CI invocation, the irreversible split runs silently. Snapshot should record that --yes was used.
Snapshot written unconditionally on dry-runs — full inventory disclosed without --execute
scripts/split-merged-sites.ts:287
Any dry-run produces a JSON with complete site/org/RPU data. Consider writing only when --execute is confirmed, or adding to .gitignore.
improvement7
Snapshot written before dry-run exit — accumulates files on repeated invocations
scripts/split-merged-sites.ts:274
writeFileSync runs before the !EXECUTE guard. Per-org pilot dry-runs leave many snapshot files; the last may not reflect the final execute state if RPUs enrolled between runs. Write the snapshot only when --execute is confirmed.
Confirmation count is stale — derived from pre-query targets, not live DB at execute time
scripts/split-merged-sites.ts:320
'About to split N sites into M new sites' from outer findSuspiciousSites. splitSite re-reads inside FOR UPDATE. If RPUs added between query and confirmation, displayed count underestimates. Qualify as 'at least M'.
Aborting via wrong confirmation answer exits with code 0 — pipelines cannot detect abort
scripts/split-merged-sites.ts:324
The 'confirmation not given' return path exits 0. Only the no-TTY path sets exitCode=1. Wrapper scripts cannot distinguish abort from success.
--yes accepted without evidence a dry-run snapshot was reviewed first
scripts/split-merged-sites.ts:91
Header says --yes is for 'piped runs after reviewing a dry-run + snapshot' but nothing enforces this. Emit a WARNING line when --yes is used.
writeFileSync has no error handling — read-only CWD throws opaque FS error
scripts/split-merged-sites.ts:275
If CWD is not writable, the script throws EACCES before showing any census output.
orgRollup keyed by org_name (mutable) — two orgs with same name collide in census
scripts/split-merged-sites.ts:256
org_name is user-editable. Key by org_id and display the name alongside.
Post-run verify uses filtered query — misleading 'OK' for partial runs
scripts/split-merged-sites.ts:344
With --org or --limit, 'no multi-RPU sites remain' shows even when other orgs are unprocessed.
History · 8 commits
- 7b5ff24needs attentionincremental0H · 2M · 3L2026-07-09 00:58
- 6231fe5needs attentionincremental0H · 2M · 4L2026-07-08 22:34
- 8fa38b5needs attentionincremental2H · 4M · 5L2026-07-08 01:45current
- 83fd5a0needs attentionincremental3H · 8M · 11L2026-07-08 01:37
- 23c04fcneeds attentionincremental3H · 3M · 2L2026-07-07 20:30
- e70f9f5blockedincremental6H · 11M · 6L2026-07-07 19:28
- 499b1a5blockedincremental6H · 9M · 5L2026-07-07 18:26
- ff23301needs attentionincremental2H · 6M · 5L2026-07-07 01:05