7 Commits

Author SHA1 Message Date
librelad
79d2a4750d feat(webui): Phase 4 — Improvements (hotfix) stream + per-app chip
Surfaces the hotfix channel in the WebUI. Primary home is the Updates &
Improvements page (the updater component) — its own "Improvements" tab — with a
secondary chip on the App detail page (fork 3 locality = both).

Updater component (components/updater):
- New "Improvements" sidebar tab + panel; renderImprovements() reads the host-
  generated artifacts_available.json (severity badge, scope chip, applied/auto/
  not-applicable badges, plain-English why). Apply/Revert buttons dispatch
  artifact_apply / artifact_revert through the TASK system (services.tasks.route)
  — no mutating API. Apply is disabled when the index is UNSIGNED.
- Overview gains an "Improvements" stat card; task-refresh now also repaints on
  artifact_* task completion; URL tab routing + dispose teardown extended.

Task plumbing (core/tasks): artifactApply/artifactRevert action methods (id is
charset-guarded before it enters the command string) + artifact_apply/
artifact_revert routeAction cases. Task list/format gain icons + friendly labels.

Apps component: an amber " N improvements" chip on an installed app's detail
header (populated async from artifacts_available.json filtered by app, applicable
& not-applied), linking to /updater/improvements. Best-effort, never throws.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-31 21:07:01 +01:00
librelad
306e6223c0 fix(webui): release leaked listeners/intervals/streams on unmount (all modules)
The teardown audit found the backup-stacking leak class across 4 more feature
modules (12 confirmed leaks); unmount() left document/window listeners, intervals,
and SSE subscriptions firing on stale controllers after navigation:

- admin: overview/ssh/peers/system each leaked a document click listener ->
  AbortController + dispose() per page; admin unmount() aborts each.
- dashboard: the 1 Hz update-countdown interval + the LiveSystem view sub ->
  stopUpdateCountdown()/detachDashboardLive(), registered via ctx.sub().
- tasks: constructor-started global live-log poller (discarded handle) -> stored
  + idempotent + cleared on unmount + re-armed on mount; per-task monitorTask
  window listeners + interval -> tracked in a map, released on unmount.
- apps: app-tabbed reconcile setTimeout loop + watchdog window/document listeners
  + popstate -> per-instance AbortController + dispose() that clears the timer,
  resets the guards, and unloads the active tab's Services intervals + log SSE.

All mirror the kernel's MountContext teardown discipline. 12 files, all pass
node --check. Backup (fixed earlier) re-confirmed clean by the audit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-31 15:27:29 +01:00
librelad
4e18a6ff42 fix(webui): render App-Updater tasks as standard tasks in the panel
updater_check/apply/apply_all/rollback tasks fell through every per-type
branch of the Tasks panel, so they showed the generic custom gear icon, a
raw/truncated command title, and (for the app:'updater' sentinel) a broken
hidden app icon. Wired them in like every other task type:

- tasks-format.js formatCommandForUser PATTERNS: added the 'libreportal updater'
  command rows (Apps - Check for Updates / Update All / <App> - Update /
  <App> - Roll Back) — only the *self*-update 'libreportal update' was mapped.
- tasks-format.js formatActionTitle: added the updater_* short labels.
- tasks-list-render.js getTaskTypeIcon: updater_check 🔍 / apply ⬆️ /
  apply_all ⬆️ / rollback ↩️ (reusing existing verify/update/restore classes).
- tasks-list-render.js renderTaskIcons: treat app:'updater' as a sentinel like
  app:'system' so updater_check/apply_all fall back to the LibrePortal logo
  instead of a 404'd /core/icons/apps/updater.svg (apply/rollback keep their
  real app icon).

node --check clean.

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-31 02:53:57 +01:00
librelad
c22b0ac60d chore(webui): strip ~665 commented-out console.* debug lines
The shipped frontend carried ~600 muted '// console.…' debug statements (and
their multi-line commented continuation lines) left over from development —
clutter across 30 files. Removed them with a guarded pass that ONLY ever deletes
lines starting with // (so it can never alter behaviour), consuming each
commented console opener plus its continuation comment lines until the
string-stripped parens balance.

665 lines removed, 30 files; 0 insertions. Verified every deleted line is a //
comment (no code touched), real prose comments preserved, full node --check
sweep clean.

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-31 01:25:41 +01:00
librelad
c920ca2dc9 refactor(webui): align page-controller names with the -page convention
From the feng-shui audit naming findings:
- admin/overview/js/admin-overview.js -> overview-page.js (class AdminOverview ->
  OverviewPage, window globals + the 'admin-overview' task-refresh id ->
  overview-page, lazy-load path + typeof/new in config-manager.js).
- admin/system/js/admin-system.js -> system-page.js (class AdminSystem ->
  SystemPage; now sits beside its -page sub-views system-metric-page.js /
  system-storage-page.js).
- tasks/js/tasks-logs-modal.js -> tasks-log-modal.js (singular 'log' to match its
  sibling tasks-log-stream.js; single path ref in system-loader.js).

These were the only page controllers breaking the dominant <thing>-page.js /
<Thing>Page convention (ssh-page/peers-page/backup-page/updater-page/
system-metric-page/system-storage-page). Pure renames; node --check clean.

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-31 01:21:07 +01:00
librelad
1b0040dbf1 refactor(tasks): decompose tasks-manager god-file into 8 responsibility files
Faithful brace-aware split of tasks-manager.js (2664->491 line base) into
list-render, data-load, log-stream, row-expand, actions, modals, logs-modal,
format — augmenting TasksManager.prototype. First removed 4 provably-dead
duplicate defs (the earlier init/setupAutoRefresh/startLogStreaming/loadTaskLogs
that the later defs already overrode — behavior-preserving). Methods relocated
verbatim via a brace-aware Node extractor (handles strings/templates/comments/
regex, fixing the line-heuristic over-capture). Verified: all 60 (deduped)
methods present exactly once, no dups, all 9 files node --check clean. Wired
after the base in the task-system loader (async=false-ordered).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 14:53:19 +01:00
librelad
2ef4cc00e1 refactor(webui): granular sub-system folders per component
De-clutter each component into sub-system folders (apps: core/ port-manager/
services/ tools/ routing/; admin: config/ overview/ system/ ssh/ peers/) with
the standard js/ css/ html/ icons/ layout inside; single-page components
(backup/dashboard/tasks/updater) get js/ css/ html/. Single-feature icon sets
moved into their sub-system (vpn -> apps/core/icons, config/cpu/os ->
admin/{config,system}/icons); shared app + category icons stay in core/icons.
feature.json + index.js stay at each component root (the scanned descriptor +
entry). Every controller/CSS/fragment/icon path reference rewritten; verified
no stale refs, all JS valid.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 12:42:35 +01:00