Commit Graph
737 Commits
Author SHA1 Message Date
Juan DenisandClaude Opus 4.8 dfc628e13b redesign(fleet): render fleet tables with sk-dtable
Agent Fleet and Fleet Monitor used the generic .table style while every other migrated list page uses the dense .sk-dtable look (mono uppercase headers, token row borders). Swap the className so they match their siblings under the Servers tab group.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 02:43:43 -04:00
Juan DenisandClaude Fable 5 b2fad9528a docs: clarify agent.key + session-token notes; record audit remediation (L2/L4-L7)
- SECURITY.md: spell out that agent.key encryption is off-host/tamper
  protection, not confidentiality against local root; 0600 perms are the real
  control (L2).
- agent_registry.py: reword the per-message session-token "TODO" to an accepted
  limitation (defence-in-depth, not a bug) (L7).
- AGENT_AUDIT.md: record H1/H2/H3 and L1-L7 status, with L4 (cap OR-merge),
  L5 (single-worker), L6 (windows .bat) noted as accepted by-design/documented.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:35:52 -04:00
Juan DenisandClaude Fable 5 df67ce782b fix(ui): remove dead agent-version management buttons (audit L3)
The Agent Versions tab rendered an "Add Version" button and per-row Edit/Delete
buttons with no handlers — there are no edit/delete endpoints. Remove the dead
controls (and now-unused Plus/Trash2 imports); the version list is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:35:43 -04:00
Juan DenisandClaude Fable 5 75db466096 fix(pairing): require developer role for claim/lookup (audit L1)
Pairing /claim creates a fleet server and /lookup reveals a pending agent's
details; both were @jwt_required() only, so any authenticated user (incl. a
read-only viewer) could use them. Gate both with @developer_required to match
POST /servers. Test: viewer 403, developer clears the gate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:35:43 -04:00
Juan DenisandClaude Fable 5 a34064d15a fix(plugins): make plugin/template features fail honestly, not silently (audit H2)
agent_plugin_service and server_template_service dispatched agent commands
through get_agent_gateway() — a function that does not exist — inside a bare
try/except. Every call raised ImportError, was swallowed, and left DB rows stuck
in 'installing'/'checking'/'remediating' forever while the UI implied the
feature worked. The agent also has no handlers for these commands.

- Plugin install now reports STATUS_ERROR with "Agent-side plugin support is not
  implemented yet" instead of hanging in 'installing'.
- Template drift-check/remediate report 'unknown' + an explanatory
  drift_report.error.
- Local-only ops (disable, uninstall, configure) just drop the dead dispatch.
- test_agent_features_honest.py: 3 tests asserting honest states.

Implementing the feature for real (agent handlers + sandbox) remains future
work; this stops it from lying in the meantime.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:35:35 -04:00
Juan DenisandClaude Fable 5 db4b403a59 fix(agent): fail-closed checksum verification in the self-updater (audit H1)
The updater could install an unverified binary three ways: it skipped
verification when no checksums URL was given, returned success when no checksum
line matched the platform, and ignored the HTTP status of the checksums fetch
(a 404 body parsed to an empty map → skipped). Since the updater runs as the
agent process (root on packaged installs), that was a code-execution primitive
that bypassed every feature gate.

- Refuse to install without a checksums URL.
- Extract a pure, fail-closed matchChecksum: empty/unparseable body, no entry
  for this GOOS/GOARCH, or a mismatch all error (was a silent skip).
- Check the checksums fetch HTTP status.
- requireSecureURL rejects non-HTTPS update/checksum URLs (dev override via
  SERVERKIT_INSECURE_TLS).
- updater_test.go: 6 tests covering match/mismatch/no-entry/empty/case/https.

Cryptographic release signing remains the recommended next layer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:35:27 -04:00
Juan DenisandClaude Fable 5 089b75526e fix(agent): accept registration token from env to keep it out of argv (M5)
The installers ran `serverkit-agent register --token <token>`, putting the
registration token in the process argument list — world-readable via `ps` /
/proc/<pid>/cmdline while register runs. The documented curl|bash one-liner also
landed the token in shell history.

- register now falls back to SERVERKIT_REGISTRATION_TOKEN /
  SERVERKIT_CONNECTION_STRING / SERVERKIT_SERVER_URL when the flags are absent
  (a process's environment is readable only by its owner and root).
- install.sh passes the token via env (drops the old `eval`) and accepts it from
  the environment so it need not appear on the curl line.
- install.ps1 passes the token to the child via env, and makes -Token optional
  with the same env fallback.

Verified: agent reads the env token at runtime (register proceeds past flag
validation to the network call); install.sh `bash -n` and install.ps1 parser
both clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 17:52:59 -04:00
Juan DenisandClaude Fable 5 6eb4471829 fix(servers): require developer role for agent self-update (audit H3)
POST /<id>/agent/update was @jwt_required() only, so a read-only viewer could
trigger agent binary replacement + service restart across the whole fleet —
inconsistent with every other state-changing server route, which is
@developer_required. Add @developer_required and a test proving a viewer gets
403 while a developer clears the gate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 17:33:29 -04:00
Juan DenisandClaude Fable 5 0bc30b62ef ci: run agent Go checks and backend pytest on push/PR (addresses audit M4)
Nothing ran the agent's tests or the backend suite automatically, so breakage
was only found by hand. Add two workflows:

- agent-ci.yml: go vet + go test on linux, plus a cross-compile build matrix
  (linux amd64/arm64, windows amd64) to catch platform-specific breakage at
  PR time. darwin is excluded — fyne.io/systray needs the macOS Cocoa toolchain
  and can't cross-compile from Linux (it's built on a mac at release time).
- backend-ci.yml: install requirements and run the full pytest suite, including
  the new end-to-end agent command-loop test.

Verified locally: go vet clean, all three cross-builds succeed, agent unit
tests and the full backend suite (136 passed) are green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 17:31:26 -04:00
Juan DenisandClaude Fable 5 43fc900944 test(agent): end-to-end test for the panel<->agent command loop
The agent subsystem had unit tests but nothing proving the whole protocol
works. This drives the REST poll transport (/connect, /poll, /result) — plain
HTTP that shares the WebSocket gateway's auth, registry, and command-routing
code — through the full loop: a correctly-signed agent authenticates, registers,
receives a command the panel issued via send_command (run on a background
thread since it blocks on the result), and round-trips the result back to the
waiter. Uses a temp-file SQLite DB so the thread and request handlers share
committed rows. 4 tests, all green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 17:31:26 -04:00
Juan DenisandClaude Fable 5 b57e436432 docs: add agent subsystem security & completeness audit
Severity-ranked, file:line-referenced audit of the agent fleet (Go agent,
gateway/registry/long-poll, pairing, panel→agent APIs, install/packaging, UI,
docs/CI) plus a remediation-status section recording the M1/M2/M3 fixes and the
M2 correction (compose allowlisting was already enforced at the handler layer).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 01:34:02 -04:00
Juan DenisandClaude Fable 5 315d443305 fix(agent): run packaged DEB/RPM agent as an unprivileged service account
The packaged systemd units ran the agent as User=root with a self-contradictory
ProtectSystem=strict, while the script installer (install.sh) runs a dedicated,
hardened serverkit-agent account. Align the packages with install.sh:

- User/Group=serverkit-agent; NoNewPrivileges=yes, ProtectSystem=strict,
  ProtectHome=yes, PrivateTmp=yes, ReadWritePaths for config/log/data.
- Create the account (deb postinst / rpm %pre), add it to the docker group,
  create+chown the data dirs, and re-chown the config dir on (re)install so an
  existing root-owned agent.key becomes readable after upgrade.
- ExecStartPre=+chown fixes credential ownership at start regardless of how the
  operator ran `register`; install docs now use `sudo -u serverkit-agent`.

Tradeoff: packaged agents match install.sh's capability set (Docker + metrics +
file access) and no longer do systemd/package management or self-update by
default (both need root). Disabling self-update also routes updates through the
OS package manager's signed path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 01:34:02 -04:00
Juan DenisandClaude Fable 5 41983cc3a9 docs(agent): clarify compose path allowlist is enforced at the handler layer
validateProjectPath is only a syntactic check (absolute, no `..`). The actual
restriction to operator-configured roots is the symlink-resolved AllowedPaths
allowlist run by every compose handler (a.validateFileAccess) before these
Compose* methods are called. Document that contract so a future caller can't
mistake validateProjectPath for the authorization boundary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 01:34:01 -04:00
Juan DenisandClaude Fable 5 fd825276b9 fix(sockets): authorize socket connections by role; gate terminal streams
The Socket.IO connect handler only checked that the JWT decoded — it never
confirmed the account still exists or is active, and recorded no identity. The
generic join_room and subscribe_terminal handlers then performed no
authorization, so a read-only viewer (or a deactivated account with an
unexpired token) could attach to a live PTY stream room and watch a privileged
shell.

- connect: resolve the JWT identity to a live, active User and stash
  {user_id, role} per sid; reject missing/deactivated accounts.
- subscribe_terminal and join_room (for _terminal: rooms): require
  admin/developer, matching the @developer_required on terminal creation.
- disconnect: drop the per-sid identity record.

Job-progress and cloudflared-login streaming (non-terminal server rooms) are
unaffected — that data is already reachable over REST by any authenticated user.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 01:33:44 -04:00
Juan DenisandClaude Fable 5 58dc9f9c4d build(agent): darwin cross-builds non-fatal in build-all
fyne.io/systray needs CGO on darwin, so the macOS steps can only succeed
on a Mac; with CGO_ENABLED=0 they always fail and aborted build-all
before... actually after linux/windows, but with a dirty exit. Mark them
non-fatal (and use CGO_ENABLED=1 so they work where they can) so
build-all completes cross-host - darwin release builds come from the
Agent Release workflow anyway.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 00:49:04 -04:00
Juan DenisandClaude Fable 5 5ceb2d83b7 fix(ui): serialize terminal input + demo chrome for the Terminal tab
Verified the S8.3 terminal live end-to-end (WSL agent -> gateway ->
browser xterm) and fixed what the test surfaced:

- RemoteTerminal sent every keystroke as its own HTTP POST; parallel
  POSTs reach the agent out of order, so fast typing arrived scrambled
  ("echo" -> "ehe..."). Input is now queued and flushed sequentially,
  coalescing keys that arrive while a chunk is in flight.
- Terminal page header -> PageTopbar (icon + mono meta), matching every
  other migrated page.
- term-shell rail rows: server icon + right-aligned glowing status dot
  (demo con-target); shell pane now sits flush against the rail with
  RemoteTerminal's drawer chrome flattened (demo con-main).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 00:36:45 -04:00
Juan DenisandClaude Fable 5 9e0f063d0a fix(agent): restore Linux build + register flag panic
Found while standing up a Linux agent to test the panel terminal:

- agentui/pairer.go calls isServiceInstalled/waitForServiceStopped which
  only existed in platform_windows.go, so the agent did not compile for
  Linux at all (its primary target). platform_other.go now stubs both:
  isServiceInstalled() returns false so pairing skips the SCM stop/start
  dance entirely on non-Windows.
- register defined -c as shorthand for --connection-string, colliding
  with the global -c/--config persistent flag; pflag panics on shorthand
  redefinition, so `serverkit-agent register` crashed on every platform
  at HEAD. Shorthand dropped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 00:36:32 -04:00
Juan DenisandClaude Fable 5 b2e4ac7c60 feat: interactive Terminal tab on /terminal over agent PTY (S8.3)
The "Terminal & Logs" page had no terminal. Now a Terminal tab hosts the
xterm console (RemoteTerminal) against paired agent servers, behind a
demo-style target rail (.term-shell: agent list with glowing status
dots, offline rows disabled, first online server auto-selected).

RemoteTerminal was built but never mountable - it imported a
nonexistent SocketContext and listened for a terminal:<sid> event that
nothing emits. Fixed the full output path:

- backend sockets.py: new subscribe_terminal/unsubscribe_terminal
  handlers join the browser into the agent gateway stream room
  (server_<id>_terminal:<session>) after validating the session via
  TerminalService.get_session
- RemoteTerminal: rewired to services/socket.js; consumes server_stream
  events filtered by the session channel (agent PTY -> gateway ->
  xterm), re-subscribes on socket reconnect, unsubscribes on unmount

VALID_TABS gains terminal (appended - logs stays the default landing
since the shell needs a connected agent; panel-host PTY remains a S5
gap, TerminalService rejects local).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 23:55:39 -04:00
Juan DenisandClaude Fable 5 1cbaa6fa27 feat(ui): Databases SQL editor gutter + highlighting, click opens console (S8.1)
- new databases/SqlEditor.jsx: the demo .sql-editor as a working editor -
  transparent <textarea> overlaid on a scroll-synced highlighted <pre>
  (identical font metrics), line-number gutter, SQL keyword/string/
  number/comment tints; wrap=off + horizontal scroll sync
- ConsoleTab swaps its bare textarea for SqlEditor (focus/shortcuts/
  read-only badge unchanged); dead .dbx-editor styles replaced by
  .dbx-sqled
- UX: single-clicking a database node in the tree now opens its SQL
  console directly (previously only via right-click context menu) and
  expands its tables; collapsing stays on the chevron so re-clicks do
  not fold the tree

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 23:34:51 -04:00
Juan DenisandClaude Fable 5 7647fde208 feat(ui): Docker per-container accent dots (S8.6)
The demo gives each container a hue-hashed identity dot in the name cell
(.dot-ico); the live table only had a green/gray status dot duplicating
the Status pill. The dot is now deterministic per container name, glows
when running, dims when stopped.

Also closes the S8.6 audit items: KPI icon tone-wash was a false alarm
(rules + tone props verified correct); Projects KPI skipped (labels only
exist on per-container inspect, count would cost an extra fetch per
target); logs modal->drawer stays blocked on the S6.3 decision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 23:09:20 -04:00
Juan DenisandClaude Fable 5 ad2d3015cb feat(ui): Files parity - syntax-tinted preview + quick access (S8.5)
- new file-manager/highlight.js: the demo hlCode line tinting (escape
  first, then kw/str/num/cmt/var token spans; PHP + JS keyword sets)
- PreviewDrawer read view -> .pv-code with line-number gutter on
  --bg-code; Edit mode keeps the textarea; >4000-line files fall back to
  the plain read-only textarea
- Quick access rail group above Folders (Sites /var/www, Stack
  /opt/serverkit, Web config /etc/nginx, Logs /var/log)
- PageTopbar meta shows the browse target (agent name / "panel host")
- breadcrumb chevron icons -> demo mono "/" separators
- ext-badge on image thumbs always visible (was hover-only)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 23:06:53 -04:00
Juan DenisandClaude Fable 5 8ac61a7f1e feat(ui): WP list bulk-select + detail posture gauge & PHP version (S8.4)
List (demo bulkbar, real APIs, no bulk route needed):
- header + per-row checkboxes with accent is-selected rows
- bulkbar fans out per site: Start (unarchive), Stop (archive), Update
  core, Backup (snapshot), Clear cache - each scoped by an applies()
  filter so e.g. Stop only hits running sites; failure counts toasted

Detail:
- Security tab gains the demo posture panel: ScoreGauge ring + checklist
  computed from 3 real signals (integrity checksums clean, WP_DEBUG off,
  no critical/high vulnerabilities); checks that have not run stay out of
  the score instead of faking it
- header subtitle now shows PHP version (site.application.php_version)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 18:46:45 -04:00
Juan DenisandClaude Fable 5 6e3d0f5155 feat(ui): Services list -> dense sk-dtable + SegControl + src badges (S8.2)
The list was a flex-row layout with three native selects - the main reason
it did not read as the demo. Now:

- rows -> .sk-dtable in a surface card: checkbox gutter, Service (type
  tile + label sub), Source badge (GitHub/git icon + owner/name from
  deploy_repo_url), Domain (mono), Status Pill (amber deploying/building,
  red failed), Last Deploy, right-aligned lucide action icons
- status select -> SegControl (All/Running/Stopped); Type + Sort selects
  kept (capability superset over the demo)
- bulk-select + row-select preserved (sk-dtable is-selected)
- narrow screens drop Source/Domain/Last Deploy columns
- dead flex-row/list-header/status-dot/repo-pill SCSS removed

CPU/Memory/Server columns omitted (no list payload - S5 gap).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 11:15:04 -04:00
Juan DenisandClaude Fable 5 8b49fd2255 docs: mark S8.7 Workspaces done in the parity map
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 10:11:51 -04:00
Juan DenisandClaude Fable 5 2312cf4448 feat(ui): WorkspaceDetail page + demo workspace cards (S8.7)
The demo's missing /workspaces/:id detail view, built on real data only:

- new pages/WorkspaceDetail.jsx: back-link + site-header hero (brand tile,
  active-workspace / status Pill, mono slug-members-since meta), Workspace
  info card (sk-info-row) + live Resources count strip, accent-underline
  tabs (Servers / Services / Sites / Members) over sk-dtable rows with
  Manage links, move-in/out pickers, member add/remove, per-app Share ACL
  modal, Set active (localStorage scope + reload, mirrors
  WorkspaceSwitcher), Settings edit modal (updateWorkspace), Archive/
  Restore + admin Delete
- list page slimmed to the demo card: clickable card -> detail, "Open >"
  footer, .ws-card.active accent wash for the scoped workspace; the
  members/resources/sharing modals moved into the detail page
- route /workspaces/:id added

Deferred (S5 backend): plan/billing, aggregated CPU/MEM usage bars,
member last_active.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 10:11:25 -04:00
Juan DenisandClaude Fable 5 a97f8a4215 feat(ui): Databases parity pass 2 - flush console + semantic tints (S8.1)
The demo is a flush full-height 3-pane console; the live page was padded
floating cards, which is why it did not read as the new design.

- de-cardify: .db-explorer padding/gaps -> 0; toolbar/tree-panel/
  workspace/statusbar lose radius+outer borders, join on 1px edges
- ResultsGrid: demo cellEl semantic tints (NULL italic-ghost, emails/URLs
  + positive statuses green, negative amber)
- tab strip: demo + new-tab pill (opens SQL console on selected source)
- result count number bold green

Follow-up (S8.1): SQL editor line-number gutter + keyword highlighting.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 02:37:40 -04:00
Juan DenisandClaude Fable 5 e0e660087e fix(ui): retint Agent Fleet + Fleet Monitor to design tokens (S8.0)
These two pages were never migrated: hard-coded Tailwind light-palette
utilities (bg-gray-200, bg-yellow-50, bg-blue-600, bg-white modal) made
the /servers -> /fleet jump read as a different app and broke dark theme.

- StatCard/StatsGrid -> MetricCard KPI strip; progress bars -> ds Gauge
- status Badges -> Pill (versions, rollouts, heatmap, alerts, anomalies,
  search, discovery)
- new token homes in _fleet-monitor.scss: .fleet-kpis/.fleet-warnrow/
  .fleet-ico/.fleet-statbox/.fleet-predbox/.fleet-modal/.fleet-statrow
- heatmap buckets + forecast chart strokes -> theme vars
- _utilities.scss: shim text-green-500/red-500/yellow-600/yellow-700

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 02:37:29 -04:00
Juan DenisandClaude Fable 5 c31ad144d3 docs: re-audit vs new design extract - add S8 parity-gap map
Pass-1 restyle stops short of real parity on several pages; S8 ranks the
gaps per page (Agent Fleet/Fleet Monitor never migrated, Databases still
cardified, Services list structure diverged, Terminal IA, WP list, etc.)
and sets the execution order.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 02:37:17 -04:00
Juan Denis 8bf6488b9c docs: redesign restyle COMPLETE - mark Applications/overlays/sweeps done 2026-06-11 02:12:17 -04:00
Juan DenisandClaude Fable 5 6f5df6db6e refactor(styles): promote .sk-state primitive + final design-system sweeps
(1) New %sk-state placeholder + .sk-state class in _design-system.scss
(mono uppercase state chip, 7 tone modifiers); the 5 page-local copies
(.mon-state/.sec-state/.inc-state+.inc-impact/.git-chip/.bk-type) now
@extend it - class names and JSX untouched, compiled output verified
equivalent. (2) Dead connectionColors export removed from
connectionRules.js (zero consumers). (3) _email.scss globals evicted:
.status-badge deleted (its unique content was dead variants + a phantom
::before dot artifact in two text badges - strict improvement),
.empty-state moved to _empty-state.scss via an html-prefixed bridge that
preserves the cascade over page-partial copies. (4) TokenModal blocks in
_servers.scss re-tokened (--bg-code scripts/connection string, eyebrow
labels, green status dot) - no other selectors in the file changed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 02:11:49 -04:00
Juan DenisandClaude Fable 5 7b1e9849ab feat(ui): restyle the infra overlays (logs dock, SSH terminal, container logs)
Map item #21, bottom-dock IA kept (S6.3 stays open). LogsDrawer: sk-
drawer-style head (icon tile, mono source sub, live-dot line counter),
log well on --bg-code, mobile fix (dock was orphan-offset 250px with the
sidebar off-canvas). RemoteTerminal: previously UNSTYLED (classes had no
stylesheet; old VS Code palette in an embedded <style> tag) - now has a
proper token home in _logs-drawer.scss; xterm theme retinted to the new
palette incl. the v5 selectionBackground key fix (v4 selection key was
silently ignored). ContainerLogs: icon-tile header + mono sub; its
styles live in _wordpress-pipeline.scss (CONTAINER LOGS section only).
All socket/resize/follow/cleanup behavior byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 02:11:49 -04:00
Juan DenisandClaude Fable 5 96641a1855 feat(ui): restyle the Applications pages + modernize the base app-* chrome
The last old-look pages. Base app-* classes in _applications.scss now
carry the new spec directly (gradient detail header + accent wash, mono
breadcrumbs/eyebrow panel headers, sk-info-row k/v grids, accent tab
strip) - property-aligned with the .wp-detail-page overrides so WP detail
stays identical and WordPressProject inherits the new chrome for free.
Applications list: PageTopbar + MetricCard KPI strip + dense sk-dtable
(type tiles, Pills, Gauge resource rows, SegControl filter); page no
longer borrows docker-* classes. ApplicationDetail: tinted header tile +
Pill/EnvTag, deploy/build Badges -> Pills, consoles on --bg-code; dead
blocks with zero consumers dropped. Also fixes pre-existing lint errors
(empty catches, unescaped entities). NOTE: /apps currently redirects to
/services so the list page is orphaned - restyled for consistency.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 02:11:48 -04:00
Juan Denis 98f41294b1 docs: mark WP detail restyle done; record flat-tabs decision (S6.2) 2026-06-11 01:30:17 -04:00
Juan DenisandClaude Fable 5 a15099c25f feat(ui): restyle the WordPress detail page (14 flat tabs) to the new look
Flat-tabs decision applied (S6.2): VALID_TABS + deep links byte-identical;
strip restyled to the accent-underline spec. Header -> demo site-header
(gradient + accent wash, WP-brand tile with status dot, Pill + EnvTag,
mono dotsep meta) and a NEW env-switcher dropdown bound to the real
site.environments payload (navigates between env site ids, with a
loading guard against stale renders).

All app-* shared-class overrides scoped under .wp-detail-page in
_wordpress.scss - _applications.scss untouched (Applications keeps its
look until its own pass). Per tab: Overview KPI strip + k/v rows + quick
actions; EnvironmentCard -> EnvTag/Pill (fixes staging mislabeled DEV);
SnapshotTable -> sk-dtable (drops inline #EF4444); Plugins/Themes ->
dense tables with amber update chips + bulk wash; Git tab -> hash chips
+ feed commits; Uptime/Analytics -> MetricCard strips + retinted REAL
recharts (no fake response-time/referrers - backend gaps); Vulns ->
severity KPI strip + chip table; Security -> --bg-code integrity well;
Updates -> run rows with Pills; Reports Badges -> Pills. HealthDot
colorMap fixed (referenced a nonexistent --color-success). WP list +
Projects styles verified unregressed; .wp-env-badge/-status kept for
their other consumers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 01:29:51 -04:00
Juan Denis aa6981c6c5 docs: mark Git/Workflow/Backups body restyles done; record resolved is_active gap 2026-06-11 00:49:00 -04:00
Juan DenisandClaude Fable 5 382dd76fd5 feat(ui): restyle the Backups body to the new look
StatCards -> MetricCard KPI strip (incl. previously-dropped file_backups
count + conditional remote card); backups list -> dense sk-dtable with
type-tinted icon tiles, mono type chips, remote-sync Pills, SegControl
type filter (same state values); schedules -> dense table with cron-chip
times + status Pills; storage tab gains a real-data spec-card strip +
SegControl provider picker (all S3/B2 fields kept); restore modal ->
amber warning + sk-info-rows (stays a modal). Heatmap/GFS/multi-
destination/selective-restore deferred (backend gaps, map S5).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:48:29 -04:00
Juan DenisandClaude Fable 5 8279c10826 feat(ui): restyle the Workflow Builder to the new look
Floating toolbar/palette cards -> flush wf-head bar (ghost title input,
real is_active Pill, mono dotsep meta) + wf-rail node palette (eyebrow
groups, tinted icon chips). NEW: Active switch wired to the REAL
Workflow.is_active flag (backend already persists it - map S5 "likely
gap" resolved); list modal shows per-workflow active Pills. ReactFlow
chrome tokenized (theme-aware dot grid via CSS var, minimap/controls on
surfaces, accent edges); nodes keep exact geometry (no layout drift).
WorkflowExecutionHistory gray-* Tailwind theming bug FIXED (token-backed
console frame, status Pills, level-colored log lines). Node/panel
palettes retinted to new-palette literals; ReactFlow interactions
verified byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:48:28 -04:00
Juan DenisandClaude Fable 5 1490315f25 feat(ui): restyle the Git page body to the new look
StatStrip -> MetricCard strip (server status/URL/SSH/version from the
loaded status payload); repo cards -> dense sk-dtable (icon tile, mono
branch chips, stars/forks/updated); repo detail re-tinted (mono tree,
accent hash chips); webhooks -> dense table with brand source tiles +
Pills (all 4 actions kept); deployments -> feed rows with status Pills,
rollback/redeploy kept; icon-font close spans -> lucide X. Git now owns
its own log-output styles (no _email.scss dependency). Provider OAuth +
Gitea metrics deferred (backend gaps).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:48:28 -04:00
Juan Denis 0530d531ab docs: mark Cron/Terminal/Workspaces/Email/Security/StatusPages body restyles done 2026-06-11 00:19:16 -04:00
Juan DenisandClaude Fable 5 89fb2c7519 feat(ui): restyle Status Pages body + cross-cutting token cleanup
StatusPages (completes the Monitoring group): Badges -> ds Pills, hero
gains a comp-dots component strip (real loaded statuses only), metrics ->
sk-spec-cards, incidents -> inc-state/impact mono chips with state-tinted
washes, rail items get visibility pills + mono slugs; all CRUD/check/
transition flows kept; default page color -> new accent.

Cleanup flagged by earlier waves: utils/serviceTypes.js old-palette hex
swapped to new-palette values (keys/shape kept; consumers verified -
Services/ServiceDetail/useService, NOT ApplicationDetail as the map
claimed); serverdetail/ServicesTab Badge -> Pill; _server-packages +
_server-services migrated off shadcn vars (incl. the broken accent-as-
background hover) onto surface/text tokens + eyebrow headers + --bg-code
log panes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:18:28 -04:00
Juan DenisandClaude Fable 5 ff2192cb45 feat(ui): restyle the Security suite (shell + 13 tabs) to the new look
Shell: StatStrip -> MetricCard KPI strip (alerts/malware/ClamAV/scan from
real status), tab strip -> accent wash via scoped SCSS (ids untouched).
Tabs: Overview cards -> Pill + sk-info-row; Scanner/Quarantine/IP-lists/
SSH-keys/fail2ban lists -> dense sk-dtable with mono cells + state chips;
Vulnerability + Audit render their REAL scores via ScoreGauge; Integrity
changes get kind chips + --bg-code file lists; Firewall sub-views -> ds
SegControl with live counts; Events -> ds Feed with tone dots;
AutoUpdates/Config reskinned (Config via SCSS only). All flows kept
(scans, bans, rules, keys, baselines). Geo-blocking/policy toggles/
schedules/sessions deferred (backend gaps).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:18:28 -04:00
Juan DenisandClaude Fable 5 bc7edde302 feat(ui): restyle the Email Server body to the new look
Status tab service cards -> icon tiles + Pills (controls kept); Domains
tab gains a real-data MetricCard KPI strip + dense sk-dtable with
DKIM/SPF/DMARC presence pills; Accounts/Aliases/Forwarding card lists ->
dense tables with mono cells; DNS providers + webmail reskinned; queue ->
dense table that now also renders the already-loaded Recipients field;
previously-unstyled password modal styled. All scoped under .email-page
to avoid cascade leaks; tab ids/deep links untouched. Volume/reputation/
activity-feed surfaces deferred (backend gaps).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:18:09 -04:00
Juan DenisandClaude Fable 5 4691bff8a3 feat(ui): restyle the Workspaces body to the new look
Header -> PageTopbar (flat item, no tabs); cards -> prototype ws-card
(ServiceTile avatar honoring the real primary_color, status Pill, mono
slug/since meta, stat strip, hover lift); members modal rows get avatars
+ role Pill/tags (backend role names kept verbatim - S6.6 unresolved);
resources modal gets eyebrows + pick-lists; sharing ACL role select ->
SegControl (same values). Create-modal color default #6366f1 -> #6d7cff.
Plan/billing/usage/counts not in payload -> skipped, nothing faked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:18:09 -04:00
Juan DenisandClaude Fable 5 2f66507a0c feat(ui): restyle the Terminal/Logs page to the flush console look
Log Files + Journal tabs -> single bordered console frame (con-rail
target list with mono eyebrow groups, accent-bg active rows, session-head
viewer bar, log well on --bg-code); Processes tab -> same frame with
sk-dtable-spec sortable table + token gauges; Services tab cards re-
tinted with status stripes. Terminal gets its OWN proc-chip filter chips
(no longer depends on _templates.scss .filter-chip); process/service
statuses -> ds Pills; hashColor/priority palettes retinted to the new
palette. Legacy block kept for shared consumers (JournalControls/
ProcessTable/ServiceCard).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:17:54 -04:00
Juan DenisandClaude Fable 5 b38053d448 feat(ui): restyle the Cron Jobs body to the new look
StatCards -> MetricCard KPI strip (jobs/active/service/platform from real
status), job cards -> dense .sk-dtable (clock tile, mono schedule chip +
readable hint, Pill status, all 4 row actions kept incl. run-now), new
list head with search + All/Enabled/Disabled SegControl (client-side
only), modals reskinned with mono eyebrows + --bg-code run output.
Next-run/history/success-rate omitted (backend gap, map S5).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 00:17:53 -04:00
Juan Denis 7e272492ef docs: mark FTP/Monitoring/ServerDetail/ServiceDetail+Templates body restyles done 2026-06-10 23:46:10 -04:00
Juan DenisandClaude Fable 5 a16ff1b8f8 feat(ui): restyle ServiceDetail tabs + Templates catalog to the new look
ServiceDetail: header -> ServiceTile gradient avatar + ds Pill + mono
dotsep meta (adds the real domain link); OverviewTab -> MetricCard strip
+ sk-info-row key/values + EnvTag + Gauge bars, deploy statuses -> Pills;
MetricsTab gauges tokenized (no fake history charts - backend gap);
Packages -> sk-dtable; Events -> tone dots + Pills; logs/shell/commands/
gunicorn consoles re-tinted to --bg-code (fixes broken light theme);
settings/git modal polished via SCSS only. Templates: catalog -> tpl-card
grid (icon tile, mono version, clamped desc, tag chips, amber featured
star, hover-reveal Deploy wired to the existing install flow) + cat-chip
category filter; drawer no longer stacks under the install modal. All
tabs, filters, handlers, and deep links kept.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:45:28 -04:00
Juan DenisandClaude Fable 5 8a61bd67ab feat(ui): restyle the ServerDetail tab bodies to the new look
Header -> demo detail-header (surface gradient + accent wash, mono dotsep
meta, ds Pill status); overview KPI tiles -> spec-card look with thin ds
Gauges (CPU/RAM/Disk retinted to accent-bright/cyan/green convention);
tab strip -> accent underline; data tables + services/packages tables ->
dense sk-dtable spec (scoped fixes for their shadcn-var partials);
docker/cron/cloudflared tabs re-skinned with Pills and mono eyebrows.
Dead blocks removed (kpi-gauge ring, resource-meters, duplicate
server-detail-tabs, notifications-tab). Servers LIST + ops workspace
styles untouched; all tabs, actions, telemetry, and deep links kept.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:45:16 -04:00
Juan DenisandClaude Fable 5 8f46ac8369 feat(ui): restyle the Monitoring body to the new look
Overview: StatStrip -> MetricCard KPI strip, current metrics -> host-card
grid (icon tile + Pill + thin token-colored Gauges + mono host-mini
footer), active alerts -> alert-row pattern with red-wash firing chips.
Alert Rules / Delivery / History tabs re-skinned in place (Pills, mono
eyebrows, surface tokens); all CRUD, scheduler, and channel config kept.
Synthetic uptime monitors / response-time charts deferred (backend gap,
REDESIGN_MAP S5). Also removes the dead .alert-item block that collided
with _servers.scss.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:45:05 -04:00
Juan DenisandClaude Fable 5 6687c429fa feat(ui): restyle the FTP Server body to the new look
Completes the Files group. StatStrip -> MetricCard KPI strip (status/
active server/users/connections), users + connections tables -> .sk-dtable
with Pills and mono cells, mono eyebrow section headers, surface-token
cards, log viewer on --bg-code. Replaced the broken icon-font <span>s with
lucide icons inside the same buttons. Dead pre-topbar blocks dropped.
All capabilities kept (install flow, user CRUD + password modal,
disconnect, logs, deep-linked tabs).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 23:44:55 -04:00