diff --git a/deploy/2026.08.30.01.md b/deploy/2026.08.30.01.md new file mode 100644 index 00000000..0f42d289 --- /dev/null +++ b/deploy/2026.08.30.01.md @@ -0,0 +1,99 @@ +# 2026.08.30.01 — the file browser's clipboard moves to the server, and plugins reach further in + +**No schema change and no dependency change.** Verified rather than assumed: + +```bash +git diff --name-only deploy/2026.08.29.04..deploy/2026.08.30.01 | grep -iE 'schema|/db/|databases' # nothing +git diff --name-only deploy/2026.08.29.04..deploy/2026.08.30.01 -- package.json bun.lock # nothing +``` + +So **no `bun db:push` and no `bun install` step exists in this plan, and neither should be improvised.** +Eleven commits; one of them is the previous release's report. + +The clipboard is per-user state and it needs no migration — it is a key in `user_state`, a JSONB column +that already exists, written by the same `PATCH /user/state` the dock and the view mode already use. + +## What is in it + +- **The file browser's clipboard lives on the server.** It was `useState`, so it existed in one tab and + died with it: copying in one window and pasting in another did nothing, and a reload lost a pending cut + with no sign that it had. It is now a key in `user_state`, per user rather than per browser — cutting on + a desktop and pasting on a phone is one gesture across two screens. +- **Files can be dragged between windows.** A custom MIME type on the DataTransfer survives between tabs + and windows of the same browser, so a row can be dragged from one Officer window into a folder in + another. It cannot cross different browsers or exchange with Finder; that is a property of the platform, + not a gap to report. +- **A window re-reads its folder and the clipboard when it comes forward**, so the window a file was cut + from stops listing it. And **re-reading no longer blanks the list** — the spinner is now for a folder + that cannot yet be shown, so a refresh after a paste or a delete leaves the rows and the scroll position + where they were. +- **A plugin can put an action in the file browser's context menu**, and gets an authenticated client to + use in it. Three commits, because the first two shipped the registration without forwarding it into the + menu, and then without a way to call the API. +- **The file browser can be a file picker** — `onPickFile` turns opening a file into handing it back, + rather than a second component that reimplements a listing, a breadcrumb and a sort. +- **A plugin can hand the agent its own MCP server**, declared in its manifest. +- **A plugin may not bring its own React.** `npmDependencies` strips and then deletes `react` and + `react-dom` after install: a plugin's peer copy landing in `plugins/node_modules` gives the app two + Reacts and every hook throws. + +## Nothing here changes behaviour anyone has to be warned about + +No route is removed, no permission changes, nothing 404s that did not before. The clipboard is additive: +a browser that has never set one reads `null` and behaves exactly as before. + +## Every host — the commands + +The standard steps in `prompts/deploy-commander.md` are the whole rollout (dirty check, +`git fetch origin --tags`, `git merge --ff-only deploy/2026.08.30.01`, `bun run plugins:update`), plus: + +```bash +pm2 restart officer +``` + +`officer` only — `plugins:update` has already restarted the plugin sidecars. + +### Verify it came back + +`pm2 jlist`: `officer` online and `restart_time` moved, then `/api/health` on the host's own port +(9010 on `macbookpro` and `production-pertento-bridge`, 9000 elsewhere). `200` or `401` are healthy. + +### And check the file browser still lists + +This release touched the file browser heavily — the listing loader, the clipboard and the row markup — +so one call per host: + +```bash +bun -e " +const { sign } = await import('./src/servers/jwt'); +const t = await sign({ id: 1, email: '' }, '2m'); +const r = await fetch('http://127.0.0.1:/api/file-browser/ls?root=home&path=/', { headers: { Authorization: 'Bearer ' + t } }); +const b = await r.json(); console.log(r.status, (b.entries ?? []).length + ' entries'); +process.exit(0)" +``` + +A `200` with a plausible count. **A 500 here is a failed host** — report it and move on. + +## Per host + +Surveyed 2026-08-30 while writing this. Every host answered, and every one is clean +(`--untracked-files=no`). + +| Host | HEAD at survey | Note | +| --- | --- | --- | +| `officer-dev` | — | **SKIP ENTIRELY.** The rollout runs here and it is already at this code. Name it as skipped. | +| `alpha` | `e9b71522` | Exactly on the previous tag. Ordinary target. | +| `fofos` | `601849be` | **Ahead of the previous tag, behind this one.** It has been hand-pulled all day while the fofos plugin work was written against it. That commit is an ancestor of this tag, so the fast-forward is ordinary — it simply travels fewer commits. It is also the only host with `av-club` and `fofos-admin` installed, so `plugins:update` moves more here than anywhere else. | +| `macbookpro` | `e9b71522` | macOS, port **9010**, a laptop. Answered the survey; if it has slept since, unreachable is a SKIP with a note, not a failure. | +| `macbruno` | `e9b71522` | macOS, login **`brunoalcadapadezmonteirodaconceicao`**. | +| `production-pertento-bridge` | `e9b71522` | Port **9010**. | +| `edge-pertento-bridge` | `e9b71522` | Ordinary target. | +| `deadpool-rezio-bridge` | `e9b71522` | Login **`br`**, checkout `/home/br/officerdev/platform`. | + +## What "done" looks like + +Per host: HEAD before and after, `plugins:update` result, `officer` back online with a moved +`restart_time`, and the `ls` check's output. + +Nothing in this release needs a database query, a backup or an install. If you find yourself running one, +stop — the plan is wrong, and that is worth reporting rather than working around. diff --git a/package.json b/package.json index 3d5fb0a4..9f3f7ff5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "officer", - "version": "2026.08.29.04", + "version": "2026.08.30.01", "private": true, "type": "module", "workspaces": [