Commit Graph
16 Commits
Author SHA1 Message Date
Hermes 82f14ba663 Update CHANGELOG with all P3-P5 features (DC-076 through DC-108)
CI / Test & Lint (push) Canceled after 0s
CI / Security audit (push) Canceled after 0s
2026-08-12 13:11:07 -07:00
Hermes a21e06bf5b [grade=B] DC-098: Update CHANGELOG with production-grade hardening sprint
CI / Test & Lint (push) Canceled after 0s
CI / Security audit (push) Canceled after 0s
Document all 13 items shipped this session in Keep a Changelog format.
Added section covers Prometheus, system/health, CI/CD, Dependabot, workflow
retry, debug logger, billing E2E test. Changed section covers cmd injection,
crypto IDs, console sweep, Docker limits, multi-stage Dockerfile, source maps.
2026-08-12 05:52:48 -07:00
Krystie d9e61ce1b7 DC-053: Public share links + Tailscale-mediated share (Pro-gated)
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
- Share-store: HMAC-signed tokens bound to serviceId+kind, persistent
  signing secret in dataDir/.share-secret, atomic writes, auto-prune
- Routes: admin endpoints gated on licenseManager.isPro() (402 Free);
  public endpoints CSRF-exempt (token IS proof)
- Tailscale path: mints single-use ephemeral pre-auth key, emails
  join link, rolls back share record if createAuthKey throws
- Email-failure path: exposes urlPath for manual delivery fallback
- 53 new tests (24 store + 29 routes), full suite 1372/1372
- Drift-test parser hardened against quoted-word comments
- share-store dataDir resolver handles Proxy/function values

CHANGELOG + BACKLOG updated.
2026-07-21 00:45:46 -07:00
hermes 321334cd33 DC-048: multi-user bootstrap + admin invites (opt-in)
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Implements the user-store + invite-store + admin routes. The whole
system is opt-in via siteConfig.authProviders.email.enabled = true;
single-user TOTP-only installs see zero behavior change.

Backend:
- src/security/user-store.js: users + allowlist + bootstrap sentinel,
  atomic writes, last-admin protection, defensive dataDir resolver.
- src/security/invite-store.js: single-use tokens (SHA-256 hashed on
  disk), TTL, auto-prune, defensive dataDir resolver.
- routes/auth/admin.js: /me, /admin/users (CRUD), /admin/allowlist,
  /admin/invites (CRUD), public /invites/:token (peek + accept).
- routes/auth/index.js: wires userStore, gates admin router on
  email auth being enabled.
- src/auth/providers/email.js: verify() enforces allowlist, creates
  user record, tags req.user; default-enabled flipped to opt-in.
- src/auth/providers/totp.js: bootstraps system@totp.local admin on
  first verify so current DNS2 operator shows in /admin/users.
- src/security/audit-logger.js: middleware adds userId/userEmail/
  userRole/viaProvider to log details when req.user is tagged.
- PUBLIC_ROUTES + CSRF allowlists updated for invite redemption.

Frontend:
- status/js/admin.js: modal overlay with users list (role-edit,
  delete), invite form (email/role/TTL), copy-link button,
  outstanding-invites list with revoke. Exports window.AdminPanel.
- status/js/core/init.js: calls AdminPanel.attachTrigger so the
  Admin button only appears when /me returns isAdmin=true.

Tests: 35 new tests across 3 files (user-store, invite-store, auth
multistore integration). Full suite: 1298/1298 passing.

Docs: BACKLOG.md marks DC-048 done. CHANGELOG.md [Unreleased]
section gets the DC-048 entry.
2026-07-20 17:44:11 -07:00
Hermes Agent bd480a69a7 BACKLOG + CHANGELOG: mark DC-049 done
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Track record of the auth-gate UI work plus the historical delta from
DC-046/047/050/049 commit chain. No code changes.
2026-07-20 02:23:26 -07:00
Hermes Agent c619d3a36b DC-046 DC-047 pluggable auth providers + email magic link
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Pluggable AuthProvider framework for any future auth method (OIDC, SAML,
passkeys) to plug in without touching the auth path again. Two
implementations ship:

  * TOTP — refactored from routes/auth/totp.js into src/auth/providers/totp.js
    as one AuthProvider impl. Legacy /api/v1/totp/* routes stay mounted for
    back-compat; new /api/v1/auth/login/totp/* routes use the new shape.

  * EmailMagicLink — src/auth/providers/email.js. Initiate issues a 32-byte
    base64url token, stores its SHA-256 hash in data/email-tokens.json
    (atomic lockfile-based mutation, automatic TTL cleanup), and delivers via
    nodemailer if providers.email.{host,port,username,password} is set OR
    falls back to log.info('auth', 'email magic link issued', ...) for dev.
    Verify accepts the token, marks it used, creates the same DashCaddy
    session cookie that TOTP uses (single global cookie model).

createAuthProviderRegistry() composes both implementations and exposes
them via /api/v1/auth/login/{methods, :provider/initiate, :provider/verify,
recovery-info} and /api/v1/auth/disable/:provider. PUBLIC_ROUTES + CSRF
exemptions updated to use :provider placeholder (parameterized for future
providers).

Test fix: src/utilities/middleware.js PUBLIC_ROUTES and csrf-protection.js
both switched to the :provider form because the prior literal 'totp'
wouldn't match the parameterized mount path Express 4.22 produces.

Test fix: __tests__/public-routes-drift.test.js extractMountPath() was
broken for Express 4.22's new ^/path/?(?=/|$) source format (no \?\?
terminator in the literal-mount case). Rewrote the parser to normalize
escaped slashes + trailing lookaheads instead of relying on regex
matching against the raw source.

New: __tests__/auth-provider-registry.test.js — 9 tests covering registry
composition, getProvider round-trip, listEnabled no-secrets-leak guarantee,
enabled-flag respect, listAll vs listEnabled distinction, email provider
dev-console fallback (token written to JSON store + log.info with
deliveredVia: 'dev-console' + response masked), verify rejects unknown
tokens via AuthenticationError.

Tests: 1241/1241 passing across 46 suites (was 1232; +9 new).

DNS2 deploy: this commit + bump VERSION to 1.16.0 + publish tarball to
get.dashcaddy.net + docker build + bash start.sh. The image-layer migration
from DC-050 also runs on first container recreate post-merge.
2026-07-20 01:40:33 -07:00
Hermes Agent 894e091335 DC-050 harden dataDir + add image-layer migration
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Three-part fix for the silent data-loss failure mode that survives DC-039:
If SERVICES_FILE env was unset, platformPaths.dataDir resolved to /etc/dashcaddy
(image-layer path), and audit/license/error logs would silently land there and
vanish on every container recreate.

1. platform-paths.assertSafe({mode:'production'}) — throws FATAL on forbidden
   zones (/app/src,routes,scripts,utils,managers,security + /etc/* + /usr + /var).
   Bypassed with SKIP_DATA_DIR_GUARD=1.
2. server.js calls assertSafe() before any runtime work.
3. start.sh one-time migration: scans 6 known image-layer zombie paths,
   copies non-empty content to bind mount with 'migrated-' prefix,
   gated by sentinel file. Survives set -e per-file failures.

19/19 platform-paths tests + 5/5 shell migration tests.
Suite: 1066/1067 (1 pre-existing public-routes-drift failure from in-flight
auth refactor, untouched by this commit).

Verified live on DNS2: live audit log at /app/data/audit-log.json (315KB,
active) is unaffected; vestigial 2-byte /app/src/security/audit-log.json +
140KB /app/src/utils/error.log (pre-DC-039 era) will be recovered on next
container recreate.
2026-07-20 00:53:05 -07:00
Krystie fb8942a3fa chore(release): bump to 1.15.0 — DC-042/043 Tailscale admin + DC-044 health-check marker
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-07-14 02:13:29 -07:00
Sami a79dc5a738 docs(changelog): document 1.14.0 release + desloppify changes
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-06-28 03:51:15 -07:00
Hermes 5f6c25d2e3 DC-018/DC-019: mark done, bump v1.13.5, CHANGELOG
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
2026-06-27 07:03:41 -07:00
Hermes 8973392c61 BACKLOG: audit DC-013/014/015/016 — all four already implemented, mark done
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Picked up the four 'Still Open' standardization items from the audit doc
as Option B work. Audited each before starting implementation:

  DC-013 (config schema migration) — src/config/migrations.js exists with
    a versioned migration system (CURRENT_VERSION=2, v1 dns normalization,
    v2 dns.provider field), loadAndMigrate() writes back to disk only when
    version changes, called from src/config/site.js on every startup.
    Guarded by 21 tests in __tests__/config-migrations.test.js.

  DC-014 (monitoring endpoint opt-in) — MONITORING_PUBLIC env var +
    config.monitoring.public both work via an IIFE in
    src/utilities/middleware.js line 297. Routes are conditionally public
    based on the flag. Default is 'true' for back-compat with existing
    dashboards that pre-load widget data. Flipping the default to 'false'
    is a fresh change with a real UX cost.

  DC-015 (CSRF token path duplication) — grep confirms only
    /api/v1/csrf-token exists. /api/v1/auth/csrf-token was never
    implemented or was already cleaned up.

  DC-016 (per-call fetchT timeouts) — src/utils/http.js defines
    fetchT(url, opts, timeoutMs) with AbortSignal.timeout() in the
    native branch and explicit timeout handlers in the http/https
    raw-request branches. 5s default covers most calls; 8 of 77 sites
    pass explicit overrides. 5min global request timeout is the backstop.

All four tasks reassigned from krystie → hermes because the work shifted
from 'implement' to 'verify and document'. No code changes in this commit
— only BACKLOG.md and CHANGELOG.md updated to reflect actual state.

This commit is the meta-example for Pitfall 20 (just added to the
standardization pitfalls reference): audit docs decay as fast as fixes
land. Always audit before implementing.
2026-06-25 17:27:56 -07:00
Hermes 8ec6c0ca6a DC-012: Add Kubernetes-style /healthz + /readyz probe aliases
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Fresh users copy-pasting healthcheck blocks from k8s/Docker docs need
the standard short aliases. Without /healthz and /readyz they get
connection refused. This commit:

1. Adds /healthz + /readyz as root-level aliases for /health/live +
   /health/ready in src/app.js. Handler bodies DRYed into named
   functions (livenessHandler, readinessHandler) so a probe semantics
   change updates all five paths at once.

2. Removes the dead /api/v1/health*, /api/v1/health/live, /api/v1/health/ready
   registrations from PUBLIC_ROUTES and CSRF exclusion list — those
   routes were never actually mounted on the apiRouter (only root
   paths existed). Anyone probing /api/v1/health now gets a clean 404
   instead of being routed through to a duplicate root handler.

3. Adds bypass for the 5 probe paths in three places where it matters:
   - PUBLIC_ROUTES (no auth)
   - csrf-protection.js excludedPaths (no CSRF check)
   - middleware.js request-logging exclusion (k8s polling every 10s
     doesn't flood the audit log)
   - middleware.js Tailscale auth bypass (probes don't carry Tailscale
     identity headers)

4. Adds __tests__/health-probe-aliases.test.js (19 tests):
   - Alias equivalence (/healthz == /health/live, /readyz == /health/ready)
   - Back-compat (/health == /health/live)
   - Path consolidation (all 3 /api/v1/health* return 404)
   - Source-of-truth PUBLIC_ROUTES allowlist sync check
   - Source-of-truth src/app.js mount list sync check (catches drift
     between handler mount and middleware allowlist)

5. Documents probes in README (copy-paste docker-compose.yml +
   Kubernetes blocks) and user-guide (Health Probes section + System
   API table updated).

Post-fix: 941/941 tests pass (+19 new). Zero new ESLint warnings
introduced. The pre-existing warnings/errors in src/app.js line 906
('os' is not defined) and the empty blocks in logging.test.js are
not regressions from this commit.
2026-06-25 17:16:16 -07:00
Hermes 283121edba Merge krystie-improvements into main
Resolves 24 conflicts between Hermes (DC-008/009/010 + response-helper
envelope standardization) and Krystie (DC-005 src/ refactor path fixes,
DC-006 TOTP integration, DC-007 new test suites, cloud backup
destinations).

Conflict resolutions:
- src/utils/logging.js:    took ours (consumers depend on logError/
                            safeErrorMessage/createLogger exports)
- src/config/site.js:      merged (her factored validateAndLogConfig +
                            applyConfigFields helpers)
- src/context/dns.js:      took hers (admin/readonly role iteration for
                            write operations)
- src/utilities/backup-
  manager.js:              took hers (Dropbox/WebDAV/SFTP cloud feature)
- status/dist/*, status/
  sw.js:                   took hers (minified bundles + newer SW cache)

Additional fix (post-merge regression):
- src/monitoring/health-checker.js: fixed DC-005 path miss —
  'require(./platform-paths)' → 'require(../../platform-paths)'

Test status: 921/922 passing. One known failure in logging.test.js
(async file-handle timing) tracked as follow-up.
2026-06-25 16:43:10 -07:00
Hermes 7f6be1c2b3 DC-009: populate [Unreleased] section in CHANGELOG.md
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Documents all unreleased work since v1.5.0:
- Security: TOTP 4-part recovery system
- Added: OpenClaw routes, auto-backup + storage limits, monitoring widget, Sami Files template, unified logger, notification manager, update UX, 7 new test files (120 tests)
- Changed: Route response standardization (DC-010, ~62 calls), /api/v1/ versioning, release.sh hardening
- Fixed: DC-011 credential route regression, 19 ESLint warnings (DC-004), workflow engine init, container-logs wireModal misuse, CSP hash mismatch, SW cache tag, updater false-positive loop
- Removed: legacy test scripts (moved to scripts/legacy/, preserved), stale root files, dead routes/ directory
2026-06-25 15:47:12 -07:00
Hermes 53680c4c74 v1.13.4: Standardize all route responses to use response helpers
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Convert ~160 raw res.json()/res.status().json() calls across 32+ files
to use centralized helpers from src/utils/responses.js (ok, errorResponse,
successMessage, notFound, validationError, forbidden, unauthorized, conflict).

No behavior changes — response shapes are identical. Future schema changes
(e.g., requestId envelope) only need to update one module.

Fix error vs errorResponse signature mismatch in routes/health.js CA cert
endpoint where error(res, message, statusCode) was being called with
errorResponse(res, statusCode, message, extras) argument order.

Files changed: middleware.js, csrf-protection.js, error-handler.js,
license-manager.js, src/app.js, and 27 route files.

Test suite: 755 pass / 4 pre-existing failures (services credential tests).
2026-06-11 00:48: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