# 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.