941 Commits

Author SHA1 Message Date
librelad
1a4de624d0 refactor(webui): separate core/css into base/components/screens
core/css held 13 flat stylesheets. Grouped by role, matching the JS sub-system
split:

  core/css/base/        foundation (3): tokens, style, themes
  core/css/components/  chrome + widgets (7): topbar, sidebar, modal, forms,
                        config, update-notifier, aurora-background
  core/css/screens/     full-page screens (3): login, loading-screen,
                        setup-wizard

Path-only move (git mv) + href rewrite in index.html. No @import anywhere and
the <link> line order is unchanged, so the cascade is preserved; all 13 paths
verified to resolve.

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 19:39:14 +01:00
librelad
227a66fdaf Merge claude/1 2026-05-30 19:32:09 +01:00
librelad
aa563f1fed refactor(webui): separate core/lib + core/boot into sub-system folders
core/lib held 18 loose .js; core/boot held 10. Grouped by responsibility,
mirroring the components/* sub-system layout:

  core/lib/task/    task kernel (8): event-bus, commands, actions, router,
                    global-functions, manager, refresh-coordinator,
                    parameter-preserve
  core/lib/config/  config helpers (2): config-shared, config-options
  core/lib/util/    generic utils (7): data-loader, dom-helpers, ui-helpers,
                    lp-ui, router, system-live, dismissible
  core/boot/setup/  first-run wizard (3): setup-detector, setup-wizard,
                    setup-completion-watcher
  core/boot/controls/ form widgets (2): custom-number, custom-select

core/lib is now purely subfolders. backup-app-card.js was misfiled in lib (it's
a UI card) — moved to core/ui/. core/boot keeps the genuine bootstrap singletons
at root (system-loader, system-orchestrator, auth-manager, loading-ui,
theme-registry).

Path-only moves (git mv); all 35 referenced core paths verified to resolve,
full node --check sweep of 100 frontend .js files clean.

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 19:32:09 +01:00
librelad
78c463d3ac Merge claude/1 2026-05-30 19:18:44 +01:00
librelad
939f0223fb refactor(webui): separate backup component into sub-system folders
backup/ held 15 loose .js plus css/html at the component root. Split into
per-tab sub-systems mirroring the admin/apps layout:

  backup/core/{js,css,html}/   schema, base BackupPage, fetch-client,
                               cron-schedule, backup.css, backup-content.html
  backup/dashboard/js/         backup-dashboard
  backup/snapshots/js/         backup-snapshots, backup-snapshot-actions
  backup/locations/js/         backup-locations, backup-location-fields,
                               backup-location-modal, backup-ssh-key
  backup/migrate/js/           backup-migrate
  backup/configuration/js/     backup-configuration, backup-retention-presets,
                               backup-engine-details

Updated the scripts[] array + loadFragment in index.js, the backup.css href in
index.html, and the handleBackup() fallback paths in spa.js. No behaviour
change — files moved verbatim (prototype-augment clusters), all 17 referenced
paths verified to resolve, node --check clean.

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 19:18:43 +01:00
librelad
be7f45def9 Merge claude/1 2026-05-30 18:26:31 +01:00
librelad
f896df6006 refactor(admin): move bare css/ into admin/core/ for sub-system consistency
admin had sub-system folders (config/overview/system/ssh/peers) AND a bare
root css/ (admin.css) — inconsistent. A component's shared base belongs in a
core/ sub-folder once it has sub-systems (matching apps/core/), so admin.css
moves to admin/core/css/admin.css. Audit confirms all components are now
consistent: sub-system components (apps, admin) use core/ + sub-systems;
single-page components (backup/dashboard/tasks/updater) stay flat js/css/html
(no sub-systems, so no core/ needed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 18:26:31 +01:00
librelad
e03c900f20 Merge claude/1 2026-05-30 15:47:37 +01:00
librelad
e30c20fde6 refactor(webui): remove leftover redirect components; one working kernel redirect
config-redirect/, peers/, ssh/ were redirect-only shim components (just a
feature.json each) whose handlers re-entered navigate() and were silently
no-op'd by the isLoading guard — i.e. the legacy /config /peers /ssh URLs were
broken, and nothing in the UI links to them. Replace all three with a single
_legacyRedirect() at the top of navigate() (before the guard, so it actually
works) that rewrites them to the canonical /admin/* path. Removed the 3
folders, their manifest entries, the 3 dead spa.js handlers, and their
setupRoutes() lines. components/ is now exactly the 6 real pages; the real
SSH/Peers pages live (as before) under admin/ssh and admin/peers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 15:47:37 +01:00
librelad
2304aed213 Merge claude/1 2026-05-30 15:27:36 +01:00
librelad
25e3570616 refactor(webui): fold app-detail into the apps feature
app-detail was a separate sibling component but is really the apps feature's
detail view (shares the apps controllers + apps-unified-layout). Merge it in:
the apps feature now owns /apps*, /app, /app* and its mount() dispatches grid
vs detail by path (checks /apps first for wildcard precedence). Removed the
components/app-detail/ folder + its manifest entry. (The 1-level feature scan
means a feature must be a direct components/<id>/ child — folding the routes
into apps is the correct way to express the relationship.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 15:27:36 +01:00
librelad
684b3b929b Merge claude/1 2026-05-30 15:06:42 +01:00
librelad
df75059330 refactor(apps): decompose apps-manager god-file into 7 responsibility files
Brace-aware split of apps-manager.js (4154->2015 base) into apps-grid,
config-form, port-manager-integration, gluetun-vpn, config-dirty-guard,
install-console, service-buttons-sidebar — augmenting AppsManager.prototype.
Removed the dead duplicate initializeSimpleTabs (kept the live later def).
Used a self-checking extractor (node --check per cluster, auto-revert on
failure): install-dispatch contains a regex literal (/^\d{16}$/) that trips
brace-bounding, so its methods were safely LEFT in the base rather than risk a
bad split. ServiceButtons class + expandServiceLinks + bootstrap also remain
inline. Verified: all 117 methods preserved (none lost), all files
node --check clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 15:06:42 +01:00
librelad
3d058b3469 Merge claude/1 2026-05-30 14:53:19 +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
e0737b65ef Merge claude/1 2026-05-30 14:02:45 +01:00
librelad
82989069e2 refactor(backup): decompose backup-page god-file into 13 responsibility files
Faithful prototype-augment split of backup-page.js (2353->753 line base) into
fetch-client, dashboard, snapshots, locations, location-fields, ssh-key,
retention-presets, configuration, engine-details, location-modal,
snapshot-actions, migrate (+ the earlier cron-schedule). Methods relocated
verbatim (mechanical sed/awk extraction, no logic change); all augment
BackupPage.prototype and load after the base via the ordered kernel loader.
Verified: all 99 original methods present exactly once across base+clusters,
no duplicates, all 14 files node --check clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 14:02:45 +01:00
librelad
3098324627 Merge claude/1 2026-05-30 13:02:13 +01:00
librelad
3ad44a62f2 refactor(backup): extract cron-schedule cluster from backup-page god-file
First god-file decomposition slice: lift the standalone cron-next utility
(nextCronFireTime/_cronFieldSet/formatRelativeFuture/formatScheduleClock) out
of backup-page.js into backup-cron-schedule.js, augmenting BackupPage.prototype.
Extracted verbatim via sed (no logic change); loaded after backup-page.js in
the feature's ordered scripts array. backup-page.js 2470 -> ~2353 lines.
Proves the faithful prototype-split pattern on the verify-confirmed-safe loader.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 13:02:13 +01:00
librelad
9eb5f7f73a Merge claude/1 2026-05-30 12:42:35 +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
librelad
db080202b6 Merge claude/1 2026-05-30 12:25:37 +01:00
librelad
0fb24435fc fix(webui): load component scripts in order (script.async=false)
system-loader's loadScript appended scripts without async=false, so a
component's scripts[] executed in download-finish order, not array order.
That's a latent nondeterminism today (duplicate-method 'last wins' depended
on it) and a hard blocker for splitting a class across files (a base file
must run before prototype-augment files). Forcing async=false makes the
boot loader honour array order, matching the kernel's ctx.loadScripts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 12:25:37 +01:00
librelad
0ae6aea5f4 Merge claude/1 2026-05-30 07:43:58 +01:00
librelad
474c518df1 docs: fix index.html comment to reference components/ after the reorg
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 07:43:58 +01:00
librelad
2b3a3429d7 Merge claude/1 2026-05-30 07:34:32 +01:00
librelad
ed4bf41cba ux(updater): match the Backups page layout (sidebar, padding, click-to-open)
Restructure the updater page to mirror Backups exactly:
- updater-content.html: shared .sidebar/.category (with .category-icon SVGs)
  outside the page card, .config-section + .page-header + a padded
  .updater-page-body — fixes the missing content padding.
- updater.css: layout copied from .backup-* (flex, padding-bottom:48px,
  body padding:22px); dropped the custom sidebar/header styles (now using the
  shared chrome); kept the updater-specific content widgets.
- updater-page.js: delegate clicks on .updater-layout (sidebar is now a
  sibling of the card) so clicking a sidebar entry opens that tab; fill the
  shared page-header icon slot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 07:34:32 +01:00
librelad
e7b299b9cc Merge claude/1 2026-05-30 07:13:52 +01:00
librelad
d39852aa3d refactor(webui): reorganize into components/ + core/ taxonomy
Final modularization layout (user-chosen): every page is a self-contained
folder under components/<id>/ (controllers + CSS + its html fragment), and all
shared/framework code folds into core/:
  core/kernel  (feature-registry, lifecycle, services, spa)
  core/boot    (auth, system-loader/orchestrator, setup, loaders)
  core/lib     (data-loader, router, helpers, the task kernel, shared modules)
  core/ui      (topbar, modal, notifications, … + topbar.html)
  core/css     (all shared stylesheets)
  core/icons
Top level is now just: components/, core/, themes/, index.html (+ runtime data/).

Every path reference rewritten (index.html, scripts arrays, fetch()/
loadFragment()/loadScript() literals, system-loader + config-manager controller
paths, kernel manifest URL, feature.json, backend FEATURES_DIR). The
/api/features/list endpoint NAME is unchanged (it now scans components/).
Deleted 3 dead files (app-content.html, apps-content.html, html-cache.js).
Verified: 0 stale prefixes, 0 double-rewrites, all JS/JSON valid.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 07:13:52 +01:00
librelad
8d193eda28 Merge claude/1 2026-05-30 03:13:26 +01:00
librelad
daa336449a feat(updater): backend — data generator + 'libreportal updater' CLI with DR
- scripts/webui/data/generators/updater/webui_updater_scan.sh (webuiUpdaterScan):
  writes frontend/data/updater/generated/{updates,cves,history}.json from the
  installed-apps DB (current image per app from compose). Available-version +
  CVE-scanner are clearly-marked pluggable hooks; always emits valid JSON.
- scripts/cli/commands/updater/{cli_updater_commands.sh,cli_updater_header.sh}:
  auto-dispatched as 'libreportal updater <sub>' (check/apply/apply-all/rollback).
  apply does disaster-recovery FIRST — snapshots the app via the backup engine,
  then pulls + recreates (real dockerComposeUp/compose-pull helpers), records
  history, and auto-rolls-back on failure. Standard LIBREPORTAL_TASK_EXEC
  enqueue/exec split so WebUI + CLI share locking + audit trail.

New .sh files: the array/function-manifest regen self-heals on deploy; the
check path also sources its generator on demand to cover the gap.

NOTE: host-side bash — written to the repo's conventions but not runnable in
this env; this is the surface to test (the WebUI feature is lp-shot-verified).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 03:13:26 +01:00
librelad
39a1b51f7f Merge claude/1 2026-05-30 02:55:31 +01:00
librelad
5e43f8ec79 feat(webui): wire updater actions through the task router
Add updater_check/apply/apply_all/rollback cases to task-router routeAction
and the matching task-actions methods, each running the locked-down
'libreportal updater …' CLI as a task (apply/rollback snapshot-before-update
host-side for disaster recovery). Verified: /updater + all tabs render, the
new Updates nav button shows globally, and the feature auto-discovers via
/api/features/list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 02:55:31 +01:00
librelad
56f0111d5f Merge claude/1 2026-05-30 02:45:40 +01:00
librelad
e1794069cb feat(webui): add App Updater feature (versions, CVEs, disaster recovery)
New self-contained feature in features/updater/ (mirrors the backup feature):
- index.js + feature.json (auto-discovered; routes /updater + sub-tabs).
- updater-page.js: 5 tabs — Overview (update/CVE/recovery counts), Updates
  (per-app current->available + Update/Update-all), Security (CVEs by severity,
  links to NVD), Recovery (per-app rollback points; snapshot-before-update),
  History. Reads /data/updater/generated/{updates,cves,history}.json; falls
  back to the installed-apps list so it's useful before the first scan. All
  actions route through services.tasks (updater_check/apply/apply_all/rollback)
  — no new mutating API.
- updater.css (self-contained, teal --page-updater hue) + updater-content.html.
- New topbar 'Updates' nav button (nav-updater) + active-highlighting in
  topbar.js + spa.js. Kernel: setupRoutesFromManifest now allows module-only
  features (no legacy handler) — this is the first such feature.

Backend generator + 'libreportal updater' task land next.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 02:45:40 +01:00
librelad
55eecd6dfe Merge claude/1 2026-05-30 02:10:09 +01:00
librelad
eaafd1bb38 refactor(webui): relocate admin area into features/admin/ + shared extractions
- features/admin/: the 10 admin-owned config controllers, the 5 admin pages
  (overview/system/charts/metric/storage), ssh-page.js, peers-page.js, plus
  admin.css/ip-whitelist.css/ssh.css (eager). config-manager.js kept last in
  the load order (it news the sub-managers).
- shared/js/: config-shared.js + config-options.js (ConfigShared/ConfigOptions
  globals consumed cross-feature by backup/apps/tasks).
- shared/css/: forms.css + config.css (generic form + config-form primitives
  borrowed by apps/backup/admin).
- Updated all path strings in system-loader.js (config component) and
  config-manager.js (lazyLoad of admin/ssh/peers controllers); index.html CSS
  hrefs. No /js/components/{config,admin,ssh,peers}/ refs remain.

js/components/ now holds only shared UI (topbar, notifications, eo-modal,
update-notifier, mobile-menu, confirmation-dialog).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 02:10:09 +01:00
librelad
a82d4b75dd Merge claude/1 2026-05-30 02:06:31 +01:00
librelad
ee44a4eb80 refactor(webui): relocate backup into features/backup/, app-card to shared/
- features/backup/: backup-schema.js, backup-page.js, backup.css (eager).
- shared/js/backup-app-card.js: cross-feature (used by backup AND the
  app-detail Backups tab), so it goes to shared/, not buried in backup.
- Updated paths: feature scripts array, spa.js handleBackup fallback,
  system-loader apps-manager component (app-card), index.html backup.css href.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 02:06:31 +01:00
librelad
402c1af861 Merge claude/1 2026-05-30 02:03:57 +01:00
librelad
f15cfe3043 refactor(webui): relocate apps + app-detail controllers and CSS into features/apps/
Move the 6 app controllers (apps-manager, app-tabbed-manager, port-manager,
routing-manager, services-manager, tools-manager) and their 7 stylesheets
(apps, apps-layout, tools, services, service-buttons, routing, port-manager)
into features/apps/. JS paths only existed in system-loader.js (the
apps-manager + app-tabbed-manager components); CSS hrefs in index.html (kept
eager). The cross-feature task-manager (/shared/task/) + backup-app-card
entries in the apps-manager component are untouched here. Globals unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 02:03:56 +01:00
librelad
7924fcc42d Merge claude/1 2026-05-30 02:00:59 +01:00
librelad
b4649cd713 refactor(webui): relocate tasks page + shared task kernel
- features/tasks/: tasks-manager.js (the /tasks page controller) + tasks.css.
- shared/task/: the 6 cross-cutting task-kernel files (event-bus, commands,
  actions, router, global-functions, manager) + task-refresh-coordinator.js —
  used by tasks AND apps/app-detail/backup, so they go to shared/, not a
  feature. task-parameter-preserve.js stays at js/ (shared root).
- Updated all path strings: system-loader.js task-system + apps-manager
  components, apps-manager loadTaskSystem(), index.html (refresh-coordinator +
  tasks.css). Globals (taskEventBus/tasksManager/TaskManager/...) unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 02:00:59 +01:00
librelad
61b48fa7ae Merge claude/1 2026-05-30 01:56:12 +01:00
librelad
3abc45985a refactor(webui): relocate dashboard into features/dashboard/
Move dashboard.js + dashboard.css into the feature folder (kept eager-linked
from the new paths in index.html — dashboard.js stays eager because
system-loader calls its bare globals at boot). No reference sites outside
index.html (the feature's index.js uses globals, not the controller path).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 01:56:12 +01:00
librelad
c6ab276c1e Merge claude/1 2026-05-30 01:52:43 +01:00
librelad
a98a241d5e chore(webui): remove dead controllers (app-manager.js, config-router.js)
Both are orphans with zero inbound references (verified by grep across the
whole frontend): app-manager.js only self-assigns window.appManager and is
in no loader/scripts array; config-router.js only self-defines ConfigRouter
and is referenced nowhere (config-manager owns rendering directly). First,
safest step of the feature reorganization.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 01:52:43 +01:00
librelad
66a48ea8b8 Merge claude/1 2026-05-30 01:14:46 +01:00
librelad
eeb1baf563 refactor(webui): begin backup god-file decomposition + sequential feature scripts
- kernel/lifecycle.js: ctx.loadScripts now loads in array order (sequential),
  so a feature can list a base file before files that augment it. Strictly
  safer than the previous parallel load.
- Extract the module-level schema/retention data (the BACKUP_* maps + the
  retention-preset detector, 83 lines) out of backup-page.js into a new
  backup-schema.js, loaded first. Verbatim move — no logic change. First slice
  of the backup decomposition (god-file: 2553 -> 2470 lines).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-30 01:14:46 +01:00
librelad
86fc41fe77 Merge claude/1 2026-05-30 01:04:59 +01:00