it was the only sidecar living outside src/servers/sidecar/ — it sat in
api/terminal/ next to the bridge that talks to it, which is the one place a reader
looking for "the sidecars" would not check. now src/servers/sidecar/pty/index.mjs,
matching every peer, with a note on the pm2 entry about why this one is node and
.mjs (node-pty is a native addon) rather than bun and typescript like the rest.
the templates/ directory went to api/users/, next to provision.ts:seedShellConfigs,
which is now its only consumer — the sidecar's duplicate seeder went with the
sandbox branch in the previous commit. api/terminal/ is left holding exactly one
thing: the websocket bridge.
no behaviour change. the pm2 entry's script path changed, so `pm2 restart
officer-pty` is not enough — pm2 remembers the old path until the entry is deleted
and started again. commands are in SIDECAR_WORK_LOG.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Officer is single-user: the server owner is the only account, created once by
/auth/bootstrap. Everything that existed to serve additional users was
unreachable, so it is gone rather than left looking like it does something.
Accounts: drop the invite / resend-invite / delete / list-users routes and the
Users settings screen, the inert /auth/signup handler, and the account
verification chain it fed (verify, resend-verification, VerifyScreen, the
UserInvite + VerifyAdmin + VerifyRegistration templates). /auth/verify-token
survives for password resets only, and now requires a reset-password token
rather than accepting any signed JWT.
Roles: drop the users.role column and the four-value USER_ROLES enum. The
permissions table granted every role identical methods, and every
role === 'Super Admin' check was permanently true. The JWT no longer carries a
role claim.
Sandbox: remove sidecar/sandbox.ts and its five call sites. bwrap was selected
only for non-Super-Admin users, so it never ran. It was also not a usable agent
jail as written — --share-net, the project root (with .env) bound read-only,
and runuser dropping to the server's own uid. Rebuilding it for agent
containment would be a different construction, and git history keeps this one.
getHomeDir keeps its DATA_PATH meaning; the new getOwnerHomeDir resolves the
owner's real login home, which is what terminals, chats and task runs use.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Remove the multi-user provisioning leftovers (the provision-existing-users.sh
migration was already deleted in the prior commit):
- gut provisionVncEnv from provision.ts (per-user startxfce4 virtual desktop, dead
since the switch to mirroring :0 — vnc-manager.ts self-provisions its own passwd)
- drop the Pi `.pi/agent/sessions` seed and the now-orphaned `run` helper
Wire provisioning into bootstrapHandler: the super admin (first user) is created via
createUser, which never called provisionUserEnvironment — only the invite/verify flow
did. So the single user's DATA_PATH/<email> was never provisioned up front. Now it is.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
replaces the single hardcoded systemd VNC service with a dynamic
sidecar that manages per-user VNC sessions on demand. any authenticated
user can now access their own desktop, not just Super Admin.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- chown user dirs to pastilhas:<username> instead of pastilhas:officerdev
so users cannot access each other's data
- chmod 2770 (setgid) gives only the owning user terminal access
- setup.sh: ensure home dir is traversable (o+x) for provisioned users
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- provision linux users with pastilhas:officerdev ownership so server
can always read/write, terminal users get group access
- add officerdev shared group setup to setup.sh
- move go install to ~/.local/go with GOPATH at ~/.local/go-path
- add upload file/folder items to file browser context menu
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
770 (rwxrwx---) is more secure - only owner and group can access, excluding 'others'.
The service user can still access because it's added to the user's group via:
usermod -aG shellUsername serviceUser
The real fix was wrapping chmodSync in try/catch in email-db.ts so it doesn't
crash when trying to chmod files owned by other users.
Issues:
1. User directories created with chmod 770 (too restrictive)
- Prevents service user from reading/writing even though in group
- Changed to chmod 775 (recursive) to allow group access
2. openEmailDb tries to chmod file it may not own
- If file owned by different user (e.g., andrepadez), chmod fails
- Wrapped chmodSync in try/catch to gracefully skip
Changes:
- src/servers/api/users/provision.ts:
* Changed chmod 770 → 775 (owner/group rwx, others rx)
* Applied recursively to all subdirectories
* Added chmod after seeding files to ensure consistency
- src/servers/api/email/email-db.ts:
* Wrapped chmodSync in try/catch
* Logs silently skip if file not owned by current process
* Database still works even if chmod fails
Fixes /email endpoint 500 errors for users with email data.
- Added detailed error logging to detect snap node compatibility issues
- When Pi process exits with code 1, log helpful diagnostic info including node path
- Add hint to check for snap node and reinstall via apt/nvm
- Create SNAP_NODE_COMPATIBILITY.md with full troubleshooting guide
- Document root cause: snap node has file descriptor incompatibility with Bun.spawn stdin pipes
- Provide clear installation instructions for NodeSource and nvm alternatives