# TODO Deferred work. Context: Officer is collapsing from multi-tenant / open-source-ready to a **single-user platform**. Treat multi-tenant indirection as accidental complexity, not a requirement. ## Single-user cleanup - [ ] **Remove dead `username` plumbing.** `pi-bridge.spawnPi` no longer uses `username` — it always runs as the service user. But the handlers still compute `toShellUsername(...)` and thread it through `sendAndAwait` → `spawnOptions`, where nothing reads it. `send-claude-code` declares `username` (lines 8, 36) without using it. Typechecks clean today (excess-property checks don't fire on variables), so it silently *looks* load-bearing. Touches: `channels/{whatsapp,telegram,discord}/handler.ts`, `channels/send-and-await.ts`, `channels/send-claude-code.ts`. After this, `toShellUsername` has one caller left (`provision.ts` → `generateClaudeSettings`) and may be inlinable. - [ ] **Delete or gut `scripts/provision-existing-users.sh`.** Line ~100 runs `sudo useradd -d "$HOME_DIR" -s /bin/zsh -M "$shell_user"`. This is what created the four vestigial Unix accounts (`andrepadez`, `john-wick`, `fedra`, `miguelbenoliel`) that cluttered the lightdm greeter. Nothing in the server creates Unix users; if this script runs again they come back. - [ ] **Collapse the rest of the multi-tenant machinery.** Candidates, in rough order of payoff: roles (`Super Admin`/`Member`), the sandboxed-vs-unsandboxed path split, per-email home dirs under `dev-data/{email}/home`, per-user server state (dock, user apps, AppRegistry keyed by email), and auth (passkeys-per-origin, JWT signin, unmounted `PasskeyGate`). ## Known bugs - [ ] **Convert Audio task fails with `ENOENT: posix_spawn 'bash'`.** Misleading error — the real cause is a *relative* `cwd` passed to `Bun.spawn` (ENOENT fires when the child's cwd doesn't exist, not when the binary is missing). Fix is in `api/tasks/task-executor.ts`: resolve `msg.cwd` against the user's home when it isn't absolute (`isAbsolute(msg.cwd) ? msg.cwd : join(homeDir, msg.cwd)`). Was written and verified once, then discarded in a working-tree cleanup. - [ ] **`bootstrap.ts` runs `npm install -g` for Pi on every boot.** `findPiPackageDir` checks stale paths and an outdated package name, so `installPi` always fires and floods the logs with `EEXIST` noise. Should detect `@earendil-works/pi-coding-agent` at the real npm prefix. ## Infra (alpha) - [ ] **`ufw` blocks port 9010 on the LAN.** Default deny incoming; only `22/tcp`, `80/tcp`, `443/tcp`, and everything on `tailscale0` are allowed — so `http://192.168.47.196:9010` is unreachable from the LAN while localhost and Tailscale work. Fix: `sudo ufw allow from 192.168.47.0/24 to any port 9010 proto tcp` ## Backburner - [ ] **Music tagging feature** (`/music`, Mp3tag-inspired). v1 was scoped as a two-panel workspace — file browser left, table right, single "Load" context-menu item flattening audio files into the table. Discarded before completion; would need `GET /file-browser/flatten-audio`, a `useFilesAPI.flattenAudio` method, and the Music app panel rebuilt from scratch.