Files
dashcaddy/DUP-CODE.md
hermes c9d067c2f0
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled
Add Security Center — multi-source event pipeline with dashboard UI
Introduces a unified security event store and HTTP API that ingests events
from any of the configured sources (API audit, Caddy access log, fail2ban,
shared_bans, future remote agents) and surfaces them in the dashboard.

New files:
  src/security/event-store.js      JSONL-backed store + in-memory query index
  src/security/host-registry.js    Registered hosts with per-host API keys
  src/security/event-workers.js    Tail-followers for Caddy/fail2ban/shared_bans logs
  routes/security.js               Events, hosts, ingest, SSE stream endpoints
  status/js/security-center.js     Dashboard modal with Overview/Events/Hosts tabs
  SECURITY-FEATURE.md              Full feature documentation
  DEAD-CODE.md, DUP-CODE.md, HARDENING.md   Prior audits

Modified:
  src/app.js                       Mount /api/v1/security/*
  src/utilities/middleware.js      Add ingest endpoints to PUBLIC_ROUTES
  src/security/audit-logger.js     Mirror audit events into security store
  server.js                        Start security workers on boot
  status/build.js                  Bundle security-center.js
  status/index.html                Add Security button to nav
2026-07-13 02:28:56 -07:00

126 lines
4.1 KiB
Markdown

# DashCaddy Duplicate Code Report
> **Generated:** 2026-07-13
> **Functions scanned:** 107 (≥200 chars body length)
> **Exact-duplicate groups:** 10
## Methodology
1. Extract every top-level `function X() { ... }` declaration
2. Skip functions < 200 chars (helpers, getters, trivial wrappers)
3. Normalize: strip comments, collapse whitespace, replace all identifiers with placeholder
4. SHA-1 the normalized body → identical hashes = duplicate bodies
## ⚠️ Caveats
- **Anonymous functions and arrow functions are not captured** (regex matches `function name(` only)
- **Class methods are not captured** (would need AST parser)
- **Near-duplicates with renamed variables are flagged as the same** (that's the point — after normalization, only structure differs)
- **`module.exports` factory functions are common and look similar** — many route files have a 5-line wrapper like `module.exports = function(ctx) { const router = express.Router(); ... return router; }`. These will show as duplicate groups.
## Exact Duplicate Groups
Functions whose bodies are byte-identical after normalization (ignoring comments, whitespace, and identifier names).
| Hash | Count | Functions |
|---|---:|---|
| `5a3372b656b7` | 2 | `base32Encode`, `base32Encode` |
| `9550727efdf2` | 2 | `base32Decode`, `base32Decode` |
| `e00959ade524` | 2 | `getSecret`, `getSecret` |
| `09498fd55b60` | 2 | `initSecret`, `initSecret` |
| `0f89a717e703` | 2 | `generateCode`, `generateCode` |
| `d92f81854134` | 2 | `parseCode`, `parseCode` |
| `8c3ecfea7f7d` | 2 | `parsePayload`, `parsePayload` |
| `fc844dbaca2f` | 2 | `verifyCode`, `verifyCode` |
| `221e46c497d9` | 2 | `main`, `main` |
| `9573dd3cd485` | 2 | `formatBytes`, `formatBytes` |
### Top Groups (Detail)
#### Hash `5a3372b656b7` (2 copies)
- `src/managers/license-keygen.js:33``base32Encode()` (374 chars)
- `license-keygen.js:33``base32Encode()` (374 chars)
#### Hash `9550727efdf2` (2 copies)
- `src/managers/license-keygen.js:48``base32Decode()` (415 chars)
- `license-keygen.js:48``base32Decode()` (415 chars)
#### Hash `e00959ade524` (2 copies)
- `src/managers/license-keygen.js:62``getSecret()` (216 chars)
- `license-keygen.js:62``getSecret()` (216 chars)
#### Hash `09498fd55b60` (2 copies)
- `src/managers/license-keygen.js:70``initSecret()` (597 chars)
- `license-keygen.js:70``initSecret()` (597 chars)
#### Hash `0f89a717e703` (2 copies)
- `src/managers/license-keygen.js:83``generateCode()` (1331 chars)
- `license-keygen.js:83``generateCode()` (1331 chars)
#### Hash `d92f81854134` (2 copies)
- `src/managers/license-keygen.js:118``parseCode()` (523 chars)
- `license-keygen.js:118``parseCode()` (523 chars)
#### Hash `8c3ecfea7f7d` (2 copies)
- `src/managers/license-keygen.js:135``parsePayload()` (443 chars)
- `license-keygen.js:135``parsePayload()` (443 chars)
#### Hash `fc844dbaca2f` (2 copies)
- `src/managers/license-keygen.js:148``verifyCode()` (1367 chars)
- `license-keygen.js:148``verifyCode()` (1367 chars)
#### Hash `221e46c497d9` (2 copies)
- `src/managers/license-keygen.js:188``main()` (4428 chars)
- `license-keygen.js:188``main()` (4428 chars)
#### Hash `9573dd3cd485` (2 copies)
- `routes/backups.js:693``formatBytes()` (259 chars)
- `routes/apps/restore.js:488``formatBytes()` (259 chars)
## Common Factory Pattern
`module.exports = function(ctx) { const router = express.Router(); ... }`
**49 files** use this factory wrapper pattern:
- `routes/errorlogs.js`
- `routes/docker-resources.js`
- `routes/ca.js`
- `routes/config-drift.js`
- `routes/containers.js`
- `routes/context.js`
- `routes/monitoring.js`
- `routes/workflows.js`
- `routes/services.js`
- `routes/sites.js`
- `routes/logs.js`
- `routes/credentials.js`
- `routes/themes.js`
- `routes/updates.js`
- `routes/dns.js`
- ... and 34 more
Could be extracted to a helper:
```javascript
// src/utilities/route-factory.js
module.exports = function routeFactory(handlerFn) {
return function(deps) {
const router = require('express').Router();
handlerFn(router, deps);
return router;
};
};
```