diff --git a/deploy/2026.08.25.01.md b/deploy/2026.08.25.01.md new file mode 100644 index 00000000..1d460631 --- /dev/null +++ b/deploy/2026.08.25.01.md @@ -0,0 +1,124 @@ +# 2026.08.25.01 + +Commanders become usable, agents get a credential that can be bounded, and a nudge finally arrives. + +96 commits — the largest release so far, and most of it is one night's work on commanders driven by +watching real setup runs. + +**One schema change**, additive and safe. **No dependency change** — `bun.lock` is untouched. +**Do not run `bun install`.** + +**`edge-pertento-bridge` is NOT a target for this release.** It needs a schema step no other host does. +See "Edge is excluded, and why" — this is the important part of this plan. + +## What is in it + +- **Commanders.** The template a new commander is created with was rewritten across the night: it asks + one question per turn in the owner's own language, proves its action on a single item before arming, + writes its own `CLASSIFICATION.md` and `DISPATCHING.md` rather than editing the platform's file, and + records per step in its ledger. The Stop control works, a deleted commander stays deleted, and its + children no longer appear in `/chat`. +- **Every agent session gets a key, scoped to `notify`.** A chat can send you a notification through + the platform instead of having no sanctioned way to reach you. It is minted per session and revoked + with it. +- **Credential narrowing** — `api_keys.permissions` (an allow list) and `api_keys.excluded_kinds` + (resolved against the live registry). Applied **before** the owner bypass, which makes it the only + thing that can bound a Super Admin — the case that matters, because a commander holds the owner's + identity unattended for months. This is the schema change. +- **`notify` moved from `app` to `core`.** It was grantable, nothing granted it, and every Member's app + was silently 403'd registering its own push token. On the bridges that is four accounts. +- **The loopback notify door is closed.** `/_officer/` paths now require a producer secret the sidecar + issues at registration. It previously accepted any caller that set a header. +- **Sidecar proxy timeouts are OFF.** `TIMEOUTS_ON = false` in `create-proxy.ts`, one line to reverse. + Bun's `server.timeout()` stores one byte, so declaring 1800 seconds gave a _shorter_ timeout than + declaring nothing. More permissive than what these hosts run today — a long transcription or a film + no longer gets cut. +- **A nudge always arrives.** Three refusals removed from the nudger. Read that commit before judging + it: the old guards meant no nudge could ever fire on a machine running commanders, silently. +- **Plugin tasks appear in the file browser**, and a direct task run is direct — no modal, no job row. +- **`/todos`**, a kanban board over the repo's own `todo/` tree, owner-only. +- **Two editor fixes** — one buffer per file across panels, and the model picker reading the right id. + +## The schema change + +Two nullable columns on `api_keys`: + +``` +permissions text[] null +excluded_kinds text[] null +``` + +Both null means unnarrowed, which is what every existing key is — including the mobile apps'. **No +existing credential changes behaviour.** Nothing is dropped and nothing is rewritten. + +`bun db:push` applies it. **Do not take the exit code as the answer** — drizzle-kit can print an error +and still exit 0. Verify on each host, against that host's own database: + +```sql +select column_name from information_schema.columns + where table_name = 'api_keys' and column_name in ('permissions','excluded_kinds'); +``` + +Two rows, or the host is not done. `permissions` alone is a half-applied push — stop and report it. + +## Every host except edge + +1. `git fetch origin --tags` then `git merge --ff-only deploy/2026.08.25.01` +2. `bun db:push` — then **run the query above**. Two rows. +3. `bun run plugins:update` +4. `pm2 restart officer` + +`officer` only at step 4. Step 3 restarts each plugin's own sidecar, which belongs in the report. + +**`macbookpro`:** append `/opt/homebrew/bin` to PATH for the `bun` commands, run `pm2` separately. It is +a laptop and may be asleep — unreachable is a skip with a note, not a failure. + +## Edge is excluded, and why + +`edge-pertento-bridge` came back on 2026-08-24 at `deploy/2026.08.22.02`, **288 commits behind**. It is +a deploy target again and its row is in `docs/servers.md`, but it must not be rolled out with the rest, +and the reason was verified on the host rather than inferred: + +- **It has no `roles` table.** `to_regclass('roles')` is null. +- **Its two accounts hold `Super Admin` and `Developer`.** + +Current schema makes `users.role` a foreign key onto `roles.name`. Every other host got `roles` created +and seeded by `2026.08.23.04`, then the foreign key added by `2026.08.23.05` — two releases, in order, +against an already-populated table. Edge would do both in one `db:push`, and the seeder runs from +`postdb:push`, which is **after** the push completes. So the constraint would be created against an +empty `roles` while `users.role` holds two values that are not in it. + +That fails. Worse, it can fail and still exit 0, leaving the schema half-applied — which is exactly the +warning `2026.08.23.05` carried. + +**It also missed two plans with one-off steps** that a single fast-forward does not replay: +`2026.08.23.05`'s pre-flight SQL, and `2026.08.23.06`'s orphan-affordance cleanup. + +So: **name edge as skipped, do not attempt it, and do not report it as a failure.** Bringing it forward +is a watched, by-hand operation — push, seed, push again, verify the constraint — and it is being done +separately by the owner and this session, immediately after this rollout. + +**One more thing about edge, for whoever reaches it later:** from `officer-dev` the name +`edge-pertento-bridge` does not resolve. It answers on **`100.64.0.15`**. `docs/servers.md` has the +address; use it. + +## What to check, this release + +**A commander can be created and asks its first question in your language.** That is the release, and +it is the thing most likely to reveal a stale bundle — hard refresh before deciding anything failed. + +**A Member's phone can register for notifications.** `notify` is core now, so an account that was +403'ing should simply work. + +**Nothing else should have changed for an ordinary signed-in owner.** Every narrowing column is null on +every existing key. + +No direct SQL is needed on any host in this release, and none is authorised. The query in "The schema +change" is a read. + +## Hosts + +- **`officer-dev`** — skip it. Restarting `officer` there ends the rollout. It is already on this code. +- **`edge-pertento-bridge`** — skipped, see above. Not a failure. +- **`alpha`**, **`fofos`**, **`production-pertento-bridge`**, **`deadpool-rezio-bridge`** — the targets. +- **`macbookpro`** — a target if it is awake. diff --git a/package.json b/package.json index aa154611..9590bf06 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "officer", - "version": "2026.08.24.02", + "version": "2026.08.25.01", "private": true, "type": "module", "workspaces": [