← back to Butlr
migrate: re-link orphaned user_id refs to current legacy admin
4d008b0c094709831c303d364b186db127692175 · 2026-05-12 17:03:23 -0700 · SteveStudio2
When users.json is wiped between deploys (which happened during the
v2 rollout — fixed by RSYNC_EXTRA_EXCLUDES in .deploy.conf), existing
calls keep pointing at the old admin's user_id. The new admin gets a
fresh id, and the calls become invisible to Steve. This pass detects
user_ids missing from users.json and re-stamps them to the current
legacy admin. Idempotent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
M scripts/migrate-calls-to-user.js
Diff
commit 4d008b0c094709831c303d364b186db127692175
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Tue May 12 17:03:23 2026 -0700
migrate: re-link orphaned user_id refs to current legacy admin
When users.json is wiped between deploys (which happened during the
v2 rollout — fixed by RSYNC_EXTRA_EXCLUDES in .deploy.conf), existing
calls keep pointing at the old admin's user_id. The new admin gets a
fresh id, and the calls become invisible to Steve. This pass detects
user_ids missing from users.json and re-stamps them to the current
legacy admin. Idempotent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
scripts/migrate-calls-to-user.js | 31 ++++++++++++++++++++++++-------
1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/scripts/migrate-calls-to-user.js b/scripts/migrate-calls-to-user.js
index 8d0e18d..9969226 100644
--- a/scripts/migrate-calls-to-user.js
+++ b/scripts/migrate-calls-to-user.js
@@ -40,21 +40,38 @@ function main() {
process.exit(3);
}
- // 3. Stamp.
- let stamped = 0, already = 0;
+ // 3. Build a set of valid user_ids so we can detect orphans.
+ const validIds = new Set();
+ try {
+ const usersFile = path.join(__dirname, '..', 'data', 'users.json');
+ const usersList = JSON.parse(fs.readFileSync(usersFile, 'utf8'));
+ for (const u of usersList) validIds.add(u.id);
+ } catch {}
+
+ let stamped = 0, already = 0, reassigned = 0;
for (const c of calls) {
- if (c.user_id) { already++; continue; }
- c.user_id = admin.id;
- stamped++;
+ if (!c.user_id) {
+ c.user_id = admin.id;
+ stamped++;
+ } else if (!validIds.has(c.user_id)) {
+ // Orphaned — owner user_id is no longer in users.json (deleted or
+ // wiped). Re-link to current legacy admin so Steve doesn't lose
+ // his own call history.
+ console.log(` re-link orphan ${c.id}: ${c.user_id} → ${admin.id}`);
+ c.user_id = admin.id;
+ reassigned++;
+ } else {
+ already++;
+ }
}
- console.log(`stamped ${stamped} (already-owned: ${already}, total: ${calls.length})`);
+ console.log(`stamped ${stamped} | reassigned ${reassigned} | already-owned ${already} | total ${calls.length}`);
// 4. Write back (with backup).
if (DRY_RUN) {
console.log('[dry-run] not writing');
return;
}
- if (stamped > 0) {
+ if (stamped + reassigned > 0) {
const backup = CALLS_FILE + '.pre-user-migration.' + new Date().toISOString().replace(/[:.]/g,'-');
fs.copyFileSync(CALLS_FILE, backup);
fs.writeFileSync(CALLS_FILE, JSON.stringify(calls, null, 2));
← 927b54f owner-auth: detect /api/* via originalUrl so middleware moun
·
back to Butlr
·
deploy.conf: lock in data/ excludes — rsync had wiped real c bc26177 →