fix: repair SSO auto-login and remove repo artifacts

- Add missing fetchT dep to session-handlers.js (fixes ctx is not
  defined error that broke jellyfin/emby/plex/syncthing SSO)
- Replace all ctx.fetchT calls with direct fetchT usage
- Remove server-old.js (69K monolith backup) from tracking
- Remove AI-generated doc artifacts from repo root
- Update .gitignore to prevent re-adding these files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-30 01:28:19 -07:00
parent 3b08fe25e8
commit 01bf01d043
10 changed files with 11 additions and 3350 deletions

6
.gitignore vendored
View File

@@ -43,12 +43,18 @@ TEST-RESULTS.md
TESTING-GUIDE.md TESTING-GUIDE.md
DashCA-Plan.md DashCA-Plan.md
vhdx-cleanup-instructions.md vhdx-cleanup-instructions.md
DESLOPIFICATION-ROADMAP.md
SECURITY-IMPROVEMENTS.md
WHAT-IS-DASHCADDY.md
error-handling-cleanup-summary.md
error-handling-migration-complete.md
# Utility scripts (local only) # Utility scripts (local only)
check-e.ps1 check-e.ps1
disk-scan.ps1 disk-scan.ps1
disk-scan2.ps1 disk-scan2.ps1
fix-wsl-and-mount.ps1 fix-wsl-and-mount.ps1
fix-ctx-routes.sh
import-services.js import-services.js
# OS files # OS files

View File

@@ -1,388 +0,0 @@
# DashCaddy API Deslopification Roadmap
**Audited:** 2026-03-22
**Version:** 1.1.0
**Total Lines:** ~26,000 (API), ~10,000 (dashboard)
**Priority:** API-first (make backend powerful, clean dashboard follows naturally)
---
## Executive Summary
The DashCaddy API is **feature-complete and security-hardened**, but the codebase shows signs of rapid evolution. While functionally robust, it would significantly benefit from architectural refactoring to improve maintainability, testability, and long-term scalability.
### Key Strengths
✅ Comprehensive feature set (76+ app templates, Docker/Caddy/DNS management)
✅ Security-conscious (TOTP auth, AES-256-GCM credentials, CSRF protection, audit logging)
✅ Recent test coverage additions (auth, credentials, Docker security)
✅ Modular route organization (routes/ subdirectories)
✅ Shared context pattern for dependency injection
### Core Issues
**Monolithic `server.js`** (1960 lines) — initialization, middleware, utilities, business logic all in one file
**God object `ctx`** — 50+ properties/methods across multiple domains with hidden dependencies
**Inconsistent patterns** — routes use classes, factory functions, or flat modules with no standard
**No code standards** — ESLint installed but no config, no formatting rules
**Mixed concerns** — HTTP handlers, business logic, validation intertwined in route files
---
## Current Architecture
```
dashcaddy-api/
├── server.js (1960 lines) ← MAIN PROBLEM
│ ├── 89 require() statements
│ ├── 131 top-level declarations
│ ├── Middleware setup
│ ├── Context (`ctx`) assembly (50+ properties)
│ ├── Route mounting
│ ├── Error handlers
│ └── Server startup
├── routes/
│ ├── auth/ (5 files, modular) ✅
│ ├── config/ (4 files, modular) ✅
│ ├── apps/ (6 files, helpers pattern) ⚠️
│ ├── arr/ (4 files, helpers pattern) ⚠️
│ ├── recipes/ (3 files) ⚠️
│ └── *.js (19 flat route files) ❌
├── Managers (clean, well-separated)
│ ├── auth-manager.js (307 lines) ✅
│ ├── credential-manager.js (395 lines) ✅
│ ├── state-manager.js (237 lines) ✅
│ ├── backup-manager.js (835 lines) ⚠️
│ ├── health-checker.js (591 lines) ⚠️
│ └── update-manager.js (911 lines) ⚠️
├── Utilities
│ ├── input-validator.js (606 lines) ⚠️
│ ├── crypto-utils.js (340 lines) ✅
│ ├── middleware.js (430 lines) ⚠️
│ └── constants.js ✅
└── Templates
├── app-templates.js (2496 lines) ⚠️
└── recipe-templates.js (339 lines) ✅
```
**Legend:**
✅ Good structure
⚠️ Works but could be cleaner
❌ Needs refactoring
---
## Deslopification Phases
### Phase 1: Foundation & Standards (IMMEDIATE)
**Goal:** Establish code quality baseline before refactoring
**Effort:** 2-4 hours
**Risk:** Low (tooling only, no code changes)
#### 1.1 Code Standards Setup
- [ ] Create `.eslintrc.js` with recommended rules
- [ ] Add Prettier config (`.prettierrc`)
- [ ] Add npm scripts: `lint`, `lint:fix`, `format`
- [ ] Run `npm run lint:fix` and commit baseline cleanup
- [ ] Add pre-commit hooks (optional)
**Why first:** Establish formatting/style consistency before making structural changes. Prevents "should I refactor this while I'm here?" scope creep.
#### 1.2 Dependency Graph Documentation
- [ ] Map `ctx` properties → which routes actually use them
- [ ] Identify circular dependencies (if any)
- [ ] Document shared utilities used across routes
**Deliverable:** `DEPENDENCIES.md` — reference for refactoring decisions
---
### Phase 2: Extract & Organize (HIGH PRIORITY)
**Goal:** Break `server.js` into logical modules
**Effort:** 1-2 days
**Risk:** Medium (requires testing at each step)
#### 2.1 Split `server.js` into Layers
**Before:** 1960-line monolith
**After:** Clean initialization flow
Create new structure:
```
src/
├── app.js ← Express app setup (middleware, routes)
├── server.js ← Entry point (load config, start server)
├── config/
│ ├── index.js ← Load all config (env, files, constants)
│ ├── env.js ← Environment variable validation
│ └── paths.js ← Platform-specific paths
├── context/
│ ├── index.js ← Assemble context (DI container)
│ ├── docker.js ← Docker-related context properties
│ ├── caddy.js ← Caddy-related context properties
│ ├── dns.js ← DNS context
│ ├── session.js ← Session context
│ └── notification.js ← Notification context
├── middleware/
│ ├── index.js ← Export all middleware
│ ├── auth.js ← Move from middleware.js
│ ├── error.js ← Error handlers
│ └── security.js ← Helmet, CORS, CSRF
└── routes/
└── (existing structure)
```
**Migration Steps:**
1. Create `src/config/` — extract all config loading from `server.js`
2. Create `src/context/` — split god object into domain modules
3. Create `src/middleware/` — break up `middleware.js` (430 lines)
4. Create `src/app.js` — Express setup + route mounting
5. Slim `server.js` → minimal entry point (~50 lines)
**Tests:** Ensure existing test suite still passes after each step
---
### Phase 3: Route Standardization (MEDIUM PRIORITY)
**Goal:** Consistent route module pattern across entire API
**Effort:** 2-3 days
**Risk:** Medium (touching business logic)
#### 3.1 Establish Route Pattern
**Chosen Pattern:** Factory function with explicit dependencies
```javascript
// routes/services.js (before)
module.exports = (ctx) => {
const router = express.Router();
// ... uses ctx.docker, ctx.servicesStateManager, ctx.log, etc.
return router;
};
// routes/services.js (after)
module.exports = ({ docker, servicesStateManager, log, asyncHandler }) => {
const router = express.Router();
// ... explicitly passed dependencies
return router;
};
```
**Benefits:**
- Self-documenting (you see what each route needs)
- Easier testing (mock only what's used)
- No hidden dependencies via god object
#### 3.2 Refactor Routes by Priority
**Order:** Most-used routes first
1. **High-traffic routes:**
- `routes/services.js` (467 lines) — core service management
- `routes/containers.js` (246 lines) — Docker operations
- `routes/health.js` (297 lines) — health checks
- `routes/dns.js` (632 lines) — DNS management
2. **Auth routes** (already modular, just align pattern):
- `routes/auth/*`
3. **Feature routes:**
- `routes/apps/*`
- `routes/arr/*`
- `routes/recipes/*`
4. **Utility routes:**
- `routes/logs.js`
- `routes/backups.js`
- `routes/ca.js`
- etc.
**Per-route checklist:**
- [ ] Extract dependencies from `ctx` → explicit parameters
- [ ] Move business logic to service layer (if complex)
- [ ] Validate inputs at route boundary
- [ ] Return consistent error format
- [ ] Add route-level tests
---
### Phase 4: Service Layer Introduction (LOWER PRIORITY)
**Goal:** Separate business logic from HTTP handlers
**Effort:** 3-5 days
**Risk:** Medium-High (significant refactor)
**Problem:** Routes currently mix HTTP concerns with business logic:
```javascript
// Current: Everything in route handler
router.post('/deploy', async (req, res) => {
// 1. Parse request
// 2. Validate inputs
// 3. Business logic (complex Docker operations)
// 4. Error handling
// 5. Format response
});
```
**Solution:** Service layer pattern
```javascript
// routes/apps/deploy.js
router.post('/deploy', async (req, res) => {
const result = await appDeployService.deploy(req.body);
res.json({ success: true, data: result });
});
// services/app-deploy-service.js
class AppDeployService {
async deploy({ templateId, config }) {
// Pure business logic, no HTTP awareness
}
}
```
**Candidates for service extraction:**
- `services/docker-service.js` — container lifecycle, networking
- `services/caddy-service.js` — Caddyfile manipulation, reload
- `services/dns-service.js` — record management, zone operations
- `services/app-deploy-service.js` — template-based deployment
- `services/backup-service.js` — backup/restore workflows
**Benefits:**
- Routes become thin HTTP adapters (easy to test)
- Business logic testable without HTTP mocking
- Reusable across routes (e.g., CLI tools, cron jobs)
---
### Phase 5: Manager Cleanup (ONGOING)
**Goal:** Refine existing manager modules
**Effort:** 1-2 days (parallel to other phases)
#### Issues to Address
1. **`backup-manager.js` (835 lines)** — too large, split backup vs restore logic
2. **`update-manager.js` (911 lines)** — complex state machine, extract version comparison utilities
3. **`health-checker.js` (591 lines)** — separate health check logic from notification daemon
4. **`input-validator.js` (606 lines)** — split by domain (docker, caddy, dns validators)
**Approach:** Incremental splitting, preserve existing API
---
### Phase 6: Template Organization (LOW PRIORITY)
**Goal:** Make templates maintainable and extensible
**Effort:** 1 day
**Problem:** `app-templates.js` is 2496 lines (76 templates in one file)
**Solution:**
```
templates/
├── index.js ← Export TEMPLATE_CATEGORIES, DIFFICULTY_LEVELS
├── apps/
│ ├── media/
│ │ ├── plex.js
│ │ ├── jellyfin.js
│ │ └── ...
│ ├── automation/
│ └── ...
└── recipes/
├── arr-stack.js
└── ...
```
**Benefits:**
- Easier to find/edit specific templates
- Contributors can add templates without merge conflicts
- Templates can import shared snippets (e.g., common env vars)
---
## Metrics & Success Criteria
### Code Quality Metrics (Before → After)
| Metric | Before | Target | How to Measure |
|--------|--------|--------|----------------|
| `server.js` lines | 1960 | <200 | `wc -l server.js` |
| Avg route file size | ~300 | <150 | `find routes -name '*.js' -exec wc -l {} + \| awk '{sum+=$1; n++} END {print sum/n}'` |
| `ctx` properties | 50+ | 0 (removed) | Manual count |
| ESLint errors | Unknown | 0 | `npm run lint` |
| Test coverage | ~30% | >60% | `npm run test:coverage` |
| Files >500 lines | 8 | <3 | `find . -name '*.js' -exec wc -l {} + \| awk '$1 > 500'` |
### Developer Experience Improvements
- **Onboarding:** New contributor should understand route structure in <10 minutes
- **Testing:** Mock only what you use (no god object sprawl)
- **Changes:** Touching one domain shouldn't require understanding entire codebase
- **Deployment:** Confidence that refactor didn't break anything (test suite)
---
## Risk Mitigation
### How to Refactor Safely
1. **Test suite first** — before touching code:
- Run existing tests: `npm test`
- Identify untested critical paths → add tests
- Establish coverage baseline
2. **Incremental changes**:
- Each phase = separate branch
- Each phase passes full test suite
- Deploy to test environment (Contabo) before merging
3. **Preserve API contract**:
- Frontend expects same endpoints/responses
- Dashboard shouldn't need changes during API refactor
- Version routes if breaking changes needed
4. **Rollback plan**:
- Git tags before each phase merge
- Keep old code in `legacy/` until confidence is high
- Document what changed in each PR
---
## Recommended Order of Execution
**Week 1: Foundation**
- Day 1-2: Phase 1 (ESLint, Prettier, dependency mapping)
- Day 3-5: Phase 2.1 (split `server.js`)
**Week 2: Routes**
- Day 1-3: Phase 3.1 (standardize top 5 routes)
- Day 4-5: Phase 3.2 (remaining routes)
**Week 3: Refinement**
- Day 1-3: Phase 4 (service layer for complex routes)
- Day 4-5: Phase 5 (manager cleanup)
**Week 4: Polish**
- Day 1-2: Phase 6 (template organization)
- Day 3-5: Documentation, final testing, deployment
**Total:** ~4 weeks part-time or ~2 weeks full-time
---
## Questions for Sami
Before starting, clarify:
1. **Testing strategy:** Current test coverage is partial. Should we:
- Write tests BEFORE refactoring (safer, slower)?
- Refactor with existing tests, add coverage later (faster, riskier)?
2. **Breaking changes:** Can we introduce backwards-incompatible API changes if we version routes (`/api/v2/...`)?
3. **Deployment cadence:** Should each phase deploy to production, or batch into one big release?
4. **Priority tweaks:** Does this roadmap align with "deslopify → market → sell" timeline, or should we focus only on the most visible pain points first?
---
## Next Steps
**If approved:**
1. Create feature branch: `refactor/deslopification-phase-1`
2. Add ESLint + Prettier configs
3. Run `npm run lint:fix` and commit baseline
4. Create `DEPENDENCIES.md` (ctx usage map)
5. Review with Sami before proceeding to Phase 2
**Estimated time to first visible improvement:** 1 week (server.js split + linting)

View File

@@ -1,289 +0,0 @@
# DashCaddy Security Improvements
**Date:** 2026-03-21
**Desloppify Score:** 15.4/100 → Target: 95.0/100
## Summary of Changes
This commit implements critical security improvements identified by Desloppify code analysis, addressing 20 security issues and establishing a foundation for comprehensive test coverage.
---
## 🚨 Phase 1: Critical Security Fixes
### 1.1 New Sanitization Infrastructure
**File:** `dashcaddy-api/logger-utils.js` (NEW)
Created a comprehensive logging sanitization utility to prevent credential leakage in logs:
- **`sanitizeForLog(data, additionalSensitiveKeys)`**: Recursively redacts sensitive fields from objects/arrays
- **`redactCredential(value)`**: Partially redacts credentials (shows first/last 4 chars only)
- **`safeLog(message, data)`**: Creates safe log objects with automatic sanitization
- **`SENSITIVE_FIELDS`**: 30+ sensitive field name patterns (password, token, apiKey, secret, etc.)
**Security Impact:**
- Prevents accidental logging of passwords, tokens, API keys, certificates
- Case-insensitive field matching
- Handles nested objects and arrays
- Supports custom sensitive field lists
---
### 1.2 Auth Manager Security Enhancements
**File:** `dashcaddy-api/auth-manager.js`
**Changes:**
1. Added `logger-utils` import for future sanitization
2. Added security comments on lines 16-18 (JWT_SECRET handling)
3. Line 48: Added comment clarifying tokens are never logged
4. Line 73: Removed error.message from JWT invalid logs (could leak token data)
5. Line 109: Added comment confirming API keys are never logged
**Fixed Issues:**
- Lines 16, 17, 96: Hardcoded secret name warnings (clarified these are variable names, not actual secrets)
- Lines 71, 73: Logging sensitive authentication data (confirmed safe - only logs event names, not values)
---
### 1.3 Environment Variable Template
**File:** `dashcaddy-api/.env.example` (NEW)
Created comprehensive environment variable template with:
- JWT_SECRET configuration
- Docker/Caddy/DNS settings
- Notification provider configuration (Discord, Telegram, Ntfy)
- Tailscale OAuth settings
- Clear documentation and warnings
**Security Impact:**
- Provides secure configuration template
- Documents all required/optional environment variables
- Prevents accidental credential commits
---
### 1.4 .gitignore Updates
**File:** `.gitignore`
**Added:**
```
dashcaddy-api/.env
.env
```
**Existing (preserved):**
```
dashcaddy-api/credentials.json
```
**Security Impact:**
- Prevents accidental commit of environment variables
- Prevents accidental commit of encrypted credential storage
---
## 📊 Phase 2: Test Coverage Foundation
### 2.1 Logger Utils Test Suite
**File:** `dashcaddy-api/__tests__/logger-utils.test.js` (NEW)
Created comprehensive test suite for logger-utils.js:
**Test Coverage:**
-`sanitizeForLog`: 6 test cases
- Sensitive field redaction
- Nested object handling
- Array handling
- Null/undefined handling
- Additional sensitive keys
- Case-insensitive matching
-`redactCredential`: 5 test cases
- Long string partial redaction
- Short string full redaction
- Null/undefined handling
- Non-string input handling
- Asterisk limiting
-`safeLog`: 3 test cases
- Safe log object creation
- Timestamp validation
- Empty data handling
-`SENSITIVE_FIELDS`: 2 test cases
- Common field name presence
- Array length validation
**Total:** 16 test cases covering all public API functions
**Test Infrastructure:**
- Uses existing Jest configuration
- Follows standard `__tests__/` directory convention
- Can be run with `npm test`
---
## 📋 Files Modified
| File | Status | Changes |
|------|--------|---------|
| `dashcaddy-api/logger-utils.js` | ✨ NEW | Logging sanitization utility (133 lines) |
| `dashcaddy-api/__tests__/logger-utils.test.js` | ✨ NEW | Comprehensive test suite (173 lines) |
| `dashcaddy-api/.env.example` | ✨ NEW | Environment variable template |
| `dashcaddy-api/auth-manager.js` | 🔧 MODIFIED | Security comments + import added |
| `.gitignore` | 🔧 MODIFIED | Added .env exclusions |
| `SECURITY-IMPROVEMENTS.md` | ✨ NEW | This document |
---
## 🎯 Desloppify Score Impact
### Current Remediation (Phase 1-2 Partial)
| Metric | Before | After | Change |
|--------|---------|-------|--------|
| **Overall Score** | 15.4 | ~25-30* | +10-15 pts |
| **Security** | 62.5% | ~80%* | +17.5% |
| **Test Coverage** | 0% | ~5%* | +5% |
*Estimated - requires rescan to confirm
### Remaining Work (Phase 3-4)
To reach target score of 95.0/100, the following work remains:
**High Priority (Phase 3):**
- [ ] Add tests for auth-manager.js (CRITICAL - handles authentication)
- [ ] Add tests for credential-manager.js (CRITICAL - handles secrets)
- [ ] Add tests for docker-security.js (HIGH - security module)
- [ ] Add tests for input-validator.js (HIGH - injection prevention)
- [ ] Refactor server.js (2,100 LOC → split into routes/ + services/)
- [ ] Extract hardcoded constants to named constants
**Medium Priority (Phase 4):**
- [ ] Subjective code review (naming, API coherence, error consistency)
- [ ] Type safety improvements (JSDoc or TypeScript migration)
- [ ] Documentation improvements (CONTRIBUTING.md, API docs)
---
## 🛠️ How to Deploy These Changes
### 1. Review Changes
```bash
git diff
```
### 2. Run Tests
```bash
cd dashcaddy-api
npm test
```
Expected output: 16 tests passing (all in logger-utils.test.js)
### 3. Copy to Production
On Windows machine (dns1-sami):
```powershell
# Backup current production
Copy-Item C:/caddy/sites/dashcaddy-api C:/caddy/sites/dashcaddy-api.backup -Recurse
# Deploy new files
Copy-Item dashcaddy-api/logger-utils.js C:/caddy/sites/dashcaddy-api/
Copy-Item dashcaddy-api/auth-manager.js C:/caddy/sites/dashcaddy-api/
Copy-Item dashcaddy-api/__tests__ C:/caddy/sites/dashcaddy-api/ -Recurse
Copy-Item dashcaddy-api/.env.example C:/caddy/sites/dashcaddy-api/
# Restart container
docker restart dashcaddy-api
```
### 4. Verify Deployment
```bash
# Check container logs
docker logs dashcaddy-api --tail 50
# Test health endpoint
curl http://localhost:3001/health
```
---
## 🔒 Security Considerations
### What Was Fixed
1. ✅ Created centralized logging sanitization
2. ✅ Added security comments to clarify safe logging practices
3. ✅ Created .env template for secure configuration
4. ✅ Updated .gitignore to prevent credential commits
5. ✅ Established test coverage foundation
### What Still Needs Attention
1. ⚠️ **Rotate any secrets previously committed to git** (if any exist in git history)
2. ⚠️ **Create actual .env file** from .env.example with real values (do NOT commit)
3. ⚠️ **Audit existing logs** for any historical credential leakage
4. ⚠️ **Implement auth-manager tests** to validate security boundaries
5. ⚠️ **Implement credential-manager tests** to validate encryption
---
## 📚 Next Steps
### Immediate (This Week)
1. Run Desloppify rescan to confirm score improvement
2. Create .env file from template (production servers only)
3. Deploy changes to production
4. Write auth-manager.js tests
### Short-term (Next 2 Weeks)
1. Complete Phase 2 test coverage (credential-manager, docker-security, input-validator)
2. Begin Phase 3 refactoring (split server.js)
3. Extract magic numbers to named constants
### Long-term (Next Month)
1. Achieve 80%+ test coverage
2. Complete Phase 4 subjective improvements
3. Reach Desloppify target score of 95.0/100
---
## 🙏 Acknowledgments
This security improvement initiative was driven by Desloppify static analysis tool, which identified:
- 20 security issues (4 hardcoded secrets, 16 logging concerns)
- 0% test coverage
- Structural improvements needed across 8 files
**Tools Used:**
- [Desloppify](https://github.com/peteromallet/desloppify) - Code quality analysis
- Jest - JavaScript testing framework
- ESLint - JavaScript linting (already configured)
---
## 📝 Commit Message Template
```
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
Adds: 16 test cases
Created: 3 new files, modified 2 existing files
See SECURITY-IMPROVEMENTS.md for full details.
```
---
**Generated:** 2026-03-21 03:45 CET
**Author:** Krystie (OpenClaw AI Assistant)
**Reviewed:** Pending human review

View File

@@ -1,242 +0,0 @@
# What is DashCaddy?
DashCaddy is a self-hosted web dashboard that unifies Docker container management, Caddy reverse proxy configuration, DNS automation, and SSL certificate provisioning into a single interface. It is designed for homelabbers and self-hosters who want to deploy and manage services without manually editing config files, writing Docker Compose YAML, or configuring DNS records by hand.
You open one page, click "Deploy", pick an app, and DashCaddy handles everything: pulls the Docker image, starts the container, creates a DNS record, adds a reverse proxy block with automatic HTTPS, and registers the service on your dashboard — all in about 30 seconds.
## The Stack
| Layer | Technology | Role |
|-------|-----------|------|
| Frontend | Vanilla JS SPA (~12,000 lines across 33 modules) | Dashboard UI, modals, wizards |
| Backend | Node.js / Express (~20,000 lines across 22 modules + 20 route files) | API server with 125+ endpoints |
| Reverse Proxy | Caddy | HTTPS termination, internal CA, automatic certificates |
| DNS | Technitium DNS Server | Automatic A-record creation for `*.sami` domains |
| Containers | Docker (via dockerode) | Application lifecycle management |
| Auth | TOTP (RFC 6238) + JWT | Two-factor authentication for dashboard access |
| Encryption | AES-256-GCM | Credential storage with OS keychain fallback |
The API server runs inside a Docker container (`caddy-api`) on port 3001. Caddy sits in front of everything on port 443, terminating TLS with certificates signed by its own root CA.
## What It Does
### One-Click App Deployment
55 pre-configured templates across 16 categories (Media, Downloads, Productivity, Development, Monitoring, DNS, Security, and more). Each template defines the Docker image, default port, environment variables, volume mounts, health check endpoint, and setup instructions. Deploying an app:
1. Pulls the Docker image
2. Creates the container with the right env vars, ports, and volumes
3. Creates a DNS A-record on Technitium (e.g., `plex.sami`)
4. Adds a reverse proxy block to the Caddyfile with TLS
5. Reloads Caddy
6. Registers the service on the dashboard with health monitoring
### Dashboard
Real-time service cards showing status (up/slow/down), response time, uptime percentage, and container ID. Each card has controls to open the service, restart the container, view logs, edit settings, manage auto-login credentials, or delete the service.
Special top-row cards for DNS servers, internet connectivity, TOTP auth status, and the certificate authority.
### Smart Arr Connect
A four-phase wizard that auto-detects Plex, Radarr, Sonarr, Overseerr/Jellyseerr, and Prowlarr, fetches their API keys, and wires them together automatically — connecting Overseerr to Plex, configuring Prowlarr with indexers for Radarr/Sonarr, etc.
### Auto-Login SSO
Per-service credential storage that authenticates users into services transparently via Caddy's `forward_auth` directive. Supports cookie-based auth, JWT-based auth (Open WebUI, Plex), IP-based auth (router), and Emby/Jellyfin token auth with separate device IDs to avoid token invalidation.
### DashCA (Certificate Authority Distribution)
A static site at `ca.sami` that auto-detects the visitor's OS and provides one-click installation of the root CA certificate. Supports Windows (PowerShell), macOS (.mobileconfig), Linux (shell script), iOS (profile), and Android (direct .crt download).
### Monitoring and Operations
- **Health Checker**: Periodic HTTP probes with configurable endpoints per service
- **Resource Monitor**: Per-container CPU, memory, disk I/O, and network stats
- **Update Manager**: Checks Docker Hub for newer image versions, one-click updates
- **Backup/Restore**: Export/import full dashboard configuration as JSON
- **Audit Logger**: Tracks all administrative actions
- **Error Log Viewer**: Aggregated error logs with severity filtering
- **Metrics**: Request counts, response times, error rates, business events (deploys, deletions, DNS records created)
- **Notifications**: Configurable alerts for health check failures and resource thresholds
### Security
- TOTP two-factor authentication with QR code setup
- CSRF token protection on all mutating endpoints
- Helmet security headers
- Rate limiting (general, strict, TOTP tiers)
- Input validation and sanitization (via `validator` library)
- AES-256-GCM credential encryption with OS keychain integration
- Docker security scanning
- API key management
- Non-root container execution with health checks
### Other Features
- Three themes (dark, light, blue)
- Keyboard shortcuts
- Customizable logo with position control
- Weather widget
- Setup wizard with three modes (Simple, Homelab, Public Server)
- Guided onboarding tour (Driver.js)
- Tailscale integration for access control
- Media folder browser for configuring volume mounts
- Interactive API documentation (OpenAPI/Swagger)
---
## Architecture Diagram
```
Browser (index.html)
Caddy :443 ─── TLS (internal CA) ───┐
│ │
├── /api/* → caddy-api :3001 │
├── *.sami → reverse proxy │
│ to Docker containers │
└── ca.sami → static DashCA site │
caddy-api container │
├── Express (server.js) │
│ ├── 20 route modules │
│ ├── State Manager (lock) │
│ ├── Credential Manager │
│ ├── Health Checker │
│ ├── Resource Monitor │
│ └── Metrics Collector │
│ │
├──→ Docker Engine (dockerode) │
├──→ Caddy Admin API :2019 │
├──→ Technitium DNS :5380 │
└──→ services.json (file-locked) │
```
## Current State
**Version**: 0.95 (1.0 = public release)
The project is fully functional and in daily use. All core features work. The codebase has a test suite (17 test files under `__tests__/`) covering validators, crypto, health checks, state management, API endpoints, and integration scenarios.
---
## Obstacles to v1.0 Release
### 1. Windows-Only — No Cross-Platform Support
DashCaddy was built on and for Windows. The entire deployment model assumes:
- `C:/caddy/` as the production path
- Windows-style path handling throughout (`C:\caddy\Caddyfile`, `host.docker.internal`)
- Docker Desktop for Windows
- Windows Task Scheduler for backups
- PowerShell for CA certificate installation
A Linux or macOS user cannot run this without significant path rewiring. For a public release, either the documentation must clearly state "Windows only" or the path handling needs to be abstracted with platform-aware defaults.
### 2. Hardcoded Infrastructure Assumptions
The codebase has assumptions baked in that only apply to the author's setup:
- **`.sami` TLD**: The local domain suffix is referenced throughout (Caddyfile templates, DNS record creation, documentation). A public user would need their own TLD — this needs to be a first-run configuration option, not a find-and-replace exercise.
- **Technitium DNS**: DNS automation assumes Technitium's REST API. Users running Pi-hole, CoreDNS, or no local DNS server have no path. The DNS layer needs to be pluggable or clearly documented as a hard requirement.
- **Docker Desktop**: Container operations assume Docker Desktop's `host.docker.internal` hostname. Native Docker on Linux uses `localhost` differently.
- **Caddy internal CA**: The TLS model assumes Caddy's built-in PKI. Users wanting Let's Encrypt or other CAs need a different onboarding flow (partially addressed by the "Public Server" setup wizard mode).
### 3. Single-Page HTML Monolith
The frontend is a ~12,000-line single HTML + 33 JS files architecture with no build step, no bundler, no framework, and no component system. While this means zero build tooling to configure, it creates obstacles:
- No minification or tree-shaking — the full payload is served on every load
- No code splitting — all 33 modules load upfront
- IIFEs communicate through `window` globals — fragile, hard to test
- No TypeScript — no compile-time safety on a 12k-line frontend
- CSS is embedded in the HTML — no style extraction or scoping
This works fine for a personal tool but makes contribution and maintenance harder at scale.
### 4. No Automated Test Coverage for the Frontend
The backend has 17 test files with unit and integration tests. The frontend has zero tests. The dashboard UI is the primary interface users interact with, and it has no test safety net — no unit tests, no E2E tests, no screenshot regression tests.
### 5. No CI/CD Pipeline
There is no GitHub Actions workflow, no pre-commit hooks, no automated linting, and no automated test runs. The deployment process is manual:
1. Edit files in `e:/CaddyCerts/sites/dashcaddy-api/`
2. Copy JS files to `C:/caddy/sites/dashcaddy-api/`
3. Run `docker restart caddy-api`
A public project needs at minimum: automated tests on push, a linter, and a documented release process.
### 6. No Installation or Setup Documentation
There is no README explaining how to install DashCaddy from scratch. The `CLAUDE.md` is an internal reference for AI assistants. A new user would need:
- Prerequisites (Docker Desktop, Caddy, Technitium, Node.js)
- Step-by-step installation guide
- First-run configuration walkthrough
- Troubleshooting guide
- Architecture overview
### 7. Single-User Only
There is no concept of user accounts, roles, or permissions. TOTP protects access but there's one global session. For a household with multiple users, there's no way to give someone read-only access or restrict who can deploy/delete containers.
### 8. No Container Orchestration Beyond Single-Host
DashCaddy manages containers on one Docker host. There's no support for:
- Docker Compose stacks (multi-container apps like Nextcloud + MariaDB + Redis)
- Docker Swarm or Kubernetes
- Remote Docker hosts
- Container networking (custom networks, inter-container communication)
Apps that need multiple containers (databases, caches, sidecars) must be set up manually.
### 9. Credential and Secret Management Gaps
While credentials are encrypted with AES-256-GCM, the encryption key management has limitations:
- The master key derivation and storage strategy isn't documented for end users
- Key rotation exists but there's no scheduled rotation or policy
- Backup exports include encrypted credentials but the key management for restoring on a different machine isn't clear
- No integration with external secret managers (Vault, 1Password, etc.)
### 10. Incomplete Template Coverage
55 templates is a strong start, but several popular self-hosted apps are missing, and the template system has constraints:
- No user-contributed templates or template marketplace
- No template versioning — if an image tag changes, templates need manual updates
- No Docker Compose support — templates are single-container only
- Environment variable templating is basic (`{{PORT}}`, `{{SUBDOMAIN}}`) with no conditional logic
### 11. No Persistent Logging or Metrics Storage
Metrics (request counts, response times, business events) are in-memory only — they reset on container restart. There's no time-series database, no Prometheus endpoint, no Grafana integration. For a monitoring-focused dashboard, losing all metrics on restart is a significant gap.
### 12. The Development/Production File Split
The two-directory development model (`e:/CaddyCerts/sites/` for editing, `C:/caddy/` for production) works for the author but would confuse contributors and can't work as-is for other users. A public release needs a single canonical source of truth with a proper build/deploy pipeline.
---
## What's Strong
Despite these obstacles, DashCaddy has substantial strengths that position it well for release:
- **Feature-complete for its core use case**: Deploy apps, manage reverse proxy, automate DNS — it all works
- **Security-first design**: TOTP, CSRF, rate limiting, encryption, input validation, non-root containers
- **Polished UI**: Themes, keyboard shortcuts, onboarding tour, skeleton loaders, responsive design
- **Smart Arr Connect**: A genuinely useful automation that saves significant manual configuration
- **Auto-Login SSO**: Handles the messy reality of diverse auth mechanisms (cookies, JWT, IP-based, localStorage)
- **55 app templates**: Broad coverage of the self-hosting ecosystem
- **Thread-safe state management**: Proper file locking prevents corruption under concurrent access
- **In-memory metrics and monitoring**: Even without persistence, the real-time view is useful
- **Test suite exists**: 17 backend test files covering critical paths
- **Modular route architecture**: 20 route files keep the 125+ endpoints organized and maintainable
## Summary
DashCaddy is a mature, feature-rich self-hosting dashboard that solves a real problem — the tedium of manually configuring Docker + reverse proxy + DNS for every new service. It's daily-driver stable for a single Windows user with Caddy and Technitium DNS.
The gap between "works great for me" and "anyone can install this" is the remaining 0.05 to v1.0. The biggest obstacles are cross-platform support, installation documentation, and removing the hardcoded infrastructure assumptions. The frontend architecture and CI/CD are secondary concerns that matter more for long-term maintainability than for a functional v1.0 release.

View File

@@ -1,6 +1,7 @@
# Backups # Backups
.backup/ .backup/
server-old.js
# Test artifacts # Test artifacts
__tests__/jest.setup.js __tests__/jest.setup.js

View File

@@ -1,7 +1,7 @@
const { SESSION_TTL, APP, PLEX, TIMEOUTS, buildMediaAuth } = require('../../constants'); const { SESSION_TTL, APP, PLEX, TIMEOUTS, buildMediaAuth } = require('../../constants');
const { createCache, CACHE_CONFIGS } = require('../../cache-config'); const { createCache, CACHE_CONFIGS } = require('../../cache-config');
module.exports = function({ authManager, credentialManager, asyncHandler, errorResponse, log }) { module.exports = function({ authManager, credentialManager, fetchT, asyncHandler, errorResponse, log }) {
// App session cache for auto-login // App session cache for auto-login
/** /**
* Auth session handlers routes factory * Auth session handlers routes factory
@@ -71,7 +71,7 @@ module.exports = function({ authManager, credentialManager, asyncHandler, errorR
case 'emby': { case 'emby': {
const mediaAuth = buildMediaAuth(APP.DEVICE_IDS.SSO); const mediaAuth = buildMediaAuth(APP.DEVICE_IDS.SSO);
try { try {
const authResp = await ctx.fetchT(`${baseUrl}/Users/AuthenticateByName`, { const authResp = await fetchT(`${baseUrl}/Users/AuthenticateByName`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-Emby-Authorization': mediaAuth }, headers: { 'Content-Type': 'application/json', 'X-Emby-Authorization': mediaAuth },
body: JSON.stringify({ Username: username, Pw: password }), body: JSON.stringify({ Username: username, Pw: password }),
@@ -95,7 +95,7 @@ module.exports = function({ authManager, credentialManager, asyncHandler, errorR
} }
case 'plex': { case 'plex': {
try { try {
const plexResp = await ctx.fetchT(PLEX.AUTH_URL, { const plexResp = await fetchT(PLEX.AUTH_URL, {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Content-Type': 'application/json', 'Accept': 'application/json', 'Content-Type': 'application/json',
@@ -127,7 +127,7 @@ module.exports = function({ authManager, credentialManager, asyncHandler, errorR
} }
try { try {
const resp = await ctx.fetchT(loginUrl, { const resp = await fetchT(loginUrl, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': contentType, ...extraHeaders }, headers: { 'Content-Type': contentType, ...extraHeaders },
body: loginBody, redirect: 'manual', body: loginBody, redirect: 'manual',

File diff suppressed because it is too large Load Diff

View File

@@ -1,206 +0,0 @@
# DashCaddy Error Handling Cleanup - Summary
## ✅ Completed Changes
### 1. Unified Error Classes (`dashcaddy-api/errors.js`)
- ✅ Merged all error types into single source of truth
- ✅ Added standard DC-XXX error codes
- ✅ All errors inherit from `AppError` with `isOperational` flag
- ✅ Removed duplicate definitions (NotFoundError, AuthenticationError, etc.)
**Available Error Classes:**
- `ValidationError` - DC-400 (client validation failures)
- `AuthenticationError` - DC-401 (auth required, with TOTP support)
- `ForbiddenError` - DC-403 (insufficient permissions)
- `NotFoundError` - DC-404 (resource not found)
- `ConflictError` - DC-409 (resource conflicts)
- `RateLimitError` - DC-429 (rate limiting)
- `DockerError` - DC-500-DOCKER (Docker operation failures)
- `CaddyError` - DC-502-CADDY (Caddy proxy errors)
- `DNSError` - DC-502-DNS (DNS service errors)
- `ServiceUnavailableError` - DC-503 (service unavailable)
### 2. Unified Error Middleware (`dashcaddy-api/error-handler.js`)
- ✅ Single `errorMiddleware` function handles all errors
- ✅ Automatic request context logging
- ✅ Consistent JSON response format
- ✅ Development mode includes stack traces
-`asyncHandler` wrapper eliminates try/catch boilerplate
-`notFoundHandler` for 404 routes
### 3. Server Configuration (`dashcaddy-api/server.js`)
- ✅ Replaced old error handlers with unified system
- ✅ Proper middleware order: routes → notFoundHandler → errorMiddleware
- ✅ Cleaner, more maintainable error handling
### 4. Route Migrations
-`routes/themes.js` - Migrated to throw-based errors
-`routes/services.js` - Updated conflict error to use `ConflictError`
-`routes/containers.js` - Already using new pattern (no changes needed)
## 📊 Before vs After
### Before (Old Pattern)
```javascript
app.get('/api/resource/:id', async (req, res) => {
try {
const resource = await getResource(req.params.id);
if (!resource) {
return res.status(404).json({
success: false,
error: 'Resource not found'
});
}
res.json({ success: true, data: resource });
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
```
**Problems:**
- 9 lines of error handling boilerplate
- Inconsistent error responses
- No automatic logging
- No error codes
- Manual status code management
### After (New Pattern)
```javascript
const { asyncHandler } = require('../error-handler');
const { NotFoundError } = require('../errors');
app.get('/api/resource/:id', asyncHandler(async (req, res) => {
const resource = await getResource(req.params.id);
if (!resource) {
throw new NotFoundError(`Resource ${req.params.id}`);
}
res.json({ success: true, data: resource });
}));
```
**Benefits:**
- 4 lines total (55% less code)
- Consistent error format with DC-404 code
- Automatic request context logging
- Type-safe error classes
- Clean, readable route logic
## 🎯 Standard Error Response Format
All errors now return consistent JSON:
```json
{
"success": false,
"error": "Human-readable error message",
"code": "DC-404",
"resource": "Container abc123"
}
```
**Optional fields:**
- `requiresTotp: true` - For authentication errors requiring TOTP
- `retryAfter: 60` - For rate limit errors
- `field: "email"` - For validation errors
- `details: {}` - Additional context for Docker/Caddy/DNS errors
- `stack: "..."` - Stack trace (development mode only)
## 📝 Migration Guidelines for Remaining Routes
### Pattern 1: Replace Direct Error Responses
```javascript
// OLD
return res.status(400).json({ success: false, error: 'Invalid input' });
// NEW
throw new ValidationError('Invalid input', 'fieldName');
```
### Pattern 2: Wrap Routes with asyncHandler
```javascript
// OLD
router.get('/path', async (req, res) => {
try {
// ... logic
} catch (e) {
res.status(500).json({ success: false, error: e.message });
}
});
// NEW
router.get('/path', asyncHandler(async (req, res) => {
// ... logic (errors automatically caught and handled)
}));
```
### Pattern 3: Use Typed Errors
```javascript
// Instead of generic errors:
throw new Error('Something went wrong');
// Use specific error classes:
throw new DockerError('Container failed to start', 'start', { containerId });
throw new NotFoundError('Container abc123');
throw new ConflictError('Port 8080 already in use', '8080');
throw new ValidationError('Email is required', 'email');
```
## 🔍 Testing Checklist
- [ ] All routes return consistent error format
- [ ] Error codes are unique and meaningful
- [ ] Stack traces only appear in development
- [ ] All errors logged with request context
- [ ] 404 routes handled properly
- [ ] Async errors caught automatically
- [ ] TOTP errors include `requiresTotp: true`
- [ ] Rate limit errors include `retryAfter`
## 📦 Files Modified
1. `dashcaddy-api/errors.js` - Unified error classes
2. `dashcaddy-api/error-handler.js` - Unified middleware
3. `dashcaddy-api/server.js` - Updated error handler registration
4. `dashcaddy-api/routes/themes.js` - Migrated to new pattern
5. `dashcaddy-api/routes/services.js` - Added ConflictError
## 🚀 Next Steps
### High Priority Routes to Migrate
1. `routes/auth/*` - Authentication routes (high traffic)
2. `routes/dns.js` - DNS management
3. `routes/caddy.js` - Caddy proxy operations
4. `routes/recipes/*.js` - Recipe deployment
### Benefits of Full Migration
- **~40% less code** in route handlers
- **100% consistent** error responses
- **Automatic logging** for all errors
- **Type-safe** error handling
- **Better debugging** with standardized codes
## 🎉 Impact
**Code Quality:**
- Eliminated duplicate error handling code
- Standardized error response format
- Type-safe error classes
**Developer Experience:**
- Routes are shorter and more readable
- No more try/catch boilerplate
- Clear error types for different scenarios
**Debugging:**
- All errors logged with request context
- Standard error codes for client-side handling
- Stack traces available in development
**Client Experience:**
- Consistent error format across all endpoints
- Machine-readable error codes
- Clear, descriptive error messages

View File

@@ -1,211 +0,0 @@
# DashCaddy Error Handling Migration - Complete! ✅
## Summary
Successfully migrated DashCaddy from 3 competing error systems to a unified, throw-based error handling architecture.
## What Was Done
### Phase 1: Foundation (Commit 64a0018)
- ✅ Created unified error class system (`errors.js`)
- ✅ Built unified error middleware (`error-handler.js`)
- ✅ Updated server configuration
- ✅ Migrated 2 example routes (themes.js, services.js)
### Phase 2: Mass Migration (Commit b172a21)
- ✅ Migrated 25 route files
- ✅ Converted ~150 error responses
- ✅ Standardized error formats across critical routes
## Files Migrated (27 total)
### Authentication Routes (7 files)
- `routes/auth/totp.js` - TOTP login/setup
- `routes/auth/keys.js` - API key management
- `routes/auth/sso-gate.js` - SSO gateway
- `routes/themes.js` - UI themes
- `routes/services.js` - Service management
- `routes/credentials.js` - Credential storage
- `routes/sites.js` - Site configuration
### Deployment Routes (6 files)
- `routes/apps/deploy.js` - App deployment
- `routes/apps/templates.js` - App templates
- `routes/recipes/deploy.js` - Recipe deployment
- `routes/recipes/manage.js` - Recipe management
- `routes/recipes/index.js` - Recipe listing
- `routes/arr/config.js` - ARR configuration
### Infrastructure Routes (8 files)
- `routes/dns.js` - DNS management (partial)
- `routes/config/assets.js` - Asset management
- `routes/config/backup.js` - Backup configuration
- `routes/config/settings.js` - Settings
- `routes/logs.js` - Log viewing
- `routes/health.js` - Health checks
- `routes/license.js` - License validation
- `routes/notifications.js` - Notification system
### Additional Routes (6 files)
- `routes/browse.js` - File browser
- `routes/ca.js` - Certificate authority
- `routes/arr/credentials.js` - ARR credentials
- `routes/tailscale.js` - Tailscale integration
- `routes/updates.js` - Update management
## Migration Statistics
### Before
- 3 different error systems competing
- Duplicate error class definitions
- Inconsistent error response formats
- ~250+ manual error responses scattered across codebase
- No standard error codes
- Tons of try/catch boilerplate
### After
- 1 unified error system
- Single source of truth for error classes
- Standard DC-XXX error codes
- Automatic request context logging
- 40% less error handling code
- Type-safe error classes
### Code Reduction Example
**Before (9 lines):**
```javascript
try {
const resource = await getResource(id);
if (!resource) {
return res.status(404).json({ success: false, error: 'Not found' });
}
res.json({ success: true, data: resource });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
```
**After (4 lines):**
```javascript
const resource = await getResource(id);
if (!resource) throw new NotFoundError(`Resource ${id}`);
res.json({ success: true, data: resource });
// Middleware handles all errors automatically
```
## Error Class Usage
| Error Class | Count | Use Case |
|------------|-------|----------|
| ValidationError | ~60 | Invalid input, bad format |
| AuthenticationError | ~30 | TOTP, JWT, API key auth |
| ForbiddenError | ~15 | Permission denied |
| NotFoundError | ~40 | Resource not found |
| ConflictError | ~5 | Duplicate resources |
| DockerError | ~10 | Docker operation failures |
| CaddyError | ~5 | Caddy proxy errors |
| DNSError | ~5 | DNS service errors |
## Standard Error Response Format
All errors now return:
```json
{
"success": false,
"error": "Human-readable error message",
"code": "DC-404",
"resource": "Container abc123"
}
```
**Optional fields:**
- `requiresTotp: true` - Authentication requires TOTP
- `retryAfter: 60` - Rate limiting retry delay
- `field: "email"` - Validation error field
- `details: {}` - Additional context
- `stack: "..."` - Stack trace (development only)
## Remaining Work
### Files Still Using Old Pattern (~82 instances)
Most remaining are complex patterns with template literals, variable status codes, or dynamic error messages. These are mostly in:
- `dns.js` - Complex error patterns with API responses
- `services.js` - Some dynamic error handling
- Various other files with edge cases
### Why These Weren't Auto-Converted
- Template literal error messages (`` `Port ${port} in use` ``)
- Variable status codes (`response.status`)
- Wrapped error responses from APIs (`safeErrorMessage(error)`)
- Conditional error patterns
### Recommendation
These remaining instances work fine and can be migrated incrementally as those routes are touched. The critical paths are all converted.
## Testing
### Manual Testing Checklist
- [x] TOTP login flow
- [x] API key generation
- [x] Recipe deployment
- [x] Theme management
- [x] Service creation
- [ ] DNS record management (partial)
- [ ] Full end-to-end deployment
### Expected Behavior
- All errors return consistent JSON format
- Error codes follow DC-XXX pattern
- Stack traces only in development
- Request context logged for all errors
- No breaking changes to API contracts
## Impact
### Developer Experience
- Routes are shorter and more readable
- No more try/catch boilerplate
- Clear error types for different scenarios
- Easier to add new routes
### Debugging
- All errors logged with request context
- Standard error codes for client-side handling
- Better stack traces
- Consistent format makes monitoring easier
### Client Experience
- Consistent error format across all endpoints
- Machine-readable error codes
- Clear, descriptive error messages
- Field-level validation errors
## Performance
No performance impact. The middleware adds negligible overhead and eliminates redundant error handling logic.
## Next Steps (Optional)
1. **Convert remaining complex patterns** - As routes are touched, convert remaining errorResponse calls
2. **Add error code documentation** - Document all DC-XXX codes for API consumers
3. **Client-side error handling** - Update dashboard to handle new error format
4. **Monitoring integration** - Use error codes for alerting/metrics
## Success Metrics
- ✅ 27 files migrated
- ✅ ~170 error responses standardized
- ✅ 40% code reduction in error handling
- ✅ Single source of truth for errors
- ✅ Automatic request logging
- ✅ Type-safe error classes
- ✅ Standard error codes
## Conclusion
The error handling migration is **functionally complete**. All critical routes use the new system, providing consistent, professional error responses. The remaining ~80 instances are edge cases that can be migrated incrementally.
**Result:** DashCaddy now has production-grade error handling that's maintainable, consistent, and developer-friendly. 🎉

View File

@@ -1,13 +0,0 @@
#!/bin/bash
# Systematically fix ctx.* references in all route files
cd /root/.openclaw/agents/main/workspace/dashcaddy-work/dashcaddy-api
# Find all route files with ctx errors
echo "Finding routes with ctx errors..."
for file in $(find routes -name "*.js" -type f | grep -v index.js | grep -v helpers.js); do
errors=$(npx eslint "$file" 2>&1 | grep -c "'ctx' is not defined")
if [ "$errors" -gt 0 ]; then
echo "$errors errors in $file"
fi
done | sort -rn