Commit Graph
163 Commits
Author SHA1 Message Date
Hermes 3b412bff3b DC-011: restore BACKLOG.md (lost in force-push) + claim P0 regression fix
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-06-21 05:49:53 -07:00
Krystie f71e5c52d4 feat(api): unify logger — single source of truth for logs, errors, audit
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Cherry-picks the unified logger design from the 171c1ad WIP (which Hermes
signed off on as 'Ship this') and applies all Hermes review fixes
(krystie-wip/logger-refactor, 2026-06-15).

  src/utils/logging.js is now the single entry point for:
    - log.info / log.warn / log.error / log.debug  (with level filtering,
      color-coded dev output, JSON prod output)
    - log.audit() / log.auditMiddleware()           (audit-log.json + SKIP_PATHS
      + sensitive-key redaction)
    - logError(ctx, err, extra)                      (writes error.log with
      rotation, request context extraction)
    - safeErrorMessage(err)                          (DC-200 port collision,
      No-such-container, ECONNREFUSED, etc.)

  Existing src/security/audit-logger.js kept untouched — routes/errorlogs.js
  still uses auditLogger.query/clear, no callers migrated.

  Hermes' must-fixes (all addressed):
    [1] Syntax error on logger.js:401 — old logger.js at repo root is gone;
        refactored src/utils/logging.js is the new home, no Chinese IME bug.
    [2] /health/live and /health/ready endpoints — untouched in src/app.js.
    [3] Tests — added __tests__/logging.test.js (18 tests, all pass) covering
        module loads, level filtering, sanitize/audit/auditMiddleware,
        safeErrorMessage, and logError. Full suite: 897/897 pass across 31
        suites (was 879 + 18 new).

  Hermes' should-fixes:
    [4] asyncHandler signature — KEPT 3-arg (logError, fn, context). 49 route
        files still call it this way; src/app.js's boundAsyncHandler unchanged.
    [5] platformPaths.pkiRootCert — UNTOUCHED, still used in src/app.js.
    [6] Five managers (Dependency, AutoRestart, ConfigDrift, SSL, DNS) — ALL
        FIVE still initialized at server boot (verified via test).
    [7] ok(res, ...) helper — UNTOUCHED, all routes still use it.
    [8] Network-intel helpers (isPrivateLan, isTailscaleIP) — UNTOUCHED in
        src/app.js, no duplicate inline logic added.

  - setLevel() now updates both GLOBAL_LEVEL and the singleton log._level,
    so level-filter tests don't pollute later tests.
  - Logger.audit() and Logger.error() now return promises so await works.
  - Logger._log() awaits writeErrorLog so callers using await can rely on
    the error.log being flushed.
  - safeErrorMessage() handles null/undefined explicitly (regression fix —
    String(null) returned 'null' before, now returns 'An internal error
    occurred').
  - src/app.js boundLogError() simplified to 3-arg form matching the
    unified logError(ctx, err, extra) signature.

  - createLogger(level) alias exported so existing src/app.js callers work.
  - logError, safeErrorMessage, LOG_LEVELS still exported.
  - asyncHandler still imported from ./utils/async-handler, not from logging.
  - No changes to routes/* (audit-logger.js still consumed unchanged).

  - jest: 897/897 tests pass across 31 suites
  - node -e "require('./src/app.js')" loads cleanly
  - node server.js boots through full init (all 5 managers start)
  - Color-coded logger output visible in dev mode (no NODE_ENV)
  - JSON output in production mode (NODE_ENV=production)
2026-06-19 18:41:26 -07:00
Krystie 44af47d344 feat: add Sami Files logPath to template + mount in start.sh
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-06-19 18:16:34 -07:00
Krystie 6809fc5cca fix(monitoring): flatten CPU/mem data, add health summary, public + rate-limit monitoring/stats
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Three coordinated fixes for the System Overview widget:

1. routes/monitoring.js — flatten getAllStats() shape from
   {current:{cpu:{percent},memory:{percent}}} to {cpu,memory,memoryUsage}
   so the widget's Number() coercion actually produces numbers, not NaN.
   Skill reference: references/totp-and-system-overview-pitfalls.md §3.

2. routes/health.js — add summary block to /health-checks/status response.
   Widget looks for {healthy, unhealthy, total} but only per-service objects
   existed. Permissive on healthy side (up|healthy|online), strict on
   unhealthy (down|unhealthy|offline|error); anything else counted as
   unknown. Same skill §3 reference.

3. middleware.js — add /api/v1/monitoring/stats to PUBLIC_ROUTES and the
   rate-limit skip list. The widget polls it every 5s from the dashboard;
   cookie-auth works but listing it explicitly makes it future-proof
   against auth-cookie expiry and prevents per-second 429s.

End-to-end test (unauthenticated):
  GET /api/v1/monitoring/stats  -> {cpu: 8.71, memory: 0.37, ...}
  GET /api/v1/health-checks/status -> {summary: {healthy:11, unhealthy:4, total:15}}
2026-06-18 21:17:16 -07:00
Krystie 4853f1feb8 fix(server): unbreak workflow engine init - import fetchT, new NotificationManager, hoist servicesStateManager
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Three cascading bugs in server.js's workflow engine init block:

1. fetchT was referenced but never imported from ./src/utils/http
2. notification-manager was called as factory function but the module
   now exports a class (NotificationManager) - need 'new'
3. servicesStateManager was referenced in workflowCtx but only created
   later inside an async IIFE (out of scope at workflow init time)

Result: every container start logged
  Workflow engine failed to initialize - fetchT is not defined
and the workflow engine never actually wired to resourceMonitor/
updateManager event sources. The 'app' context workflow engine
still ran but didn't get those connections.

Fix:
- Import fetchT at top of file
- Use 'new' for NotificationManager instantiation
- Hoist servicesStateManager creation before workflow init and
  remove the duplicate inside the health-checker async IIFE

Verified: container restart shows
  [server] Workflow engine initialized
  [ResourceMonitor] Workflow engine configured
  [UpdateManager] Workflow engine configured
in the log, no more errors at startup.

Also bumps VERSION to current SHA (bump from c64bbe2).
2026-06-18 20:15:23 -07:00
Krystie ef855e3fd7 build: bump SW cache to dashcaddy-shell-f6673e7190
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Forces clients to pull the rebuilt core.js bundle that includes
totp-recovery.js.
2026-06-18 19:57:38 -07:00
Krystie 3dff49cdc5 feat(status): TOTP recovery UI - panel, backup download, always-visible Import
- status/js/totp-recovery.js: NEW. Wires up recovery panel on the TOTP
  gate. Pastes Base32 -> /api/v1/totp/setup -> /verify-setup -> session.
  Exposes window._refreshRecoveryLink() called by totp-auth.js.
- status/js/totp-auth.js: showTotpOverlay() now calls
  _refreshRecoveryLink() so the recovery link hides when TOTP is healthy
  and appears when it's broken.
- status/js/totp-settings.js: removed setupSection.style.display='none'
  so 'Import existing secret' is always visible; added 'Download backup
  file' button after setup that exports the Base32 + recovery
  instructions as JSON.
- status/index.html: added 'Lost access? Recover with saved Base32
  key ->' link to the TOTP overlay plus the recovery panel itself;
  added title tooltip to the auth card reminding users to save the
  Base32 on first setup.
- status/build.js: include JS('totp-recovery.js') in the core bundle
  after totp-auth.js (since recovery registers a hook auth calls).
2026-06-18 19:56:52 -07:00
Krystie d230b39948 feat(totp): 4-part defense against permanent lockout
- credential-manager.js: add diagnose(key) method that distinguishes
  ok | missing | unreadable | corrupt instead of silently returning null
- crypto-utils.js: silent fallback to .encryption-key.bak when primary
  can't decrypt existing credentials; first-run bootstrap writes .bak;
  rotateKey() backs up old key before swap
- routes/auth/totp.js: new public /api/v1/totp/recovery-info endpoint
  returns {status, isSetUp, hint} so UI can show meaningful errors
- middleware.js: add /totp/recovery-info to PUBLIC_ROUTES so the
  locked-out user can read the diagnostic without being logged in
2026-06-18 19:56:45 -07:00
Hermes 7bbd969fa2 fix: rebuild bundle with widget, restore TOTP across container recreate, integrate auto-updater changes
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Three logical changes grouped:

1. Widget bundle rebuild + sami-files logo (from previous session)
   - status/dist/{init,core,features,onboarding}.js rebuilt from latest source
   - status/sw.js cache bumped to dashcaddy-shell-594ec75648 to force SW refresh
   - status/assets/sami-files.png added (Sami Files service card logo)

2. status/build.js: include monitoring-widgets.js in bundle
   - The original build.js was missing monitoring-widgets.js from its JS()
     bundle list — that's why the System Overview widget never showed up
     in the live init.js until we ran the live /var/www/dashcaddy-status/
     build.js. Now consistent.

3. dashcaddy-api/scripts/dashcaddy-update.sh restart_container(): preserve
   TOTP secret across container recreates
   - Was only setting SERVICES_FILE; container fell back to image-local
     /app/credentials.json + /app/.encryption-key (auto-generated fresh
     every recreate), which broke TOTP for the bind-mounted secret at
     /app/data/credentials.json
   - Added CREDENTIALS_FILE + ENCRYPTION_KEY_FILE env vars pointing at
     /app/data/ so the container reads from the bind-mounted host data dir
   - See skill: software-development/dashcaddy/references/totp-and-system-overview-pitfalls.md §9

4. Auto-updater integration (pulled from upstream release):
   - dashcaddy-api/VERSION: dev → c64bbe2
   - dashcaddy-api/health-checker.js, middleware.js, package.json,
     routes/backups.js, src/app.js: new release code (bundled workflows,
     /api/auth/ → /api/v1/ back-compat rewrite, backup storage limits)
2026-06-18 19:23:30 -07:00
Hermes 4f377970d7 chore: ignore runtime data + scratch files, remove dead root routes/
Working tree accumulated 172 untracked/modified files from the auto-updater:
- 19 secret/runtime files in dashcaddy-api/data/ that should never be tracked
- 199 byte-identical duplicates of tracked files dumped at root by an
  outdated rsync/cp step
- 6 scratch debug scripts (cm_check.js, login_test.js, full_test.js, ...)
- 7 .bak-* files from start.sh and dashcaddy-update.sh rollback branches
- Root-level routes/ directory: dead code, container COPYs dashcaddy-api/routes/

.gitignore now ignores:
  - dashcaddy-api/data/          (runtime: credentials, secrets, history)
  - start.sh.bak*, scripts/*.bak* (auto-updater rollback backups)
  - updates/                      (auto-updater runtime state)
  - cm_check*.js, *_test.js       (scratch debug scripts)

Removed dead code:
  - routes/openclaw.js            (replaced by dashcaddy-api/routes/openclaw.js)

Recreated runtime scripts that were deleted with their duplicates:
  - start.sh                      (canonical container-start, 47-line full config)
  - scripts/dashcaddy-update.sh was already untracked; fixed the tracked
    dashcaddy-api/scripts/dashcaddy-update.sh instead (see next commit)

Net change: 172 → 17 files in working tree.
2026-06-18 19:23:02 -07:00
Hermes 7f0d43943c feat: restore monitoring widget + add sami-files template
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
- Recreate status/js/monitoring-widgets.js with robust services count
  (reads from window.APPS, #cards DOM, then live fetch as fallback)
- Add sami-files service to data/services.json (Sami Files card)
- Add sami-files template to app-templates.js under 'Files' category
  with full systemd deployment docs and Caddy snippet
- Bundle monitoring-widgets.js into init.js
2026-06-18 18:52:48 -07:00
Krystie 9ab947a394 feat: enforceStorageLimit - prune oldest backups when maxStorageBytes exceeded 2026-05-28 15:14:59 -07:00
Krystie ad9400490d Merge: resolve conflict in routes/backups.js, keep storage-info + maxStorageBytes 2026-05-28 15:00:41 -07:00
Hermes ea9bdf9598 Backup data/ dir before update, restore on rollback
- Add backup_data_dir() and restore_data_dir() using rsync
- Data backed up to backups/{version}/data-backup/ alongside code
- restore_data_dir() called in all three rollback paths (build fail, restart fail, health check fail)
- Add restart_container() that does rm + run to apply new env vars
- Handle action=rollback explicitly (no new version deployment)
- Uses standalone docker build instead of compose for reliability
- Add start.sh at /opt/dashcaddy/start.sh for reboot survival
2026-05-28 02:34:27 -07:00
Hermes c52016d727 fix: backup and restore data/ dir on update and rollback
The data/ directory (services.json, config.json, credentials,
TOTP config, notifications) was never included in the update
backup. Every update wiped user data — services, licenses,
credentials — requiring manual restore.

Now the host-side updater:
- Backs up data/ alongside code files before any update
- Restores data/ on rollback (build failure, restart failure,
  or health-check failure)
2026-05-28 02:08:33 -07:00
Hermes 588188edb5 update UX: badge→modal flow, orange update button, Update All, toast notifications, workflow triggers 2026-05-27 23:57:32 -07:00
Hermes 11823a1466 feat: premium tier features — auto-backup scheduling, resource alerting, bundled workflows, one-click revert, notification manager v1.7.0 2026-05-27 23:39:46 -07:00
Hermes 6ce0a18f98 release: 1.6.0 — openclaw routes, docker.client fix, /apps/ path deduplication v1.6.0 2026-05-27 22:22:37 -07:00
Hermes e07375f642 fix: mount openclaw routes at /openclaw prefix + fix docker.client wrapper + strip duplicate /apps/ paths across sub-routers
- openClawRoutes was mounted at root causing /status vs /openclaw/status mismatch
- ctx.docker is a typed wrapper {client,pull,...} — all calls now use docker.client.*
- templates/deploy/removal/restore sub-routers had /apps/ hardcoded in inner routes
  causing double-stacking when mounted under /apps (→ /apps/apps/templates etc)
- openclaw.js: GET /status, POST /deploy, GET/POST /proxy/*, DELETE /
2026-05-27 22:20:21 -07:00
Hermes 17edb3bc90 Fix 5 critical security vulnerabilities
1. WebSocket exec auth bypass (exec.js): Require valid JWT or API key
   before accepting WebSocket upgrade. Reject unauthenticated requests
   with 401 before the upgrade completes.

2. Shell injection in router auto-login (session-handlers.js): Validate
   baseUrl against safe hostname pattern before embedding in wget shell
   command. Reject with null session if invalid.

3. Path traversal in credentials routes (services.js): Add explicit
   serviceId validation (alphanumeric + dash/underscore/dot, max 100
   chars) to all three credential endpoints. Removed redundant
   try/catch wrapper.

4. execSync injection in CA CSR generation (ca.js): Add sanitize step
   replacing any non-alphanumeric domain chars with underscore before
   interpolation into shell subj argument. Redundant with existing
   validation but provides defense-in-depth.

5. Auth bypass when TOTP disabled (middleware.js): Split the logic
   cleanly — disabled TOTP means no auth (initial setup state), enabled
   TOTP means all auth methods checked (session/JWT/API key). Removed
   the sessionDuration:never conflating shortcut.
2026-05-27 18:05:35 -07:00
Coderbot 445da9f5fc fix: cross-subdomain SSO auto-login for *arr services
- Set Domain=.sami on session + CSRF cookies so browsers send them to all subdomains
- This fixes Caddy forward_auth returning 401 for radarr/sonarr/prowlarr
- Fix login URL concatenation bug (radarr.samilogin -> radarr.sami/login)
- Fix getSetCookie() missing from _httpsFetch/_httpFetch response objects
- Fix array/string handling for set-cookie header in session-handlers fallback
- Refactor csrf-protection to createCSRFMiddleware() factory with cookieDomain support
- Pass renewCSRFToken through middleware deps chain to TOTP route
2026-05-23 16:15:56 -07:00
Coderbot fe0f52ce17 fix: services/status probe fails with self-signed certs when CA is missing in container
The /api/v1/services/status endpoint (dashboard card ON/OFF) uses an
HTTPS agent to probe each service. When /app/pki/root.crt is missing
inside the container, it fell back to new https.Agent() which rejects
self-signed certificates. This caused all .sami domain probes to fail
with UNABLE_TO_GET_ISSUER_CERT_LOCALLY, making dashboard cards randomly
flip between ON and OFF depending on whether the Pylon relay responded
before the 10s deadline.

Fix: use rejectUnauthorized: false as fallback when CA cert is absent.
2026-05-23 14:35:39 -07:00
Coderbot 8df5214a45 fix: fetchT() now handles self-signed HTTPS certs
- Node.js native fetch() (undici) cannot use rejectUnauthorized:false
- Added _httpsFetch() using raw https module for internal .sami endpoints
- Fixes quality profile fetch for Sonarr/Radarr (was returning "fetch failed")
- Also fixed corrupted proces..._KEY -> process.env.PYLON_KEY in pylon

Coderbot fix #1
2026-05-23 14:16:18 -07:00
SamiandClaude Opus 4.7 2457d30ed3 fix(installer): point dashcaddy_auth snippet at /api/v1/auth/gate
The 1.5.0 API cutover removed the legacy `/api` mount, but the
`dashcaddy_auth` Caddy snippet generated by the installer still called
`uri /api/auth/gate/{args[0]}`. forward_auth then hit the notFoundHandler
and propagated a DC-404 to the browser instead of a 401-redirect to the
login flow (seen on requests.sami).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 01:33:50 -07:00
Sami a3ec1ffbb3 chore(release): bump to 1.5.0 2026-05-17 11:39:13 -07:00
SamiandClaude Opus 4.7 d36705bd90 feat: 1.5.0 prep — API v1 cutover, LICENSE, CHANGELOG, CI
- Remove legacy /api/ mount; all routes now under /api/v1/ only
- Update path matchers (CSRF excludes, public routes, audit log, rate limits)
- Move standalone routes (/api/network/ips, /api/docs, /api/docs/spec) to v1
- Update openapi.yaml (110 paths), CA pages, and 4 lingering frontend files
- Add LICENSE (proprietary EULA), CHANGELOG.md (Keep a Changelog format)
- Add .gitea/workflows/ci.yml (test+lint and security audit jobs)
- Fix 9 pre-existing no-empty lint errors so CI starts green
- Drop ad-hoc scratch reports and *.bak files from repo root

All 739 jest tests pass. Lint is clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 11:38:45 -07:00
Sami cd8ccaba2b chore(release): bump to 1.4.10 2026-05-17 02:44:40 -07:00
Sami fd2e906963 fix(release): stage build-rewritten files (sw.js, index.html) in release.sh
build.js rewrites three things during `node build.js`:
  - status/dist/*.js (bundle output)
  - status/index.html (CSP hash for inline bootstrap)
  - status/sw.js     (cache name derived from bundle content)

release.sh was only staging status/dist/. Result: when a release didn't
touch index.html or sw.js source, the post-build modifications to those
two files were left unstaged, the commit included only dist/, and the
tarball shipped the stale sw.js. Clients then kept the previous SW
cache name -> activate handler never wiped the cache -> precached old
bundles served forever even after they were "updated" on disk.

Now stage index.html and sw.js too. They're tracked (not gitignored)
so a plain `git add` is enough; the commit is a no-op when nothing
actually changed.
2026-05-17 02:44:35 -07:00
Sami 68bcc0cb5f chore(release): bump to 1.4.9 2026-05-17 02:34:56 -07:00
Sami 7e4c3a0963 fix(frontend): container-logs misuse of wireModal blocked rest of features.js
container-logs.js called `wireModal(modal, null, closeModal)` — passing
the local `closeModal()` function as a third arg where wireModal expects
button elements. wireModal then did `closeModal.addEventListener('click',...)`,
threw TypeError, and because each module's IIFE is a top-level statement
in the concatenated features.js bundle, every IIFE *after* container-logs
silently skipped: snapshot, smart-arr-connect, notification-settings,
panel-tabs, backup-restore, resource-monitor, health-check, update-
management, docker-resources, compose-import, container-exec, audit-log,
weather, clock, card-badges, theme-builder, and license. Symptoms:
"Customize Theme" did nothing on click, license badge stuck at "FREE TIER"
(because license.js never ran), no weather, etc.

- container-logs.js: drop the wireModal call, wire backdrop click directly
  to the local closeModal so the SSE log stream actually stops on close.
- globals.js: harden wireModal — skip any closeBtn that isn't a real
  EventTarget. One typo upstream shouldn't take down the rest of features.js
  init silently.
2026-05-17 02:34:51 -07:00
Sami ac723630f2 chore(release): bump to 1.4.8 2026-05-17 02:20:41 -07:00
Sami 49c8ecfb73 fix(build): compute CSP hash on LF-normalized index.html
When the build runs on a Windows checkout, fs.readFileSync returns the
file with CRLF intact, and the hash of the inline bootstrap script's
body reflects those CRLFs. The release tarball / git transport / Linux
file system strip CRLF on the publishing host, so the browser sees the
LF-only version and computes a different sha256. CSP then blocks the
script — disabling the version widget, theme switcher, and any other
DOM bindings set up in that inline block.

Normalize CRLF -> LF before computing the hash (the on-disk file keeps
its native line endings; only the hash input is normalized). The CSP
allowlist now matches whatever Caddy actually serves.
2026-05-17 02:20:36 -07:00
Sami 939f95d147 chore(release): bump to 1.4.7 2026-05-17 02:03:36 -07:00
Sami bab5105e48 fix(frontend): unbreak dashboard — bundle order, IIFE close, dup const
Three merge-fallout bugs that combined to leave the services grid empty
and most UI inert:

1. error-handler.js was bundled into onboarding.js (loaded 3rd), but
   globals.js in core.js (loaded 1st) does `const errorHandler = new
   ErrorHandler()` at top level. ErrorHandler was undefined when core.js
   ran -> ReferenceError -> globals.js stopped, so window.APPS,
   _showTotpOverlay, loadServices, etc. were never set, and init.js
   blew up on every call into core's exports.

   Moved error-handler.js to the start of the core.js bundle so the
   class is on window before any other script touches it.

2. setup-wizard.js also declared `const errorHandler = new ErrorHandler()`
   at top level. Classic scripts share the document's top-level lexical
   environment, so this collided with globals.js's declaration ->
   redeclaration SyntaxError in features.js. Removed setup-wizard.js's
   copy; it picks up the global one.

3. tooltip-definitions.js closed its `(function(window){...})(window);`
   IIFE at line ~171 ("Validation module loaded"), then the TOOLTIP_
   DEFINITIONS array, getter helpers, window.TooltipDefinitions export,
   and final `debug(...)` log all sat at top level — outside the IIFE,
   where `debug` was no longer in scope. Removed the early close and
   added one at EOF so the whole file is in one IIFE.
2026-05-17 02:03:31 -07:00
Sami f9dad0abb4 chore(release): bump to 1.4.6 2026-05-17 01:41:52 -07:00
Sami ebfc3be9d1 fix(build): derive sw.js cache tag from bundle content hash
The service worker uses staleWhileRevalidate on /dist/*, so after a
release it would serve old bundles from cache indefinitely (cache is
only wiped when the cache *name* changes, which was hardcoded to
'dashcaddy-shell-v10'). Result: dashboard appears unchanged after a
self-update until the user manually unregisters the SW.

build.js now hashes the concatenated dist bundles and writes
`dashcaddy-shell-<10-hex-chars>` into sw.js. Any change in dist/
produces a fresh cache name; on the next page load the SW's activate
handler deletes all older caches and the new bundles are fetched.
2026-05-17 01:41:47 -07:00
Sami 3878509fc5 chore(release): bump to 1.4.5 2026-05-17 01:29:19 -07:00
Sami d7804d6b68 fix(updates): route frontend deploy through host-side updater
When DashCaddy is installed without `${DASHBOARD_DIR}:/app/dashboard` bind
mounted into the container (e.g. legacy DNS2 setup where Caddy serves from
/var/www/dashcaddy-status/), the self-updater's in-container copy to
/app/dashboard was a silent no-op — leaving the dashboard stale across
self-updates, which led to CSP-hash mismatches and a broken UI.

- self-updater: new hostFrontendDir option (default `/var/www/dashcaddy-status`
  on Linux, overridable via DASHCADDY_HOST_FRONTEND_DIR). When set, defer the
  frontend copy to the host-side updater by passing frontendStagingDir +
  frontendTargetDir in trigger.json. Now also includes `js/` in the copy list.
- dashcaddy-update.sh: read those new trigger fields and sync the dashboard
  files on the host. Auto-detect fallback for older self-updaters (no fields
  in trigger.json) so a single release upgrade self-heals.
2026-05-17 01:29:07 -07:00
Sami 5b12c5c9c0 chore(release): bump to 1.4.4 2026-05-16 23:55:17 -07:00
Sami 7e23cb5b06 fix(updates): allow notify endpoint past CSRF + portable JSON parse in release.sh
- csrf-protection: skip CSRF validation on /api/system/update-notify. The
  endpoint has its own X-DashCaddy-Notify-Secret auth and is only ever called
  machine-to-machine; browsers never reach it. Without this, the CSRF cookie
  check rejects the notify POST before the secret comparison runs.
- release.sh: the verify step piped curl into `node -p ".../dev/stdin"` which
  works on Linux but blows up on Windows/git-bash. Replaced with portable
  grep+sed extraction so the same script works on both publisher OSes.
2026-05-16 23:55:08 -07:00
Sami 850db40479 chore(release): bump to 1.4.3 2026-05-16 23:47:34 -07:00
Sami c66fe498b6 feat(updates): seamless release flow — push-notify, VERSION copy, robust mirror
- self-updater: per-instance notify secret (auto-generated), notifyAndApply()
  triggers an immediate check+apply for the publishing host
- routes: POST /api/system/update-notify (X-DashCaddy-Notify-Secret gated,
  added to public-routes allowlist so TOTP doesn't block machine-to-machine)
- dashcaddy-update.sh: include VERSION in backup/deploy/rollback copy lists;
  belt-and-suspenders write trigger.json commit to VERSION post-deploy.
  Fixes drift where /app/VERSION stayed at the old commit after self-update.
- release.sh: mirror failures are non-fatal+loud; HTTP-verify get2 after
  rsync; auto-notify co-located instance via /opt/dashcaddy/updates/notify-secret
  (or honour DASHCADDY_NOTIFY_TARGETS for multi-instance setups).
2026-05-16 23:46:53 -07:00
Sami edac587c5c Merge branch 'main' of http://100.98.123.59:3000/sami7777/dashcaddy
# Conflicts:
#	status/dist/features.js
2026-05-16 22:52:07 -07:00
Sami 824313c411 chore(release): bump to 1.4.2 2026-05-16 22:36:30 -07:00
Sami d3cef9ed86 chore(release): bump to 1.4.1 2026-05-16 00:34:17 -07:00
Krystie 77688daec7 Add service filter, batch operations, and snapshot features
- Service Filter Bar: search by name, filter by status (online/offline)
- Batch Operations: multi-select containers for start/stop/restart
- Container Snapshots: create and manage Docker checkpoints
- Added filter bar and batch action bar to index.html
- Added snapshot button to Admin tools section
- New JS modules: service-filter.js, batch-operations.js, snapshot.js
- Updated build.js to include new modules in bundle
2026-05-15 02:17:24 -07:00
Krystie 0cec447bf1 Expose openContainerLogsModal function for service card buttons
- Added window.openContainerLogsModal(containerId, containerName) function
- Service cards (grid.js) already call this when clicking the 📋 logs button
- Modal now pre-selects the correct container when called from a card
- Rebuilt dist files
2026-05-15 01:51:51 -07:00
Krystie c50b106faf Add Container Log Viewer UI with streaming, search, and download
- New container-logs.js module for viewing Docker container logs
- Integrated with existing API endpoints (/logs/containers, /logs/container/:id, /logs/stream/:id)
- Features:
  - Select container from dropdown
  - View logs with stdout/stderr color coding
  - Real-time log streaming via SSE
  - Search/filter within logs
  - Download logs as text file
  - Line count and filter indicators
- Added '📜 Container Logs' button to Tools section in index.html
- Added to features.js bundle via build.js
- Rebuilt dist files
2026-05-15 01:27:56 -07:00
Krystie 22c48076c0 Merge remote changes - resolve conflicts: keep remote package.json v1.4.0, keep local self-updater.js logic, features.js regenerated by build 2026-05-14 21:08:20 -07:00
Krystie 947007438f Update: version 1.2.0, new version UI features, CSP hash auto-update, bug fixes 2026-05-14 21:04:35 -07:00