Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
11 KiB
2026.08.23.05 — deploy report
5 of 5 target hosts succeeded. Two hosts skipped by design: officer-dev (the host running the
rollout) and edge-pertento-bridge (in the Deliberately skipped section of docs/servers.md).
Every target ended at e15ab2303a17ed0e1d1cf59b35f34aec68875907 = deploy/2026.08.23.05, merged
--ff-only onto the tag itself. No host was left on the branch, and no host is a commit past the tag.
Schema evidence is per host, by query, below. --force was never used and was never needed.
Per host
alpha — succeeded
Checkout (from PM2 pm_cwd) |
/home/pastilhas/officerdev/platform |
| HEAD before | ff647fba (deploy/2026.08.23.04) |
| HEAD after | e15ab230 (deploy/2026.08.23.05) |
| Tracked changes before | none |
| Untracked files | none |
Pre-check: roles = 4, orphan users 0, orphan grants 0.
SQL applied, exit 0. Verification query:
conname | pg_get_constraintdef
-------------------------------+-------------------------------------------------------------
ck_role_permissions_not_owner | CHECK ((role <> 'Super Admin'::text))
fk_role_permissions_role | FOREIGN KEY (role) REFERENCES roles(name) ON UPDATE CASCADE
fk_users_role | FOREIGN KEY (role) REFERENCES roles(name) ON UPDATE CASCADE
Both fk_ present, ON UPDATE CASCADE, no ON DELETE. ck_role_permissions_role absent.
ck_role_permissions_not_owner present. Re-queried after db:push — unchanged.
bun db:push ran clean. It is not a no-op on this host — see "The one thing that is not clean" below.
bun run plugins:update: 12/12 updated in 47s, exit 0. That step restarted twelve plugin sidecars —
atelier, bitcoin-wallet, email, gitea, invoices, jellyfin, music, offscale, photos, soulseek,
transmission, vault.
pm2 restart officer: restart_time 70 → 71, online. All 19 officer* processes online afterwards.
fofos — succeeded
| Checkout | /home/pastilhas/officerdev/platform |
| HEAD before | ff647fba (deploy/2026.08.23.04) |
| HEAD after | e15ab230 (deploy/2026.08.23.05) |
| Tracked changes before | none |
| Untracked files | scripts/chk.ts — left alone, not a reason to skip |
Pre-check: roles = 4, orphans 0 / 0. SQL applied, exit 0. Verification query returned the same
three rows as alpha: both fk_ present with ON UPDATE CASCADE, ck_role_permissions_role absent,
ck_role_permissions_not_owner present.
bun db:push clean; a second push --verbose said No changes detected — a genuine no-op.
bun run plugins:update: 1/1 updated in 7s, exit 0. Restarted officer-gitea.
pm2 restart officer: 24 → 25, online. All 8 processes online.
production-pertento-bridge — succeeded
| Checkout | /home/pastilhas/officerdev/platform |
| HEAD before | ff647fba (deploy/2026.08.23.04) |
| HEAD after | e15ab230 (deploy/2026.08.23.05) |
| Tracked changes before | none |
| Untracked files | none |
Pre-check: roles = 4, orphans 0 / 0. SQL applied, exit 0. Verification query: same three rows,
same verdict.
bun db:push clean; second push --verbose → No changes detected.
bun run plugins:update: 1/1 updated in 5s, exit 0. Restarted officer-gitea.
pm2 restart officer: 3 → 4, online. All 15 processes online (this host also runs eight non-Officer
PM2 entries — Crons/Dashboard/Tracking/Uptime — untouched and still online).
Cosmetic, pre-existing, not caused by this release: every $SHELL -ic command on this host prints an
nvm warning about a globalconfig/prefix in ~/.npmrc. Nothing failed because of it.
deadpool-rezio-bridge — succeeded
Login br, per docs/servers.md.
| Checkout | /home/br/officerdev/platform |
| HEAD before | ff647fba (deploy/2026.08.23.04) |
| HEAD after | e15ab230 (deploy/2026.08.23.05) |
| Tracked changes before | none |
| Untracked files | none |
Pre-check: roles = 4, orphans 0 / 0. SQL applied, exit 0. Verification query: same three rows,
same verdict.
bun db:push clean; second push --verbose → No changes detected.
bun run plugins:update: 2/2 updated in 7s, exit 0. Restarted officer-email and officer-offscale.
pm2 restart officer: 9 → 10, online. All 9 processes online.
macbookpro — succeeded, and the host the plan flagged is now verified
Awake and reachable. macOS, so the PATH and psql notes in docs/servers.md all applied.
| Checkout | /Users/pastilhas/projects/officer-suite/platform |
| HEAD before | 6e092c32 (deploy/2026.08.23.04-48-g6e092c32) |
| HEAD after | e15ab230 (deploy/2026.08.23.05) |
| Tracked changes before | none |
| Untracked files | none |
It started 48 commits past the previous tag rather than on it — the tag was still an ancestor, so the fast-forward was legitimate and no reset was needed.
The roles table the plan could not verify before the tag is now verified: roles = 4, orphan users
0, orphan grants 0. The plan was right that there is no psql here — there is also no Homebrew
postgres and no postgres container. The query went through Bun's own SQL client (bun 1.3.14)
against the same OFFICERDEV_POSTGRES_URL the platform's drizzle.config.ts reads, so it is that host's
own database and not an inference from another one.
SQL applied through the same client, no exception raised. Verification query:
[
{ "conname": "ck_role_permissions_not_owner",
"pg_get_constraintdef": "CHECK ((role <> 'Super Admin'::text))" },
{ "conname": "fk_role_permissions_role",
"pg_get_constraintdef": "FOREIGN KEY (role) REFERENCES roles(name) ON UPDATE CASCADE" },
{ "conname": "fk_users_role",
"pg_get_constraintdef": "FOREIGN KEY (role) REFERENCES roles(name) ON UPDATE CASCADE" }
]
Both fk_ present with ON UPDATE CASCADE and no ON DELETE; ck_role_permissions_role absent;
ck_role_permissions_not_owner present. Same verdict as the other four.
bun db:push ran clean. It is not a no-op here either — see below.
bun run plugins:update: exit 0, and its whole output was no plugins installed — nothing to update.
No sidecar restarted. That is worth a second look and is covered below.
pm2 restart officer: 11 → 12, online. All 6 processes online.
The one thing that is not clean
The plan says bun db:push should be a no-op after the SQL, and that anything it still wants to alter
means the SQL was incomplete. On two hosts it still wants to alter something. It is not the release's
schema change, and the SQL was not incomplete — the verification query above proves the constraints
this release introduced are exactly right on all five hosts, and re-querying after push on alpha
showed them unchanged.
What push --verbose still wants, after the SQL:
alpha— drops and immediately re-addspk_music_now_playingonmusic_now_playing, with an identical definition.macbookpro— the samemusic_now_playingchurn, plus twoatelier_collection_itemsforeign keys dropped and re-added under names one character longer (…_id_f→…_id_fk).
Both are plugin tables, both are the documented drizzle-kit mis-diff on named composite constraints and
on foreign keys whose generated name Postgres truncates at 63 characters. The atelier case is
precisely the churn this release's notes claim to end "across the fleet's plugins" — and on alpha,
where the plugins did update, the atelier churn is indeed gone and only the music one remains. On
macbookpro the plugins did not update at all, so it still carries both.
fofos, production-pertento-bridge and deadpool-rezio-bridge all reported No changes detected —
a true no-op, which is the outcome the plan expected.
I judged this not to be a stop condition and continued. The reasoning, so it can be overruled: the plan's
"stop and report" is aimed at the roles/FK change being half-applied, that change is provably whole on
every host, and the residue is a pre-existing self-cancelling churn on plugin tables that this release
does not touch. If that call was wrong, the thing to re-examine is music_now_playing's composite
primary key — it is the one still churning on the host where plugins are current.
What I did not do, and could not verify
officer-dev— skipped entirely. Not pulled, nothing restarted. It is at6cd99ddb, one commit past the tag; that commit landed onmasterafter the tag was cut and is a docs commit. Its schema change was already applied and verified before this rollout, per the plan. It is the only host not at the tag exactly, and restarting it is the owner's deliberate last step.edge-pertento-bridge— skipped, not a failure. Listed in Deliberately skipped since 2026-08-23. Nothing was spent on it: no SSH attempt, no retry.- The five-language picker was NOT checked in a browser. The plan's "what to check" asks for the
profile settings picker to offer five languages and for a panel to be inspected in a non-English
locale. That is a UI check and I did not perform it. What I can say is narrower: every host serves the
tag's bundle and every host restarted
officerafterwards, so the fix is present in the code each host is running. Whether it renders is unconfirmed. - Minesweeper's absence was not checked.
/minesweeperwas not requested on any host, and the dock was not inspected. macbookproreports no plugins installed whilegen-plugin-schemasfinds three schema files on disk (atelier,kiosk,music). So that host has plugin schemas without registered plugins. This predates the release and nothing in the plan covers it, so I left it alone — but it explains why the atelier constraint churn cleared onalphaand not here, and it meansmacbookpro's plugins are not being updated by the deploy at all.plugins:updaterestarted sidecars on four hosts before the plan's own restart step, asdocs/servers.mdwarns. Counted per host above rather than left as "restarted: officer".
One note for docs/servers.md
The database URL key is not the same on every host. alpha has only POSTGRES_URL; fofos,
production-pertento-bridge, deadpool-rezio-bridge and macbookpro have only
OFFICERDEV_POSTGRES_URL. drizzle.config.ts reads OFFICERDEV_POSTGRES_URL ?? POSTGRES_URL, so both
work for the app — but a rollout that queries the database directly must follow the same precedence or
it verifies the wrong database and says "schema ✓" about it. This cost one failed step on fofos before
being caught, and I re-checked alpha afterwards to confirm it holds only the one key and that its
verification was therefore sound.
macbookpro also has no timeout(1). A remote command wrapping anything in timeout fails there with
command not found — and it fails silently in the sense that what you see is the next command's error,
not the missing binary's.