Commit Graph
100 Commits
Author SHA1 Message Date
LukeGus c7fd900732 feat: merge host editor terminal tabs into one owned by ssh-terminal 2026-09-27 14:03:02 -05:00
LukeGus fff373d5bd chore: remove references to plugin sdk ARCHITECTURE.md 2026-09-27 14:02:40 -05:00
LukeGus 4ce551822b chore: untrack plugin sdk ARCHITECTURE.md 2026-09-27 14:00:49 -05:00
LukeGus bbeed088ad fix: compute beta changes across dev branches and move the beta tag 2026-09-27 01:12:39 -05:00
LukeGus 4897024324 fix: make link-store secret check immune to random base64 matches 2026-09-27 00:50:14 -05:00
LukeGus 25d11b1edb Merge remote-tracking branch 'origin/dev-2.9.0' into dev-2.9.0 2026-09-27 00:45:11 -05:00
LukeGus 50a263a8dc feat: add plugin sdk build to beta release 2026-09-27 00:45:04 -05:00
LukeGus 4423c4c8ef fix: keep plugins loaded after signing in from the login screen 2026-09-27 00:38:06 -05:00
LukeGus 8043d6dbdd chore: simplify plugin readmes, changelogs and manifest descriptions 2026-09-27 00:24:48 -05:00
LukeGus 26d52c7631 fix: keep rounded-full circular in production builds 2026-09-26 18:49:48 -05:00
LukeGus c38c2e84b8 fix: link every plugin workspace before npm ci in docker deps stage 2026-09-26 13:05:16 -05:00
LukeGus 2ca7a36dbc fix: link plugin-sdk workspace before npm ci in docker deps stage 2026-09-26 12:56:31 -05:00
LukeGus e14c0b32e0 fix: set blacksmith builder cache-key to stop broken gha cache fallback 2026-09-26 12:53:21 -05:00
LukeGus 6cd9a2846d feat: rebuild desktop sync as linked server accounts, fix packaged plugin bundles and UI scaling 2026-09-26 00:41:25 -05:00
LukeGus 7c02daccf4 feat: unify alerts into one plugin, channels, rules and inbox 2026-09-25 16:26:37 -05:00
LukeGus fbe736bc20 feat: tailscale add host and copy ip, fix outbound fetch hang and plugin ESM warning 2026-09-25 13:06:33 -05:00
LukeGus c21bca8cf0 feat: show credential sharing inline in the sidebar like host sharing 2026-09-25 12:03:41 -05:00
LukeGus 4a320a2258 feat: improve UI loading time and jitter 2026-09-25 11:33:24 -05:00
LukeGus 0f8956dcf3 fix: give bundled plugin backends a real require for CJS deps 2026-09-25 10:13:52 -05:00
LukeGus f779d6a08e test: prove 2.8 to 2.9.0 upgrade is lossless and fix what it caught 2026-09-25 09:58:45 -05:00
LukeGus 2ee9b3592c feat: add plugin packing, signing, pinned trust and tmxplug bundling 2026-09-25 09:21:28 -05:00
LukeGus c6a44b7ff3 fix: harden the plugin runtime after the 2.9.0 security review 2026-09-25 08:48:54 -05:00
LukeGus 2961297989 chore: lock the plugin boundary and remove 2.9.0 leftovers 2026-09-25 07:24:46 -05:00
LukeGus 6489b62ece fix: finish 2.9.0 plugin moves and get every check green 2026-09-24 23:35:18 -05:00
LukeGus 8c1e02af89 feat: move acme certificate automation into a plugin (C7) 2026-09-24 21:19:27 -05:00
LukeGus 4dbce08379 feat: move termix identity into a plugin (C6) 2026-09-24 20:50:54 -05:00
LukeGus 6e56c90aac feat: move vault ssh signing into a plugin (C5) 2026-09-24 20:24:09 -05:00
LukeGus b027717c46 feat: move step-ca into a plugin (C4) 2026-09-24 19:55:28 -05:00
LukeGus 98d367d7e2 feat: move opkssh and warpgate into plugins (C3) 2026-09-24 19:28:19 -05:00
LukeGus 925da4a661 feat: move sso and ldap logins into plugins (C2) 2026-09-24 18:23:20 -05:00
LukeGus 5c18435105 feat: move totp and passkeys into plugins (C1) 2026-09-24 16:57:24 -05:00
LukeGus f4f26a9b8b feat: convert secret-sources into a plugin (B20) 2026-09-24 16:20:20 -05:00
LukeGus 2ac7779eda feat: convert wake-on-lan into a plugin (B20) 2026-09-24 15:49:55 -05:00
LukeGus d4ec444558 feat: finish the homepage plugin, move service links and canvas out of core (B19) 2026-09-24 15:07:25 -05:00
LukeGus 21937a6b02 feat: finish the ai plugin (B18) 2026-09-24 13:43:26 -05:00
LukeGus 6b4d1432ab feat: finish the automations plugin (B17) 2026-09-24 13:05:44 -05:00
LukeGus 993a91c899 feat: finish the docker plugin (B15) 2026-09-24 11:58:20 -05:00
LukeGus 0a3f05d99d feat: finish the host-metrics plugin, move host status into core (B16) 2026-09-24 11:21:23 -05:00
LukeGus 14eb558b85 feat: finish the remote-desktop plugin (B14) 2026-09-24 01:02:45 -05:00
LukeGus 0af2c94983 feat: turn session recording into a plugin (B13) 2026-09-24 00:09:48 -05:00
LukeGus a276f6898c feat: move session sharing and collab rooms into a plugin (B12) 2026-09-23 23:42:46 -05:00
LukeGus 791d8656a1 feat: convert serial console into the serial plugin 2026-09-23 23:06:37 -05:00
LukeGus 708eedb861 feat: convert tmux monitoring into a plugin (B10) 2026-09-23 22:42:56 -05:00
LukeGus 79d77678c9 feat: move the terminal fully into the ssh-terminal plugin (B9) 2026-09-23 21:41:22 -05:00
LukeGus 535126fd1b feat: finish the web-endpoint plugin, add ctx.desktop (B8) 2026-09-23 18:36:41 -05:00
LukeGus 1682861853 feat: convert ssh tunnels into a plugin 2026-09-23 17:27:28 -05:00
LukeGus c85c1fdb86 feat: convert file manager into a plugin 2026-09-23 16:27:29 -05:00
LukeGus b76da9ab52 Merge remote-tracking branch 'origin/dev-2.9.0' into dev-2.9.0 2026-09-23 13:10:24 -05:00
LukeGus c381955ed0 feat: finish the fleets plugin, add ctx.hosts and host-commands SDK (B4) 2026-09-23 13:10:18 -05:00
LukeGus bf147096eb feat: drop proxmox host columns, use plugin settings instead 2026-09-23 13:06:43 -05:00
LukeGus 37c015a760 feat: move proxmox node stats and collectors into the proxmox plugin 2026-09-23 13:06:18 -05:00
LukeGus 218c5088e7 feat: add ctx.hosts create/update to the SDK, host-metrics drops proxmox 2026-09-23 13:06:06 -05:00
LukeGus f9283ec83f chore: regenerate drizzle migration journals for B5 2026-09-23 13:05:55 -05:00
LukeGus 115bc515e1 chore: update proxmox and host-metrics locale files for B5 2026-09-23 13:05:19 -05:00
LukeGus 3b2c849514 feat: finish the fleets plugin, add ctx.hosts and host-commands SDK (B4) 2026-09-23 11:24:16 -05:00
LukeGus d2ff5fc78f feat: finish the tailscale plugin, including SSH auth (B3) 2026-09-23 09:41:20 -05:00
LukeGus c77301577f feat: wire ai, automations, fleets and ssh-terminal to snippets (B2) 2026-09-23 08:59:24 -05:00
LukeGus 3656caf168 feat: add the snippets plugin (B2) 2026-09-23 08:59:16 -05:00
LukeGus 1eac0f54b0 feat: point core frontend snippets pickers at the plugin (B2) 2026-09-23 08:59:06 -05:00
LukeGus e07221eaf3 feat: move snippets backend and tables into a plugin (B2) 2026-09-23 08:58:53 -05:00
LukeGus fdedca39fd feat: convert network-topology to a full plugin (B1) 2026-09-23 07:36:39 -05:00
LukeGus 95abe24798 fix: gate second factors after SSO/LDAP behind an admin setting 2026-09-23 07:17:03 -05:00
LukeGus f217d8db89 feat: rebuild workspaces as the reference plugin 2026-09-23 07:04:03 -05:00
LukeGus d774df8b41 feat: add auth extension points and one ssh connect pipeline 2026-09-23 00:44:33 -05:00
LukeGus d3c209af13 fix: mock the ai status fetch in its activate test 2026-09-22 20:20:47 -05:00
LukeGus e88d5a52e3 feat: load plugin frontends at runtime and remove plugin ids from the shell 2026-09-22 20:15:52 -05:00
LukeGus 49f0286a14 feat: give plugins their own settings and one settings screen 2026-09-22 18:31:19 -05:00
LukeGus cc15559ea1 feat: namespace plugin permissions and keep them valid when a plugin is off 2026-09-22 17:30:00 -05:00
LukeGus 8431570ff7 feat: serve plugin http and websockets from one mount instead of ports 2026-09-22 16:39:41 -05:00
LukeGus c496a093ca feat: give plugins their own tables, migrations and sync entities 2026-09-22 15:49:54 -05:00
LukeGus 5796186a1c feat: make each plugin an npm workspace built by a termix-plugin CLI 2026-09-22 15:09:50 -05:00
LukeGus 4758016f41 feat: collapse plugin runtime to one tier behind a plugin SDK 2026-09-22 14:11:50 -05:00
LukeGus 6e058f6e9e feat: move web endpoint into a first-party plugin 2026-09-22 12:30:35 -05:00
LukeGus 6f0dff58a3 feat: move workspaces into a first-party plugin 2026-09-22 10:45:15 -05:00
LukeGus 8742c5d381 feat: move tailscale device discovery and settings into a plugin
Adds plugins/tailscale/ with a devices sidebar tab, admin settings
section, and re-auth dialog. Host Metrics tailscale manager card and
SSH re-auth banner parsing stay in core.
2026-09-22 10:45:15 -05:00
LukeGus 5fbd5fb7e2 feat: move network topology into a first-party plugin 2026-09-22 10:45:15 -05:00
LukeGus e372b0eda7 feat: remove legacy alert rules, superseded by automations
Alert rules already auto-migrate into automations on boot and the old
engine stands down after. Deletes the rule/firing tables, routes, UI,
and AI tools; keeps notification channels since automations still use
them. Also fixes automations' notify step, which still called the
deleted repository.
2026-09-22 10:45:12 -05:00
LukeGus e0f14f2ecf feat: move automations into a first-party plugin 2026-09-22 08:14:03 -05:00
LukeGus a6f6a0439c feat: move fleets into a first-party plugin 2026-09-21 20:44:00 -05:00
LukeGus 76b2e5739a feat: wire remote-desktop plugin into core and rename i18n keys
Repoints core consumers (dispatcher, collab, session-sharing, tab
utils) at the plugin, adds isTabTypeAvailable gating for rdp/vnc/
telnet, widens hostCapability to accept an array, and renames the
guacamole i18n namespace to remoteDesktop.
2026-09-21 20:26:09 -05:00
LukeGus c6bcfdb80d feat: move remote desktop (RDP/VNC/Telnet) into a first-party plugin
Relocates guacamole backend/frontend source and tests into
plugins/remote-desktop, following the ssh-terminal/docker pattern.
2026-09-21 20:25:52 -05:00
LukeGus d440ce9073 feat: move proxmox discovery/import/sync into a first-party plugin 2026-09-21 19:20:17 -05:00
LukeGus 9db66d5780 feat: add cross-plugin secret references gated by the provider's RBAC permission 2026-09-21 17:09:28 -05:00
LukeGus 2d6c1cdecb feat: add a permission-gated UI action registry and action slots for plugins
Moves the terminal toolbar's hardwired AI button into a slot the ssh-terminal
plugin offers and the ai plugin fills, gated on ai.services.use.
2026-09-21 16:56:15 -05:00
LukeGus 225f618337 feat: add a permission-gated backend service registry for plugins 2026-09-21 16:23:00 -05:00
LukeGus ee2d6b4697 fix: remove compiled plugin JS left behind in plugins/ after build
copy-bundled-plugins.cjs compiled and rewrote plugin backend TS in
place, copied it to dist/plugins, but never deleted the .js it had
just emitted next to the .ts sources. Those files shadowed the real
source for vitest/tsx and had import paths rewritten for the dist
layout, so tests failed with "Cannot find module" once a local build
had run. Affects docker, host-metrics and ai, not just this one.
2026-09-21 15:25:17 -05:00
LukeGus 504710b065 feat: ship the AI assistant as a first-party in-process plugin
Moves src/backend/ai and its routes into plugins/ai, mounted through a
small /ai dispatcher instead of its own port. Moves the ai-enabled and
ai-private-endpoints settings routes out of user-settings-routes.ts
into the plugin too, so it has no leftover core dependents.
2026-09-21 15:20:05 -05:00
LukeGus c58ccbfc3f fix: harden plugin auth and add per-request identity for ctx calls
Require auth on /plugin-api, gate plugin enable/grant/revoke routes
behind admin.plugins.manage, and thread the calling user through
worker ctx.hosts/ctx.ssh calls instead of always using the install
owner. Also adds the plugin permissions grant/revoke UI.
2026-09-21 14:32:59 -05:00
LukeGus 19b70430a1 feat: ship host metrics as a first-party in-process plugin 2026-09-21 11:30:46 -05:00
LukeGus a2479c19b0 feat: ship docker as a first-party in-process plugin
Moves docker backend and frontend into plugins/docker/, alongside
ssh-terminal. Adds a host editor tab seam, a dashboard card registry,
and a build step to compile plugin backends into dist.
2026-09-21 09:55:37 -05:00
LukeGus c94a453f1e feat: ship the ssh terminal as a first-party in-process plugin
Adds a hardcoded process:transport-owner tier so the terminal can own its
WebSocket server and ssh2 clients, which cannot cross the worker boundary.
2026-09-21 08:28:50 -05:00
LukeGus e040b12045 fix: update stale SFTP transfer test for single file destination paths
The test still asserted transferToHost was called with the destination
directory "/srv". Commit 7727fa09 (#1304) deliberately changed a single
file transfer to send the full destination path including the filename,
so the correct expectation is "/srv/remote-1.txt". The code was right
and the test was left behind.
2026-09-21 07:23:48 -05:00
LukeGus 4e1dec8435 feat: dispatch plugin HTTP routes and wire the runtime into startup
ctx.http.route now registers a real router on the /plugin-api/:pluginId
dispatcher, replacing its stub 404. A plugin never touches the Express
req/res: it gets a plain summary and returns a plain object, so sockets
and session cookies stay on this side of the boundary. Authorization and
cookie headers are not forwarded.

Plugins load last in the start-up sequence, after the server is fully
wired, and are terminated before the database on shutdown so none can
outlive it. A plugin that fails to load cannot stop the backend.

fix: correct the nginx plugin-api location regex

The pattern was ^/plugin-api/(/.*)?$, which needs a double slash and so
never matched /plugin-api/<id>/<route>. Every other block in the file
uses ^/prefix(/.*)?$. Left alone, plugin routes would work in dev and
404 only behind Docker.
2026-09-21 07:19:02 -05:00
LukeGus 4311a0e98a feat: add plugin ctx broker with permission gate and audit
Every ctx call a plugin makes is checked against its granted
capabilities, performed by the main thread, then audited. A capability
must be both declared in the manifest and granted in the database, so
widening a plugin's reach always needs a new manifest the user can see,
never just a database row.

Audit attribution is set by the broker, not the plugin. The plugin
supplies only the details, so it cannot forge the actor.

fix: stop plugin workers seeing plaintext credentials in error messages

A failing ctx.ssh.connect handed the worker the raw error from deep in
the SSH stack, which embeds the connect config. The worker received, in
full:

  Authentication failed for root using password <SECRET>

where <SECRET> was the host's real plaintext password. Any plugin with
ssh.exec could read it by catching the error, defeating the whole point
of the handle-based ssh API.

Errors crossing the boundary are now sanitised. Only PluginFacingError
and PluginPermissionError, both authored here, reach a plugin verbatim;
anything else becomes a generic message and the real one goes to the
log. This uses a marker class rather than matching on message text,
because matching would start leaking again the moment an upstream error
happened to contain a familiar phrase.

Covered by credential-isolation.test.ts, which plants a sentinel in
every secret-bearing field and asserts it appears in no message the
worker ever receives.
2026-09-21 07:19:01 -05:00
LukeGus 1393fa7581 feat: route internal events through a shared plugin event bus
Formalises three ad-hoc publish paths that already existed:
automation-events.ts, metrics/automation-bridge.ts and the
hostSessionStatus singleton, now the host.session.status topic.

Both invariants the old code relied on are preserved. Publishing stays
fire-and-forget, so a failing subscriber cannot disturb a metrics poll or
a host delete. The automations engine subscribes to the bus at scheduler
start instead of being imported ad hoc, which keeps the edge
one-directional: automations may import repositories, hosts modules must
not import automations.
2026-09-21 07:19:01 -05:00
LukeGus 0a771c9600 feat: add plugin loader with manifest validation and crash restart
Validates an unpacked plugin, spawns a worker_threads worker and manages
activate/deactivate/crash-restart with backoff, disabling after three
tries.

The crash counter clears only after a plugin stays up past a stability
window, not on activation. Clearing it on activation let a plugin that
activates cleanly and then dies restart forever, because every attempt
looked like the first.

loader.ts documents what the worker boundary does and does not buy you.
Node's permission model is process-wide, not per-worker, so it cannot be
enabled for plugin workers alone and is not claimed here.
2026-09-21 07:19:01 -05:00
LukeGus 9f4a2d3951 feat: add allowlisted host view for plugins
An allowlist rather than a list of fields to strip. A blocklist rots:
the moment a new secret-bearing column lands on SSHHost it starts
leaking silently. With an allowlist a new field stays invisible to
plugins until someone adds it here on purpose.
2026-09-21 07:19:01 -05:00
LukeGus 248698f62d feat: add plugin worker protocol, bootstrap and plugin_storage table
Worker-side ctx proxy plus the message envelope it talks over, and the
per-plugin key/value table behind ctx.storage with migrations for all
three dialects. Rows cascade with the plugin so uninstalling leaves
nothing behind.
2026-09-21 07:19:01 -05:00
LukeGus 7f1beddccc feat: add category and icon fields to plugin manifest schema 2026-09-20 21:06:16 -05:00
LukeGus 5a76d30637 chore: increment ver 2026-09-20 21:00:38 -05:00