# Changelog

All notable changes to DashCaddy are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- **Auto-login page served from API (`GET /api/v1/auth/login-page?service=<id>`).** Chat, Plex, Jellyfin, and Emby auto-login pages are now generated by the API instead of living as 5 KB inline HTML blobs inside Caddyfile `respond` blocks. Caddyfile blocks shrink from ~50 lines to 3. Future login-page changes deploy with the container, no `caddy-apply` needed.

### Fixed
- **SSO cookie placeholder bug.** `dashcaddy_auth` Caddy snippet had `header_up Cookie {http.request.cookie}` — an invalid placeholder that resolved to empty string at runtime, silently clearing the session cookie before it reached the `forward_auth` gate. SSO worked only via the IP-session fallback (same-IP). Removed the line; Caddy's `forward_auth` forwards all original request headers automatically.
- **Jellyfin/Emby `merge()` syntax error.** `try` block in the auto-login page's `merge()` helper was missing its closing `}` before `catch`, causing a JS syntax error in the browser that silently broke localStorage token merging.

### Changed
- **CLAUDE.md rewrite.** Was describing the old Windows-local `C:/caddy/` + `caddy-api/` layout. Now accurately documents DNS2 as production (`/opt/dashcaddy/`, `caddy-apply`, correct Tailscale IP, SSO architecture).
- **`.gitignore` coverage.** Runtime-generated data files (`audit-log.json`, `backup-history.json`, `credentials.json`, `health-history.json`, etc.), cert directories (`generated-certs/`, `pki/`), and root-level test scripts now ignored.

## [1.14.0] - 2026-06-28

### Security
- **TOTP recovery system (4-part defense against permanent lockout).** Pre-lockout: `.bak` fallback credentials file checked at every TOTP init, used silently when primary fails. Diagnostic: `/recovery-info` endpoint + `/recovery-panel` UI on the entry screen with one-click "Import Backup" + "Download Backup" buttons. Post-lockout: friction-free `.license-secret` restore flow. (`d230b39`, `3dff49c`, `7bbd969`)

### Added
- **Kubernetes-standard health probe aliases (DC-012).** Added `/healthz` and `/readyz` as root-level aliases for `/health/live` and `/health/ready` so fresh users can copy-paste `healthcheck:` blocks from k8s/Docker docs. Liveness (`/healthz`) is a pure process check — no I/O. Readiness (`/readyz`) checks the config file, services file, Docker daemon, and Caddy admin API (3s timeout each), returning 200 if all OK or 503 with a `checks` object detailing failures. Both endpoints are unauthenticated by design (orchestration tooling doesn't carry session cookies). Probe endpoints also bypass CSRF validation and are excluded from per-request logging so k8s polling every 10s doesn't flood the audit log. Added `__tests__/health-probe-aliases.test.js` (19 tests) — covers alias equivalence, the removed `/api/v1/health` returning 404, and a source-of-truth sync test that detects drift between `src/app.js` mount list and `src/utilities/middleware.js` allowlist. README and user-guide updated with copy-paste `docker-compose.yml` and Kubernetes probe blocks. Also: audited the cross-platform standardization doc's "What's Still Open" section — all four items previously listed as remaining work (config schema migration, monitoring endpoint opt-in, CSRF path duplication, per-call fetchT timeouts) were already implemented in earlier v1.13.x audit passes but never marked done. Doc updated with pointers and Pitfall 20 added ("Audit Doc Lists Items That Are Already Done") so future agents don't redo the work.
- **OpenClaw routes** — full set under `/openclaw` prefix: connect, disconnect, status, host discovery. `docker.client` wrapper fixed; duplicate `/apps/` paths stripped across sub-routers.
- **Auto-backup scheduling (premium tier)** + storage-limit enforcement (prune oldest when `maxStorageBytes` exceeded) + restore-from-backup on update rollback. Bundled workflows included out-of-the-box.
- **Monitoring widget on main dashboard** — CPU/mem data flattened, health summary added; `/api/monitoring/stats` exposed as a public route with rate-limit.
- **Sami Files template** — logPath wired into the template and mounted in `start.sh`.
- **Unified logger** — single source of truth for logs, errors, and audit events.
- **Notification manager + resource alerting** (premium tier).
- **Update UX** — badge→modal flow, orange update button, "Update All", toast notifications, workflow triggers.
- **Comprehensive test suite additions:** 7 new test files (`dns-propagation`, `notification-manager`, `ssl-monitor`, `log-digest`, `metrics`, `config-drift-detector`, `auto-restart-manager`) — 120 new tests, all passing.

### Changed
- **Route response standardization (DC-010).** Every `{success, ...}` envelope across 9 route files now flows through `response-helpers` (`success()` / `ok()`). Only 2 intentional raw-array calls remain (`routes/services.js` lines 360+368 — frontend wire contract). Error-path envelopes use `error()` separately. ~62 calls converted across `browse/logs/sites/updates/notifications/tailscale/events/workflows/openclaw/dns/health/ca`.
- **`/api/v1/` versioning:** all routes mounted under `/api/v1/`. Legacy un-versioned `/api/` mount removed. Frontend, OpenAPI spec, DashCA pages, and all internal path matchers (CSRF exclusions, auth public routes, audit log, rate-limit mounts) updated.
- **`scripts/release.sh`** now stages build-rewritten files (`sw.js`, `index.html`) for the published tarball, copies `VERSION` into the tarball, and writes both `dashcaddy-api/package.json` AND root `VERSION` on every release. No more version drift.

### Fixed
- **Credential route path regression (DC-011).** `routes/services.js` had dropped the `/services/` prefix from credential routes (POST/DELETE/GET) during a refactor, causing 4 test failures and a live 404. Re-applied the prefix; also fixed a latent `ReferenceError` where invalid serviceIds called `ctx.errorResponse()` in a factory-destructured module (replaced with the imported `errorResponse` helper).
- **19 ESLint warnings (DC-004).** Reached zero warnings across `src/` — most cleared by the refactor, the final 3 (`require-await` on `resyncHealthChecker`, two `max-depth` violations) fixed in `src/app.js`.
- **Workflow engine init broken** — `fetchT` not imported, `NotificationManager` constructor missing `new`, `servicesStateManager` not hoisted. Fixed; events now fire on startup.
- **Container-logs feature was misusing `wireModal`** — short-circuited the rest of `features.js` and broke unrelated dashboard features. Replaced with the correct wiring.
- **CSP hash mismatch** between Windows and Linux builds — now computed on LF-normalized `index.html` so hashes are identical across platforms.
- **SW cache tag** now derived from bundle content hash, so the service worker invalidates correctly when bundle content changes.
- **Updater false-positive loop** when commit hash was unknown — fixed.
- **Logger.error() swallowed the writeErrorLog promise (DC-018).** `Logger.error()` called `this._log('error', ...)` but dropped the return value, so the async error.log disk write was fire-and-forget. Every `await logError(...)` / `await log.error(...)` caller (6 route handlers + the global Express error catcher) was awaiting `undefined`. This caused a flaky `logging.test.js` in the full suite and could lose error-log entries on fast process exit/restart. One-line fix: `return this._log(...)`.
- **Flaky backup-manager tamper test (DC-019).** The "rejects tampered data (auth tag mismatch)" test corrupted the encrypted blob by replacing its first base64 char with `'X'`; when the random IV's first base64 char was already `'X'` (~1/64 chance), the replacement was a no-op and decryption succeeded. Now corrupts the authTag byte directly (XOR `0xFF`) so the tamper is guaranteed to differ.

### Removed
- **Dead `/api/v1/health`, `/api/v1/health/live`, `/api/v1/health/ready` routes** (DC-012) — these were registered in `PUBLIC_ROUTES` and CSRF exclusion lists but never actually mounted on the apiRouter. Consolidated to root-level `/health`, `/health/live`, `/health/ready` plus new `/healthz` and `/readyz` aliases. Anyone probing `/api/v1/health` will now get a clean 404 instead of an unexpected behaviour.
- Stale ad-hoc test/debug scripts (`comprehensive-test.js`, `test-security-fixes.js`) moved to `dashcaddy-api/scripts/legacy/` (preserved, not deleted — 875 lines of security test coverage retained as a manual smoke test).
- Stale root-level files: `*.bak`, `server-old.js`, and ad-hoc reports (`DEPLOYMENT-SUCCESS.md`, `FINAL-DEPLOYMENT-REPORT.md`, `DESLOPIFICATION-ROADMAP.md`, etc.) — disk-only cleanup, already gitignored.
- Dead `routes/` directory at API root (replaced by `src/routes/`).

### Security (TOTP integration)
- TOTP integration tests now cover the full `/api/auth/check` → session → endpoint flow (DC-006). 25 new tests including: `setup` (generate + normalize + reject invalid Base32), `verify-setup` (missing/bad/no-pending/valid-code paths), `verify` login (400/400/401/200), `check-session` (passthrough when disabled + 401 no-session + 200 valid-session), `disable`, `config` (valid/invalid/never-disables), and full end-to-end setup→login→check-session→disable.

### Fixed (from merge)
- **routes/updates.js** — krystie's branch had `if (!ok)` referencing the helper function instead of the `secretOk` boolean. Would have 500'd every `/system/update-notify` request. Caught during merge, kept my version with the correct boolean check.
- **routes/notifications.js** — two places where she replaced `res.json({success: result.success, ...})` with `ok(...)` would have forced `success: true` for partial-failure delivery. Kept my version with explicit `res.json` to preserve the semantic.

## [1.13.4] - 2026-06-12

### Changed
- Standardized all route handler responses to use helpers from `src/utils/responses.js`
  (`ok`, `errorResponse`, `successMessage`, `notFound`, `validationError`, `forbidden`,
  `unauthorized`, `conflict`). ~160 raw `res.json()` calls converted across 32+ files.
  No behavior changes — response shapes are identical. This ensures future schema
  changes (e.g., adding a `requestId` envelope) only need to update one module.
- Fixed `error` vs `errorResponse` signature mismatch in `routes/health.js` CA cert
  endpoint. The `error` helper takes `(res, message, statusCode)` while `errorResponse`
  takes `(res, statusCode, message, extras)` — the wrong alias was being used for
  calls that needed the 4-argument form.
- Updated `middleware.js`, `csrf-protection.js`, `error-handler.js`, and
  `license-manager.js` to use response helpers for rejection/error responses
  instead of inline `res.status().json()`.

### Note
- 4 pre-existing test failures in `services.routes.test.js` (credential storage)
  remain from before this release. They are unrelated to the standardization pass.

## [1.5.0] - 2026-05-17

### Changed (BREAKING)
- API routes now mounted exclusively under `/api/v1/`. The legacy un-versioned
  `/api/` mount has been removed. Frontend, OpenAPI spec, DashCA pages, and
  all internal path matchers (CSRF exclusions, auth public routes, audit log,
  rate-limit mounts) updated accordingly. **Existing integrations that hit
  `/api/...` directly must update to `/api/v1/...`.** Held at minor bump
  (1.5.0) rather than major (2.0.0) — DashCaddy is still pre-1.0-API-stable.

### Added
- `LICENSE` (proprietary EULA) at repo root.
- `CHANGELOG.md` (this file) — Keep a Changelog format.
- Gitea Actions workflow ([.gitea/workflows/ci.yml](.gitea/workflows/ci.yml))
  that runs `npm test` (with coverage) and `npm run lint` on every push to
  `main`/`master` and on PRs, plus a `security` job running `npm audit` and
  the security-focused test subset.

### Fixed
- 9 pre-existing `no-empty` ESLint errors in `backup-manager.js` and
  `routes/backups.js` (intentional ignore-failure catches now annotated).

### Removed
- Stale files at repo root: `*.bak`, `server-old.js`, and ad-hoc
  deployment/migration/test reports (`DEPLOYMENT-SUCCESS.md`,
  `FINAL-DEPLOYMENT-REPORT.md`, `DESLOPIFICATION-ROADMAP.md`,
  `error-handling-*.md`, `WHAT-IS-DASHCADDY.md`, etc.). Already gitignored —
  disk-only cleanup.

---

## [1.4.10] - 2026-05-17

### Fixed
- `release.sh` now stages build-rewritten files (`sw.js`, `index.html`) so
  they're included in the published tarball.

## [1.4.9] - 2026-05-17

### Fixed
- Container-logs feature was misusing `wireModal`, which short-circuited the
  rest of `features.js` and broke unrelated dashboard features.

## [1.4.8] - 2026-05-17

### Fixed
- CSP hash now computed on LF-normalized `index.html` so Windows and Linux
  builds produce identical hashes.

## [1.4.7] - 2026-05-17

### Fixed
- Dashboard unbroken: corrected bundle order, closed dangling IIFE, removed
  duplicate `const` declaration.

## [1.4.6] - 2026-05-17

### Fixed
- `sw.js` cache tag now derived from bundle content hash, so service worker
  invalidates correctly when bundle content changes.

## [1.4.5] - 2026-05-17

### Fixed
- Frontend deploy routed through the host-side updater (matches the API
  container's own update path).

## [1.4.4] - 2026-05-16

### Fixed
- `notify` endpoint exempted from CSRF (it's called by the host-side updater,
  not the browser).
- `release.sh` JSON parsing made portable (no longer assumes GNU `jq`
  semantics on every host).

## [1.4.3] - 2026-05-16

### Added
- Seamless release flow: push-notify endpoint, VERSION file copy into
  release tarball, robust SSH mirror handling on port 22022.

## [1.4.2] - 2026-05-16
## [1.4.1] - 2026-05-16

### Changed
- Version bump only — packaging plumbing for the 1.4.x release line.

## [1.4.0] - 2026-05-06

### Added
- `scripts/release.sh` — one-command release cutting and publishing.

---

## [1.3.1] - 2026-05-06

### Fixed
- Installer: added `src/` directory to the deploy manifest; dropped
  `MakeDirectory=yes` from the systemd updater path unit.
- Self-updater: copies `src/`, replaces `routes/` in place instead of
  nesting it inside the existing tree.

## [1.3.0] - 2026-05-06

### Added
- Self-updater supports `DASHCADDY_API_SOURCE_DIR` env override for
  non-standard deploy layouts.

### Fixed
- Self-updater now clears *all* pending history entries, not just one.

---

## [1.2.0] - 2026-05-14

### Added
- Container Log Viewer with streaming, search, and download.
- Service filter, batch operations across multiple services, and snapshot
  capture.
- Auto CSP hash updates during build.
- Dashboard version button and self-update UI wiring.
- Release policy checks and dashboard version verification.

### Changed
- All routine `console.log` calls gated behind `window.DASHCADDY_DEBUG`
  flag for quieter production output.
- All `console.error` calls routed through `ErrorHandler` for consistent
  tracking.

### Fixed
- Updater no longer triggers a false-positive "update available" loop
  when commit hash is unknown.

---

## [1.1.5] - 2026-03-23

### Added
- Pylon health relay for remote service health checks (with relay
  fallback on `/probe/:id`).
- Host-side auto-updater for zero-touch API container rebuilds.

### Fixed
- Service edit preserves service ID on subdomain change; accepts
  `localhost` as a valid IP.
- Taxi theme accent color now distinct from text.
- Prevents encryption key conflicts; adds license backup on rotation.

## [1.1.1] - 2026-03-23

### Fixed
- Service edit, CSRF token stability, and license restore.

---

## [1.0.x] - 2026-03-05 → 2026-03-22

Initial release line. Highlights from work between v1.0 and v1.1:

### Added
- Cross-platform path support (Windows + Linux deployments).
- Subdirectory routing mode for public-domain deployments.
- Auto-update system for DashCaddy instances.
- Batched status endpoint (frontend performance).
- Install-wide onboarding tour (no longer per-browser).
- Daily log digest and Docker hygiene/maintenance.
- Unified backup/restore v2.0 with full state capture.
- DNS uptime bars and fully-dynamic DNS server config.

### Changed
- Phase 1-3 refactor: extracted config/context/utils into `src/`, split
  monolithic `server.js`, standardized all 25+ route files with explicit
  dependency injection.
- Unified error handling system (throw-based, migrated 25 route files).
- ESLint + Prettier baseline with auto-fixes.

### Security
- 7 critical + 16 high/medium API security bugs fixed.
- 7 frontend security vulnerabilities fixed (4 critical, 3 high).
- Logger sanitization to prevent log injection.

### Tests
- Comprehensive test suite reaching 80%+ coverage threshold.
- `docker-security` test suite (41 tests).
- `auth-manager` and `credential-manager` test suites.

## [1.0.0] - 2026-03-05

Initial release of DashCaddy. Unified dashboard for Docker container
management, Caddy reverse proxy configuration, DNS automation, and SSL
certificate provisioning.

[Unreleased]: ../../compare/v1.5.0...HEAD
[1.5.0]: ../../compare/v1.4.10...v1.5.0
[1.4.10]: ../../compare/v1.4.9...v1.4.10
[1.4.9]: ../../compare/v1.4.8...v1.4.9
[1.4.8]: ../../compare/v1.4.7...v1.4.8
[1.4.7]: ../../compare/v1.4.6...v1.4.7
[1.4.6]: ../../compare/v1.4.5...v1.4.6
[1.4.5]: ../../compare/v1.4.4...v1.4.5
[1.4.4]: ../../compare/v1.4.3...v1.4.4
[1.4.3]: ../../compare/v1.4.2...v1.4.3
[1.4.2]: ../../compare/v1.4.1...v1.4.2
[1.4.1]: ../../compare/v1.4.0...v1.4.1
[1.4.0]: ../../compare/v1.3.1...v1.4.0
[1.3.1]: ../../compare/v1.3.0...v1.3.1
[1.3.0]: ../../compare/v1.2.0...v1.3.0
[1.2.0]: ../../compare/v1.1.5...v1.2.0
[1.1.5]: ../../compare/v1.1.1...v1.1.5
[1.1.1]: ../../compare/v1.0.0...v1.1.1
[1.0.0]: ../../releases/tag/v1.0.0
