fix(config): monitoring.public gate was dead 4 ways — live gate + schema + dedupe (DC-096) [glm-grade=A]
CI / Test & Lint (push) Canceled after 0s
CI / Security audit (push) Canceled after 0s

The documented hardening option for exposed deploys (monitoring: {public: false}
in config.json / MONITORING_PUBLIC env) never worked:
1. applyConfigFields dropped the monitoring key entirely
2. monitoring missing from config-schema KNOWN_KEYS (Unknown-key warnings)
3. MONITORING_PUBLIC frozen at mount + re-required singleton instead of injected dep
4. PUBLIC_ROUTES had unconditional duplicate entries defeating the gated spread

- site.js: copy monitoring through; drop dead write-only siteConfig.caName
- config-schema: +monitoring key, validateMonitoring (public must be boolean);
  remove never-written typo-footgun keys setupCompleted/setupMode (git -S: zero writers ever)
- middleware: live isMonitoringPublic() (env > config > default public), per-request
  gate via monitoring:true flag, remove duplicate unconditional route entries
- default unchanged (endpoints stay public — System Overview widget)

Tests: +11 (__tests__/monitoring-public-gate-dc096.test.js); suite 118/2735 green.
Judge: GLM-5.3 cold-read A (deleg_98aba845), URN urn:ump:zgvtskqljurasdagc632atnybb2p6gakk4cxcmjd3i4ivy7rvwta
This commit is contained in:
Hermes
2026-08-22 21:35:51 -07:00
parent 83ef84d218
commit bb59595d6d
4 changed files with 247 additions and 25 deletions
+5 -2
View File
@@ -13,7 +13,6 @@ const { loadAndMigrate, CURRENT_VERSION } = require('./migrations');
const siteConfig = {
tld: '.home',
caName: '',
dnsServerIp: '',
dnsServerPort: CADDY.DEFAULT_DNS_PORT,
dashboardHost: '',
@@ -27,7 +26,6 @@ const siteConfig = {
function applyConfigFields(raw) {
siteConfig.tld = raw.tld || '.home';
if (!siteConfig.tld.startsWith('.')) siteConfig.tld = '.' + siteConfig.tld;
siteConfig.caName = raw.caName || '';
siteConfig.dnsServerIp = (raw.dns && raw.dns.ip) || '';
siteConfig.dnsServerPort = (raw.dns && raw.dns.port) || CADDY.DEFAULT_DNS_PORT;
siteConfig.dashboardHost = raw.dashboardHost || `status${siteConfig.tld}`;
@@ -37,6 +35,11 @@ function applyConfigFields(raw) {
siteConfig.domain = raw.domain || '';
siteConfig.routingMode = raw.routingMode || 'subdomain';
siteConfig.pylon = raw.pylon || null;
// DC-096: `monitoring` was previously NOT copied out of raw config, so the
// documented hardening option `monitoring: { public: false }` (middleware.js
// MONITORING_PUBLIC) silently never applied — siteConfig.monitoring stayed
// undefined forever. Copy it through so the middleware actually sees it.
siteConfig.monitoring = raw.monitoring || null;
}
function validateAndLogConfig(raw, log) {
const { valid, errors: configErrors, warnings: configWarnings } = validateConfig(raw);