Commit Graph

55 Commits

Author SHA1 Message Date
Krystie
5da1e572a1 refactor(server): Complete Phase 2.1 - Split monolithic server.js
MASSIVE REFACTOR:
- Created src/app.js (17KB) - Express setup, middleware, routes
- Slimmed server.js from 1997 lines → 230 lines (88% reduction!)
- Backed up original as server-old.js for reference

NEW STRUCTURE:
src/
├── app.js (Express application factory)
├── config/ (paths, site config, constants)
├── context/ (DI container, domain modules)
└── utils/ (http, logging, responses, async-handler)

STATS:
- Old server.js: 1997 lines (monolith)
- New server.js: 230 lines (entry point only)
- Modular code: 1729 lines across 14 files in src/
- Total reduction: 88% in main file

server.js now ONLY handles:
- App creation
- License loading
- HTTP server startup
- Feature module initialization
- Graceful shutdown

All business logic moved to src/ modules. Clean, testable, maintainable.

Phase 2.1 COMPLETE 
2026-03-29 19:46:41 -07:00
Krystie
fa7a78388a refactor(utils): Extract utilities from server.js
- Create src/utils/http.js - fetchT and HTTP helpers
- Create src/utils/logging.js - Structured logging and error logging
- Create src/utils/responses.js - Standard API responses
- Create src/utils/async-handler.js - Async wrapper with error handling
- Create src/utils/index.js - Consolidated exports

Removes scattered helper functions from server.js
2026-03-29 19:40:18 -07:00
Krystie
173dafa2f3 refactor(context): Extract context modules from god object
- Create src/context/docker.js - Docker operations
- Create src/context/caddy.js - Caddyfile manipulation
- Create src/context/dns.js - DNS token management and API calls
- Create src/context/session.js - Session wrapper
- Create src/context/index.js - Context assembly (DI container)

Breaks up the 50+ property ctx god object into domain-specific modules
2026-03-29 19:39:17 -07:00
Krystie
6c3d2baede refactor(config): Extract configuration into src/config/ module
- Create src/config/paths.js for all file paths and env vars
- Create src/config/site.js for site configuration loading
- Create src/config/index.js as unified config export
- Prepare for server.js modularization (Phase 2.1)

Part of deslopification roadmap: break 1997-line server.js into layers
2026-03-29 19:36:43 -07:00
Krystie
b172a21b63 Migrate 25 route files to throw-based error handling
Converted routes:
- All auth routes (totp.js, keys.js, sso-gate.js)
- Recipe deployment routes (deploy.js, manage.js, index.js)
- App deployment routes
- Config routes (assets, backup, settings)
- ARR routes (config, credentials)
- Infrastructure routes (dns, services, sites, logs)
- Additional routes (browse, ca, health, license, notifications, tailscale, updates)

Changes:
- Replaced ctx.errorResponse() with throw statements
- Replaced errorResponse() with throw statements
- Added proper error imports to each file
- 400 errors → ValidationError
- 401 errors → AuthenticationError
- 403 errors → ForbiddenError
- 404 errors → NotFoundError
- 409 errors → ConflictError
- 500 errors → Handled by middleware

Result: 25 files migrated, ~150 error responses standardized
2026-03-29 18:53:03 -07:00
Krystie
64a0018d00 Unified error handling system
- Consolidated all error classes into single errors.js
- Removed duplicate error definitions (NotFoundError, etc.)
- Added standard DC-XXX error codes for all error types
- Unified error middleware with automatic request logging
- Migrated routes/themes.js to throw-based error pattern
- Updated routes/services.js to use ConflictError
- Cleaner server.js error handler registration
- 40% less error handling boilerplate in routes
- Consistent error response format across all endpoints
2026-03-29 18:46:02 -07:00
Krystie
51d6c37e4a refactor(routes): Phase 3.6-10 - standardize 5 utility routes
- credentials.js (2 deps: credentialManager, asyncHandler)
- backups.js (2 deps: backupManager, asyncHandler)
- license.js (2 deps: licenseManager, asyncHandler)
- errorlogs.js (3 deps: ERROR_LOG_FILE, auditLogger, asyncHandler)
- themes.js (0 deps! Standalone route)

Total: 9 routes refactored so far
2026-03-28 19:32:01 -07:00
Krystie
f095ef24aa refactor(routes): Phase 3.5 - standardize monitoring.js (only 3 deps!) 2026-03-28 19:30:03 -07:00
Krystie
970e862533 refactor(routes): Phase 3.4 - standardize dns.js with explicit dependencies
- Replaced god object ctx with explicit dependency injection
- Added JSDoc documenting required dependencies (7 deps vs 50+)
- Updated response calls to use response-helpers (success/error)
- Dependencies: dns, siteConfig, asyncHandler, log, safeErrorMessage, fetchT, credentialManager
- DNS record management, Technitium proxy, credential storage all preserved
- 632 lines, now self-documenting and testable
2026-03-28 19:28:17 -07:00
Krystie
eac4ede21e refactor(routes): Phase 3.3 - standardize health.js with explicit dependencies
- Replaced god object ctx with explicit dependency injection
- Added JSDoc documenting required dependencies (8 deps vs 50+)
- Updated response calls to use response-helpers (success/error)
- Self-documenting: you can see exactly what this route needs
- Health checks, pylon relay, CA cert validation all preserved
2026-03-28 19:25:06 -07:00
Krystie
4e2bec2ef0 refactor(routes): Phase 3.2 - standardize containers.js with explicit dependencies
- Replaced god object ctx with explicit dependency injection
- Added JSDoc documenting required dependencies (only 3!)
- Updated response calls to use response-helpers (success)
- Dependencies: docker, log, asyncHandler (vs 50+ ctx properties)
- Self-documenting and testable
2026-03-28 19:23:39 -07:00
Krystie
13d612df5d refactor(routes): Phase 3.1 - standardize services.js with explicit dependencies
- Replaced god object ctx with explicit dependency injection
- Added JSDoc documenting all required dependencies
- Updated response calls to use response-helpers (success/error)
- Maintained all existing functionality
- Self-documenting: you can see exactly what this route needs
- Easier testing: mock only what's actually used (14 deps vs 50+ ctx properties)
2026-03-28 19:22:42 -07:00
cc8073256a refactor: Phase 2 - add error handling modules and response helpers 2026-03-28 19:01:24 -07:00
6c3848102b refactor: Phase 1 code cleanup - constants, logging, and repository organization 2026-03-28 18:54:39 -07:00
4ab9a770be chore: bump version to 1.1.5
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:40:18 -07:00
c49d86b0b8 fix: preserve service ID on subdomain change, accept localhost as IP
- serviceUrl() now checks service.url before falling back to buildServiceUrl(id)
- Service update no longer overwrites ID with the new subdomain
- Accept "localhost" as valid IP in service update validation
- Find services by ID or URL match when updating

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:38:41 -07:00
e5cd8678b0 fix: add pylon relay fallback to dashboard status endpoint
The dashboard uses /api/v1/services/status (not /api/health/services)
for live status cards. This endpoint was missing pylon relay fallback,
so services unreachable from the Docker container showed as OFF even
when the pylon was running. Also adds Windows VBS startup wrapper for
pylon persistence across reboots.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 16:50:24 -07:00
fc6275a96b feat: add Pylon health relay for remote service health checks
DashCaddy Pylon is a lightweight probe agent that runs on remote
networks to relay health checks for services the main DashCaddy
instance can't reach directly (e.g., .sami domains, LAN IPs).

- Standalone zero-dependency Node.js script (pylon/dashcaddy-pylon.js)
- Optional API key auth, HEAD→GET fallback, batch probe support
- Health routes now try direct check first, fall back to pylon relay
- New endpoints: /health/probe (act as pylon), /health/pylon (status)
- Config: add "pylon": { "url": "...", "key": "..." } to config.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 15:52:43 -07:00
d332084206 feat: add host-side auto-updater for zero-touch API container rebuilds
When the in-container self-updater downloads a new version, it writes
trigger.json. The new systemd path unit watches for this file and runs
dashcaddy-update.sh, which backs up current API files, copies the new
ones, rebuilds the container, verifies health, and writes result.json.
Automatic rollback on build or health check failure.

Also fixes undefined `isWindows` variable in self-updater.js and adds
DASHCADDY_HOST_UPDATES_DIR env var to the installer's docker-compose
template for correct container-to-host path translation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 14:25:22 -07:00
abd54d4b99 fix: prevent encryption key conflicts and add license backup
- Remove eager key generation from crypto-utils module load (was baking
  keys into Docker images that conflicted with mounted production keys)
- Add license backup to config.json (survives credential store failures)
- LicenseManager.load() falls back to config.json backup if credential
  store decryption fails (e.g. after container rebuild with new key)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 14:17:25 -07:00
64b3534c7d Merge branch 'main' of http://100.98.123.59:3000/sami7777/dashcaddy
# Conflicts:
#	dashcaddy-api/.license-counter
#	dashcaddy-api/__tests__/docker-security.test.js
2026-03-23 13:42:22 -07:00
b4022288dc fix: service edit, CSRF token stability, and license restore (v1.1.1)
- Fix service edit double-write bug (was creating duplicate entries)
- Add editable display name field to service edit modal
- Backend update endpoint now accepts name, logo, and recalculates url
- Fix CSRF token regeneration breaking all POST requests (nonce was
  being regenerated on every request, invalidating cached tokens)
- CSRF nonce now persists across requests, rotated only on TOTP login
- Frontend secureFetch auto-retries on CSRF failure with fresh token
- Restore lifetime license activation on DNS2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 13:39:05 -07:00
Krystie
d76644d948 Sync DNS2 production changes - removed obsolete test suite and refactored structure 2026-03-23 10:47:15 +01:00
Krystie
1ac50918ab Add package-lock and deployment script updates 2026-03-23 10:35:29 +01:00
263b090769 test: add comprehensive docker-security test suite (41 tests) 2026-03-22 11:46:30 -07:00
Krystie
883cce27df Phase 3 (WIP): Refactor license, credentials, backups routes
- All use explicit deps instead of ctx
- Pattern consistent across all refactored routes
2026-03-22 11:09:55 +01:00
Krystie
81f778df72 Phase 3 (WIP): Refactor containers & monitoring routes
- routes/containers.js: Explicit deps (docker, asyncHandler, log)
- routes/monitoring.js: Explicit deps (docker, resourceMonitor)
- Pattern established: factory function with destructured deps
2026-03-22 11:09:16 +01:00
Krystie
3efa5dc3f4 Phase 2 (WIP): Extract context modules (caddy, dns)
- src/context/caddy.js: Caddyfile manipulation, reload, config generation
- src/context/dns.js: DNS API wrapper with token management
- All context modules use factory pattern with explicit dependencies
2026-03-22 11:08:05 +01:00
Krystie
efa9c7ba6b Phase 2 (WIP): Add caddy context module
- src/context/caddy.js: Caddyfile manipulation, reload, config generation
- Uses dependency injection (init() pattern) for siteConfig, log, fetchT
- Atomic mutex-based modifications with rollback on failure
- All Caddy operations now in one module
2026-03-22 11:07:03 +01:00
Krystie
6771e4775e Phase 2 (WIP): Add logger and docker context modules
- src/utils/logger.js: Structured JSON logging
- src/context/docker.js: Docker API wrapper (pull, findContainer, getUsedPorts)
- All modules can now be imported directly instead of via ctx
2026-03-22 11:05:50 +01:00
Krystie
d5a6789366 Phase 2 (WIP): Extract config and utils modules
- Created src/config/ (env.js, site-config.js)
- Created src/utils/ (async-handler.js, responses.js, safe-error.js)
- server.js not yet modified (backward-compatible extraction)
2026-03-22 11:04:04 +01:00
Krystie
039d3d07e2 Phase 1: Add dependency analysis documentation 2026-03-22 11:01:40 +01:00
Krystie
e2c67a8fe8 Phase 1: Add ESLint/Prettier config + baseline auto-fixes 2026-03-22 11:00:25 +01:00
41a0cdee7e test: expand credential-manager edge case coverage 2026-03-22 02:37:32 -07:00
6775dc154b test: add comprehensive docker-security test suite (39 tests) 2026-03-20 22:45:55 -07:00
43b06c519f test: add comprehensive docker-security test suite (39 tests, Phase 3) 2026-03-20 22:45:11 -07:00
d15c160185 test: add comprehensive auth-manager test suite (Phase 3 WIP) 2026-03-20 22:19:45 -07:00
Krystie
3c5376c7b9 security: implement Phase 1-2 fixes (logger sanitization + tests)
- Add logger-utils.js for credential sanitization in logs
- Add security comments to auth-manager.js
- Create .env.example template
- Add .env to .gitignore
- Implement comprehensive logger-utils tests (16 cases)

Desloppify score: 15.4 → ~25-30 (estimated)
Security: 62.5% → ~80%
Test coverage: 0% → ~5%

Fixes: 20 security issues flagged by Desloppify
Adds: 16 test cases
Created: 3 new files, modified 2 existing files

See SECURITY-IMPROVEMENTS.md for full details.
2026-03-21 03:43:03 +01:00
75e2d7853e Unify backup/restore into single v2.0 file with full state capture
Server export now includes encryption key, themes, and all config files.
Client export bundles all DashCaddy localStorage keys (19 named + dynamic
widget keys) as browserState. Restore handles both server and browser
state in one operation. Legacy v1.0 import format still supported.
Removed redundant Export/Import toolbar buttons — Backup modal is now
the single entry point.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 21:06:56 -07:00
6d098fd96f Exempt DNS logs from rate limiting and hide Tokens button when no DNS configured
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 19:31:12 -07:00
f2f33b4b40 Make DNS servers fully dynamic from config.json
DNS server IDs (dns1, dns2, dns3) were hardcoded throughout the frontend
and backend. Now config.json's dnsServers object is the single source of
truth — adding or removing a DNS server in config automatically updates
the dashboard cards, credential modal, health checks, and probes.

- credentials.js: rebuild modal sections dynamically from SITE.dnsServers
- globals.js: add getPrimaryDnsId() helper for primary DNS lookups
- service-create.js, service-infrastructure.js: use dynamic DNS ID
- startup-validator.js: dynamic topCardServices from config
- middleware.js: add license endpoints to public routes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 16:55:07 -07:00
2815233e86 Unify URL resolution, add health checker sync, and make modules optional
- Add url-resolver.js with single resolveServiceUrl() used by all 5 consumers
  (probes, health routes, health checker auto-config)
- Health checker now does full sync (add/update/remove) instead of add-only,
  and re-syncs automatically after every services.json mutation
- docker-maintenance and log-digest are now optional imports with try/catch,
  preventing container crashes when these files are absent
- Add null guards in routes/logs.js for graceful 503 responses

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 23:01:20 -07:00
70b818c2bd Fix Tailscale route prefix mismatch and increase health check timeout
Mount Tailscale router at /tailscale prefix so all 10 routes resolve
to /api/tailscale/* as expected by middleware, audit logger, and
frontend. Previously 5 routes (status, config, check-connection,
devices, protect-service) resolved to /api/* instead, with config
colliding with the settings route. Strip redundant /tailscale/ prefix
from OAuth routes that were compensating for the missing mount prefix.

Increase default health check timeout from 10s to 20s to reduce false
positives on slower services.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 18:44:20 -07:00
Krystie
df0daaad46 Add full cross-platform path support
- Added automatic volume path translation in deployment (deploy.js)
- Updated FileBrowser template to use /opt/ instead of hard-coded E:/
- Migrated self-updater.js to use centralized platformPaths module
- Updated UI placeholders to use platform-neutral paths (/media/)
- All paths now automatically adapt to Windows or Linux at runtime via process.platform detection
2026-03-14 06:52:18 +01:00
e615f24627 Add Docker hygiene, deployment manifests, and daily log digest
Prevents Docker disk bloat by adding log rotation (10MB max, 3 files)
to all container creation and update paths, auto-pruning dangling
images after deploy/remove/update, and a daily maintenance module
that cleans build cache and warns on disk thresholds.

Saves a deployment manifest in services.json at deploy time so users
can restore all their apps after a Docker purge. Adds restore-all
and restore-single endpoints that recreate containers, Caddy config,
and DNS records from the saved manifests.

Adds an hourly log collector and daily digest generator that
summarizes errors, warnings, and events across all services into
a single human-readable report with guidance on where to investigate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:41:40 -07:00
root
4131c3c6f6 Fix CSRF cookie Secure flag for localhost development
- Changed hardcoded secure:true to req.secure || req.protocol === 'https'
- Allows CSRF cookies to work over HTTP on localhost
- Still enforces secure flag for HTTPS connections
- Enables OpenClaw programmatic API access
2026-03-13 05:30:09 +01:00
0f4bd419e1 Add batched status endpoint and optimize frontend performance
Server-side batched /api/v1/services/status endpoint replaces N
individual browser probes with a single API call (HEAD-first with
GET fallback, concurrency-limited, CA-aware HTTPS agent).

Frontend: clock reuses DOM instead of rebuilding innerHTML every
second with drift-correcting timer that pauses on hidden tabs.
Card animations use CSS transitionDelay + requestAnimationFrame.
Internet dot blink moved from JS intervals to CSS keyframes with
prefers-reduced-motion support. Service worker rewritten with
network-first navigation, stale-while-revalidate assets, and
navigation preload. Font faces drop TTF fallbacks, use font-display
swap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 22:39:29 -07:00
2d1944fd55 Fix auto-update pipeline bugs discovered in e2e testing
- Fix container-to-host path mapping in trigger.json (stagingDir
  was using container path /app/updates/ instead of host path
  /opt/dashcaddy/updates/)
- Fix download race condition: primary download's async unlink
  could delete mirror download's file — use unlinkSync before retry
- Fix DASHCADDY_COMMIT build arg not passed to docker compose build
  (was set as env var, now uses --build-arg)
- Remove MakeDirectory=yes from systemd path unit (was creating
  trigger.json as directory instead of file)
- Remove unused 'tar' npm module import
- Add mirror fallback for tarball downloads (not just version checks)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 03:32:08 -08:00
ffa6966fd3 Add auto-update system for DashCaddy instances
- self-updater.js: polls for new versions, downloads/verifies tarballs,
  triggers host-side rebuild via systemd path unit
- dashcaddy-update.sh + systemd units: host-side container rebuild with
  automatic rollback on health check failure
- 7 new /api/v1/system/* endpoints for version info, update check/apply,
  rollback, and update history
- Frontend: DashCaddy tab in Updates modal with version display,
  changelog, update button, rollback, and notification dot
- install.sh: updater service installation, volume mounts, env vars
- build-release.sh + webhook-handler.js: release server pipeline
  (Gitea webhook → build tarball → deploy to get.dashcaddy.net)
- Dockerfile: DASHCADDY_COMMIT build arg → VERSION file
- Version bump to 1.1.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 03:11:35 -08:00
52577b11ed Fix 7 frontend security vulnerabilities (4 critical, 3 high)
- Escape all innerHTML assignments with user/external data across 12 JS files
- Upgrade credential encryption: per-value IV, key moved to sessionStorage
- Fix open redirect in TOTP auth via proper URL hostname validation
- Remove sensitive DNS topology data from localStorage cache
- Add security regression test suite (51 tests)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:29:04 -08:00