rdmsm4x — fleet state consolidation and GitHub sync
[2026-08-31 13:23:49 EDT · rdmsm4x] · session
dev-ec [0e396b] · window 12:23:21 → 14:10 EDT
One line: every project now lives on rdmsm4x and 101
repositories push clean to private GitHub mirrors — including 18
directories that no repository had ever covered and every host's
~/scripts — all five spoke Macs are pointer-only with their
old trees moved (not deleted) to on-host archives, and the consolidation
uncovered a credential incident: live Cloudflare, GoDaddy, TLS and
employer credentials published to private repos for up to 19 days, now
quarantined behind a new content gate but needing Rich to rotate and to
decide one disclosure question.
Session: dev-ec [0e396b],
claude@rdmsm4x · Window: 2026-08-31
12:23:21 → 13:23:49 EDT (1h 00m) Mandate: Rich,
/goal 12:23 EDT — consolidate every project onto
rdmsm4x, merge duplicates, sync latest state to GitHub,
sync with fleet agents, leave spokes holding only remote pointers. All
actions pre-approved; decide rather than block.
⚠ READ FIRST — a credential incident, and it needs you
The consolidation is done. What matters more is what the
consolidation uncovered: live credentials have been
published to private GitHub repos for up to 19 days. Full
ordered rotation list with per-finding evidence:
fleet/consolidation-20260831/CREDENTIAL-AUDIT.md (9 rows).
Ticket: ISSUES.md → ISSUE-20260831-01.
Rotation is yours; everything an agent could safely do is done.
Rotate in this order. Each is live in
~/.secrets/global.env, so update that file as you
rotate or whatever reads it breaks.
CLOUDFLARE_GLOBAL_API_KEY— account-wide and unscopable: every zone, DNS record and billing setting fordev.ecs0.netanddataroo.net. Exposed via four repos.GODADDY_API_KEY+GODADDY_API_SECRET— the registrar. With #1 that is DNS and registrar: enough to redirect or transfer the domain, not merely edit records.- TLS private key material for
dataroo.net— three files inai/LLM, including thecertbot .../live/dataroo.net/privkey.pem. This is a certificate compromise, not a key rotation: revoke and reissue. Rotating anything else is pointless while the old cert is still trusted. Exposed since 2026-08-12 — a 19-day window. TOSHLLM_API_KEY, the OpenAI keys, the AWS key, the Dropbox app key + secret.
A decision only you can make.
sites/dataroo.dev/public/startup_notes.json carries tokens
labelled "arista lclaude API key" beside
[email protected] and
aikeys.infra.corp.arista.io — employer credentials
on a personal GitHub account, published since 2026-08-27 and
confirmed present in the fetched tree. This crosses the boundary your
own RULE-employer-client-material-boundary-20260823.md
exists to protect, and it got there inside a personal project
rather than through the excluded arista/ domain. Beyond
rotation, whether Arista needs telling is your call and your
employer's, not an agent's.
A separate hard blocker that outlives the GitHub cleanup: do
not deploy sites/dataroo.dev until public/ is
cleaned. It is a Next.js app with
output: "standalone", and Next serves everything in
public/ at the site root with no authentication — a 6.1 MB
file of credentials would be fetchable at
/startup_notes.json the moment that site gets an A record.
It has none today; verified twice independently, status codes only,
never response bodies.
Order matters: rotate BEFORE deleting refs. Deleting
a ref hides an exposed key without invalidating it. And the two exposure
classes need different remediation — apps/dataROO,
apps/fleetreg and ai/LLM have secrets in real
commits (history rewrite or repo deletion);
concepts/llm-wiki, sites/dataroo.dev and
concepts/icloud-cleanup have them only in
refs/backup/snap-* (ref deletion genuinely suffices). Repo
deletion needs an interactive
gh auth refresh -s delete_repo.
Stopped from getting worse: six repos quarantined —
ai/LLM, concepts/llm-wiki,
concepts/icloud-cleanup, apps/dataROO,
apps/fleetreg, sites/dataroo.dev. And the tool
that leaked them is fixed: github_backup_dev.zsh
v1.6 now gates on file CONTENT, not just filenames.
It caught sites/dataroo.dev itself, in production,
on its first full run — a repo nobody had flagged, which had
been re-publishing every night. Quarantine stops the bleeding; it does
not un-expose anything already pushed.
What the goal asked for, and where each part actually landed
"All projects located on rdmsm4x" — DONE
Five spokes inventoried read-only. Result:
- rdmbair13m5 held a 121-commit
apps/Tyrellwith no remote, which read as unpromoted work. It was not: HEAD6ddef9bis a strict ancestor of canonical's 212 commits (shared root560608c) and its one modified file was byte-identical to canonical. Its.gitwas moved to~/dev-archive-20260831/on that host with the evidence written beside it. - jdmbair13m5, rdmpw3265m, rdmpw3275m held no git repositories at all — changelogs, build artifacts and small handoff docs. All promoted.
- rdmbair15m5 was a genuine 19 GB second working
root. Its delta — 15,836 files / 1.4 GB present there
and absent or different on canonical — was intaken to
~/dev/_fleet-intake-20260831/rdmbair15m5/. - 634 changelogs across all six hosts consolidated
into
~/dev/LLM/Claude/changelogs/.
"Merged / consolidated" — DONE, with two deliberate non-merges
- Root-level strays
local-llm-benchmark/andrdmpw3265m-reports/merged into their canonical homes and moved toarchive/consolidation-20260831/. Empty~/dev/rdmsm4x/removed. - NOT merged, on purpose: rdmbair15m5's
agy/*(1.2 GB) is stale pre-consolidation copies — canonical carries 32.MOVED.mdtombstones proving those projects were deliberately moved intoapps/on 2026-08-24. Restoring them would have undone that consolidation. They are preserved in the intake and left there. - NOT merged, on peer warning:
apps/obsidian_fleet_syncis a real separate directory and a strict subset ofapps/ObsidianFleetSync. Two prior sessions were burned by "merging" it. Left alone and recorded.
"Synchronized to a github repo" — DONE for everything permitted
103 repositories attempted, 103 pushed, 0 failed on the final run (13:17 EDT). 108 registered locally; 312 repos now exist on the account.
The substantive win was not pushing existing repos — it was finding what no repository covered at all, and therefore what the nightly backup had never once seen:
| Newly under version control | Size |
|---|---|
design |
28,143 files, 2.1 GB |
fleet |
1,428 tracked files |
agy, notes, todo,
data, docs, tests,
_nocontext, outputs, inbound,
packages, skills, bladerunner,
_fleet, _handoffs,
macos-tools |
— |
issues (the fleet ticket store — had history but
no remote at all) |
first off-host backup |
Plus the 25 root-level documents —
AUTHORITY.md, CLAUDE.md,
PROJECTS.md, ISSUES.md,
SESSION-STATE.md and 20 more — which lived at the
~/dev root on exactly one disk. They are now snapshotted
into fleet/dev-root-docs/ by
sync_dev_root_docs.zsh. git init in
~/dev itself was considered and rejected: it would
make git add -A from that directory legal in a tree six
agents write concurrently, which is precisely the failure that has
already swept other sessions' work into the wrong commit here. A copy is
the safe version of the same backup.
"Spokes hold only remote projects pointing to our source" — DONE
Every spoke verified at 13:11 EDT: 0 git
repositories, README-CANONICAL-DEV.md and
FLEET-PROJECT-POINTERS.md present (87 projects → their
private mirrors).
| Host | ~/dev before |
after | archived locally |
|---|---|---|---|
| rdmbair15m5 | 19 GB | 823 MB | 18 GB |
| rdmbair13m5 | 816 MB | 763 MB | 95 MB |
| jdmbair13m5 | 1.0 GB | 1.1 GB | — |
| rdmpw3265m | 1.3 GB | 1.3 GB | — |
| rdmpw3275m | 1.3 GB | 1.3 GB | — |
Moved, never deleted. Everything removed from a
spoke sits in ~/dev-archive-20260831/ on that same host,
restorable with one mv. What was kept on each spoke was
determined by reading its launchd plists, not by guessing:
apps/Tyrell (tyrelld, tyrellbar)
and _ops/fleetwatch (offhostwatch) are live
dependencies and were left untouched.
"Sync with all agents in the fleet" — DONE
Coordinated with dev-8a (which held the same mandate,
issued 9 minutes later, and stood down to a narrow lane),
jdmbair13m5-scalable-widget, and dev-e2. Their
census prevented four concrete mistakes: intaking over dev-bf's
in-flight LogTTY release, merging the obsidian_fleet_sync subset, using
Tyrell's fleet_status as a sync gate (it has a permanent
nonzero floor), and treating sites/dev.ecs0.net as mine to
commit.
I was corrected once and it mattered. I reported "83
gmail-authored commits in LogTTY, needs a history rewrite."
dev-8a re-measured per repo: the real number was 3, all
made that afternoon, all unpushed, fixed by an amend. My scan had
counted every non-noreply author and swept in 82 legitimate
[email protected] commits that push fine. Same
aggregate, opposite response — and the wrong version would have put a
pointless privacy decision in front of Rich. I verified the correction
independently before accepting it.
Left open, deliberately, with owners
| Item | Owner | Why not done here |
|---|---|---|
ISSUE-20260831-01 credential rotation |
Rich | Rotation, ref deletion and repo deletion are all his; ref deletion is blocked here and is the wrong first step anyway |
ISSUE-20260831-06 apps/RDReceipt protected
by nothing but this disk |
Rich | Correctly excluded from GitHub (real financial corpus) — but
"excluded" must not read as "covered", and its newest work is on an
unmerged branch. Same question for apps/autoCE and 7
arista/* |
ISSUE-20260831-07 apps/xframework mirrors
to a stale repo name |
Rich / any permitted session | gh repo rename blocked here; content pushed to the old
remote so it is not unprotected |
fleet/maintenance push blocked by GH007 |
dev-e2 |
One git commit --amend on an unpushed commit in their
tree — handed over with the exact command |
ISSUE-20260831-03 sites/dev.ecs0.net lost
commit fcd185d |
session holding that tree | Content survives as 35,752 staged additions; one commit from recovery. Not mine to commit |
ISSUE-20260831-05 /Users/richh/scripts/
unbacked on every host |
Rich | Outside ~/dev and outside this scope. The sharper case:
MCPFleetDisable/backups/20260830-1648/ on jdmbair13m5 is
the only undo path for the Stitch disable |
| Apple Notes changelogs on jdmbair13m5 | that host's GUI session | My original wording here was wrong. I wrote that
the host "cannot publish, not an Aqua session".
launchctl managername is a property of the
session, not the host: from my SSH connection it
returns Background, while a session running inside that
host's GUI login context returns Aqua — and both are
correct simultaneously. The console user there is richh
with one live console session, so an Aqua session exists. The refusal
was correct for the session that hit it; generalising it to the host was
not. Needs one re-check after that host's pending reboot. |
ISSUE-20260831-02/04 backup-script gaps |
next fleet-tooling session | A repo whose .git is destroyed vanishes from the report
silently; and the credential gate checks filenames, not content — which
is exactly how ISSUE-01 happened |
What the second half of the session added (subagents + peer sessions)
Rich asked for subagents once the consolidation was done. Two ran at Sonnet, each producing one artifact, alongside continuous exchange with four peer sessions. That collaboration is where the credential incident was actually found — not by the consolidation itself.
CREDENTIAL-AUDIT.md— 9 ordered rotation rows, every finding checked against what GitHub actually holds (git ls-remote, plusgit archiveof the pushed snapshot refs into an isolated copy) rather than what is merely on disk. 12 benign categories named so they are never re-chased. It found the TLS keys and the Arista material, neither of which any earlier scan had.SCRIPTS-AUDIT.md+fleet/tooling/host-scripts/— closesISSUE-20260831-05. 177 files from all six hosts'~/scripts, which was under no git repo and no mirror anywhere. Stored per-host rather than deduplicated, deliberately: picking a winner for each of the 9 divergent files would silently overwrite a real difference for 8.2 MB of saving. It also caught thatjdmbair13m5was running a buggyagent_session_logger.zshv1.0.0 that printed spurious job-control notices into every terminal on that host — fixed, now v1.1.1 like the other five.github_backup_dev.zshv1.6 — content gate plus lost-git detection, written here, then hardened three times by peer review (below).
Four corrections this session took — the record, because the corrections were the value
dev-8a: my "83 gmail commits in LogTTY need a history rewrite" was wrong. Real answer: 3, all unpushed, fixed by one amend. I had counted every non-noreply author. Re-measured per repo and confirmed before accepting. The wrong version would have put a pointless privacy decision in front of Rich.dev-e2: llm-wiki was NOT the worst case, as this document originally said — itsmainis clean. Three other repos had secrets committed. Verified independently, and found ai/LLM was 12 files not 10.dev-e2, twice more, on my own fix: v1.6's extractor was anchored to end-of-line, so any value with a trailing comment was invisible — andCLAUDE.mdtells Rich to store secrets with a dated comment, so the gate would have gone blind to the Cloudflare key the hour he rotated it. And the candidate list was capped before the placeholder filter, so a documentation repo could discard every real hit. Both fixed.- Mine, in my own code: the gate first read
git diff --cached— only what changed since HEAD. Every secret already committed appears in no diff, so it would have waved all three EXPOSED-TRACKED repos through nightly, forever, while reporting success. The failure mode wearing the fix's clothes. Now readsls-files --cached.
dev-bf separately retracted a "stale, nothing to
salvage" verdict on rdmbair15m5's LogTTY after this session read the
working tree rather than the commit graph — 62 files that exist nowhere
else were one archive away from being lost. Handoff:
_handoff/HANDOFF-logtty-rdmbair15m5-delta-20260831.md.
Two honest caveats about this session's own work
- The intake's second pass over
apps/used a wrong--compare-dest(~/dev/instead of~/dev/apps/), so it re-copied ~17,453 files that were already identical to canonical. The first pass is the authoritative delta (15,836 files). The effect is an over-full intake directory, not a gap — over-preservation is the safe direction of that error, but the numbers in_fleet-intake-20260831/should not be read as "all of this was unique." --compare-destcompares by size and mtime, not checksum. A file identical in both but differing in content would have been skipped. Judged low-risk because these trees were rsync-distributed from canonical with mtimes preserved — and in any case nothing was deleted, so the spoke archives remain a second copy.