diff --git a/deploy/2026.08.23.05.report.md b/deploy/2026.08.23.05.report.md new file mode 100644 index 00000000..ba1563b4 --- /dev/null +++ b/deploy/2026.08.23.05.report.md @@ -0,0 +1,225 @@ +# 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: + +```json +[ + { "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-adds `pk_music_now_playing` on `music_now_playing`, with an + identical definition. +- **`macbookpro`** — the same `music_now_playing` churn, plus two `atelier_collection_items` foreign + 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 at `6cd99ddb`, one commit + *past* the tag; that commit landed on `master` after 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 `officer` afterwards, so the fix is present in the code each + host is running. Whether it renders is unconfirmed. +- **Minesweeper's absence was not checked.** `/minesweeper` was not requested on any host, and the dock + was not inspected. +- **`macbookpro` reports no plugins installed** while `gen-plugin-schemas` finds 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 on `alpha` and not here, and it means `macbookpro`'s plugins are not + being updated by the deploy at all. +- **`plugins:update` restarted sidecars on four hosts before the plan's own restart step**, as + `docs/servers.md` warns. 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.