# 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)
