Commit Graph
3 Commits
Author SHA1 Message Date
pastilhasandClaude Opus 5 d6f093532d install radicale and register officer-caldav on an existing server's next boot
Calendar and contacts became core in 9c309c5a. A FRESH install gets radicale
from machine-setup and officer-caldav from CORE_PROCESSES; an existing one gets
neither from a git pull, because a pull changes nothing outside the repository.
So without this, pulling that commit leaves /calendar mounted, rendering, and
talking to nothing — the silent half-working failure this codebase keeps
getting bitten by, and the same shape as the plugin permission collision fixed
in ee321f49.

Best-effort and AFTER serve(), never blocking: a held apt lock, an unreachable
mirror or a machine without passwordless sudo must not stop Officer starting.
Uses the existing os-deps machinery rather than a second spelling of "install a
package" — including `sudo -n`, which fails fast instead of hanging on a prompt
no one can answer under PM2. When it cannot install, it logs the exact command
to run by hand.

addCoreProcess is new and deliberately narrow. The platform normally never
writes a core entry — it does not know the core list, and duplicating
CORE_PROCESSES here would be a second copy to drift. The exception is exactly
this: a commit that MOVES something into the core set, which an existing
install has no other way to learn about.

Verified on this machine rather than assumed: radicale was absent, the guard
installed it (3.1.8), and a second run reported `present` and wrote nothing.
The install path is not unit-tested on purpose — a test that really ran
apt-get would modify the machine running it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 04:28:17 +00:00
pastilhasandClaude Opus 5 7b7d8bbf36 add gen:ecosystem script to rebuild ecosystem.config.cjs from the database
bun gen:ecosystem writes the whole file from three sources: CORE_PROCESSES read
directly out of scripts/setup/officer-setup/lib/services.sh (shelled out to bash,
so there is exactly one list rather than a TS copy to keep in sync by hand),
marketplace plugins that are installed AND enabled in Postgres and actually ship a
sidecar/, and app-store services that are installed AND enabled, using each
catalogue entry's `process` name against the src/servers/sidecar/<id>/index.ts
convention.

Extracted `pluginPm2Entry` (a pure DiscoveredPlugin -> Pm2App) out of
addPluginToEcosystem so the live install/uninstall path and this from-scratch
rebuild share one definition of what a plugin's entry looks like, rather than two
that can drift apart. addPluginToEcosystem's own behavior is unchanged.

Complements, not replaces, the existing incremental add/remove in
servers/plugins/ecosystem.ts — that edits the live file at install time; this
regenerates the whole thing, for a fresh clone, drift, or restoring from a backup.

Found while testing against this machine's real file, worth flagging rather than
silently working around: officer-marketplace (the marketplace.officer.dev process,
src/servers/marketplace/server.tsx) is in this machine's ecosystem.config.cjs by
hand and is modeled by neither the plugin system nor the app-store catalogue, so
this script does not know about it and would drop its entry on a real run. Left
alone rather than guessed at.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 09:23:25 +00:00
pastilhasandClaude Opus 5 2634df7a04 the install runner: ecosystem entry, sidecar, row, mounts
closes the hole app-store/pm2.ts has carried since 2026-08-13 — "installing a
plugin has to append its entry here before starting it, that is the plugin
system's job and it is not built". this is that job, and it is why nothing in
the app-store catalogue installs end to end either.

verified against a running server with a sidecar in the tree:

  install    ecosystem added · sidecar started · recorded · mounted /example
             route 200, pm2 online
  disable    sidecar stopped · unmounted
             route 404, pm2 stopped
  enable     sidecar started · mounted
             route 200, pm2 online
  uninstall  record removed · unmounted · sidecar stopped, deleted, entry gone
             route 404, not in pm2, tables untouched

afterwards ecosystem.config.cjs is byte-identical to before, pm2 holds the same
five core apps, and plugin_installs is back to zero rows.

the ecosystem file is edited rather than regenerated: the core entries come from
officer-setup's shell array, so the platform does not know that list and a copy
here would be a second thing to drift. the header above module.exports is
preserved verbatim too — officer-setup's explains that bun auto-loads .env from
the working directory and that data-path derives the install root from its
PARENT, so a wrong cwd relocates the whole install rather than failing. losing
that to a plugin install would be a poor trade.

order is the design. bringing up goes outside-in, taking down goes inside-out,
so the worst intermediate state is "recorded but not running" — visible, and
fixed by a retry — never "running but forgotten", which nothing can see.

each verb returns what it actually did, in order, and the detail panel shows it.
an install that mounted routes but could not start a sidecar is a different
outcome from one that worked, and a spinner that stops cannot say which.

the schema push is still deliberately not wired, and the reason is now in the
code: db:push DROPS tables absent from the schema it is given, so an uninstall
that regenerated the barrel would delete a plugin's data as a side effect of
stopping it. offscale does not need it — headscale_servers already ships in the
platform schema.

720 pass, same 10 pre-existing failures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 21:38:21 +00:00