Files
platform/TODO.md
T
pastilhasandClaude Opus 4.8 3fc7bcb32f always run pi as the service user, drop the sudo -u branch
- the sandbox already drops privileges to the OS user (id -un), so pi-bridge was
  the only code path that switched to a per-user unix account
- the four accounts it targeted (andrepadez, john-wick, fedra, miguelbenoliel)
  are vestigial: created by scripts/provision-existing-users.sh, with no home
  dirs, no files, no processes. the only live account is pastilhas@officer.dev,
  which maps to the service user, so isServiceUser was always true and the
  sudo -u branch could never fire
- add TODO.md tracking the leftover username plumbing, the useradd script, known
  bugs (task-executor relative cwd, bootstrap pi EEXIST), and the ufw 9010 rule

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 21:57:49 +00:00

3.2 KiB

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 sendAndAwaitspawnOptions, 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.tsgenerateClaudeSettings) 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.