Commit Graph
6 Commits
Author SHA1 Message Date
Hermes b4e09af712 [grade=A urn:ump:swcz3quualvlmdanpqm5v46cr6zkazes7erbftk6rj3jxv6ip4fa] docs(DC-170): changelog rebuild, version sync, API-SURFACE regen (audit batch 7)
Customer-facing professionalism tier (AUDIT-2026-10-27.md findings 34-39):

- CHANGELOG.md rebuilt to Keep-a-Changelog: ONE Unreleased section, the
  2026-08-12 hardening sprint folded into 1.17.0 (no v1.16.0 tag exists,
  verified via git tag -l), ALL 7 judge-grade/URN lines moved out of
  customer copy into RELEASE-EVIDENCE-internal.md, missing DC-166/169
  entries added, full DC-170 sweep entry written, DC-171 DNS-parity
  ticket recorded, date order strictly descending across all 22
  sections (1.1.5 restored with its true content after the re-sort ate
  the heading), compare-link chain filled (Unreleased from v1.17.0,
  1.17.0 from v1.14.6-patched, 18 missing version links added)
- VERSION 1.15.0 -> 1.17.0 + openapi.yaml 1.15.0 -> 1.17.0 (three-way
  drift closed: VERSION=package.json=openapi; start.sh build stamps
  single-sourced)
- README: quickstart endpoints rewritten against the live router (the
  fictional /api/caddy/{config,reload} section replaced with the real
  /api/v1/caddy/* routes from routes/sites.js), 50+ -> 78 templates
  (proven in VERIFY-OUTPUT.txt via require of src/docker/app-templates),
  version badge 1.17.0, yourusername links -> sami7777, roadmap
  reconciled with shipped features (multi-user DC-048, DNS UI DC-166,
  backup automation marked shipped), verification note scoped to the
  MCP drift gate's actual coverage
- API-SURFACE.md regenerated: 443 handler rows / 368 unique paths / 441
  unique operations / 88 public rows, Known Limitations section (static
  extraction, line-oriented, may omit multiline/computed/chained
  registrations), exact duplicate registrations with file:line
- VERIFY-OUTPUT.txt: verbatim command/output transcript proving all
  version + count claims (sha256 of the generated doc recorded and
  matching)
- state-manager test mock extended for the atomic tmp+rename contract

Judge rounds: r1 D -> r2 D -> r3 D -> r4 D -> r5 C -> r6 C -> r7 C ->
r8 C -> r9 C -> r10 A (each round fixed blockers in-lane; no bypasses).
r10 independently reproduced all counts and the generated doc hash
against the live repository.
2026-10-29 02:29:07 -07:00
Hermes 65457ff8e0 feat(security): activate caddy security-event pipeline — bounded first-start replay, self-noise filter, host fidelity (DC-113) [glm-grade=A]
CI / Test & Lint (push) Canceled after 0s
CI / Security audit (push) Canceled after 0s
The caddy tail worker (DC-112) was 100% dead in prod: no /var/log/caddy
mount, no CADDY_ACCESS_LOG env, no global access log in the Caddyfile.
Store census 45,912 events, 100% source_type 'api', ZERO 'caddy'.

- createTail: firstStartMaxBytes (5 MiB) bounds first-ever-start replay
  against a long-lived access.log; multi-chunk partial-line discard on
  the jump; normal restarts resume at exact persisted offset (judge r1
  fix-first fold)
- worker: self-noise filter drops our own probe UAs
  (DashCaddy-Probe/1.0, DashCaddy-HealthCheck/1.0) from the derived
  store — raw log keeps everything; ~50-100 events/min of probe noise
  would otherwise bury perimeter signal in the 100k-cap store
- worker: metadata.host reads request.host (real caddy JSON nests it;
  verified against live /var/log/caddy/seeds.log — the DC-112 read was
  always null on live lines); top-level fallback kept
- worker: onAppear recovery log (DC-112 judge polish fold)
- start.sh: -v /var/log/caddy:/var/log/caddy:ro + CADDY_ACCESS_LOG env
- README: dead caddy-api/ dir refs -> dashcaddy-api/ (queue item e)
- tests: +12 DC-113 pins (hermetic, real worker + store); DC-112
  fixtures corrected to the real nested request.host shape

126 suites / 2841 tests green. Judge: GLM-5.3 round-1 B, round-2 A
(SHIP). Verdict urn:ump:mccln523fptotuvrmddlqpf4zpkrxf273tg4kyytuyy3776rj3pq
2026-08-23 12:40:32 -07:00
Hermes c429b8fdd7 fix(security): redact-on-rotate for error.log archive + README PII docs (DC-108) [glm-grade=B]
CI / Test & Lint (push) Canceled after 0s
CI / Security audit (push) Canceled after 0s
DC-095 masks emails at every live log sink; the rotated archive was the
remaining belt-and-braces gap — any future sink that forgets masking would
persist raw PII in error.log.1 for a full rotation cycle. appendErrorLog
now scrubs the freshly rotated archive with the SAME canonical mask
(sa****@example.com) via atomic rewrite (sibling .redact-<pid> temp, wx
open preserving mode else 0600, fsync, rename). Scrub failure is caught
and logged; the new error line is still appended. Stale crash-leftover
.redact-<pid> temps are swept best-effort on every rotation. Also
documents scripts/redact-log-pii.js usage in README (queue item e).

Judge: GLM-5.3 cold read (deleg_e7cd7f8c), round-1 grade B ship — both
nits addressed in-commit: stale-temp sweep (new 5th test pins it),
quoted-local-part mask edge deferred as pre-existing DC-095 primitive.

Tests: 122 suites / 2790 green (+5 DC-108 pins; was 2785 post-DC-107).
2026-08-23 05:22:04 -07:00
Hermes 7f6203b2f7 fix(readme): correct license badge — MIT to Proprietary EULA, bump version badge to 1.15.0
The README showed MIT license and version 1.0.0 — both wrong. LICENSE
file is a 125-line proprietary EULA (added at v1.5.0). Version badge
was stale from initial release.

Refs: DashCaddy audit 2026-08-02
2026-08-03 00:37:15 -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
Sami f61e85d9a7 Initial commit: DashCaddy v1.0
Full codebase including API server (32 modules + routes), dashboard frontend,
DashCA certificate distribution, installer script, and deployment skills.
2026-03-05 02:26:12 -08:00