Index: src/server.js
===================================================================
--- src/server.js	(revision f7d142fd84f4cfd1fcf99b1ca2ac8620ef8159f2)
+++ src/server.js	(revision 897c33b994240165ec071824cfd3be00f63ffa3e)
@@ -96,4 +96,12 @@
 app.use((req, res, next) => { res.locals.cspNonce = crypto.randomBytes(16).toString('base64'); next(); });
 
+// HSTS. The default ships a plain long max-age — safe on ANY domain. includeSubDomains +
+// preload are aggressive (they affect the operator's OTHER subdomains and can get their
+// domain baked into browsers near-permanently), so they're opt-in via HSTS_STRICT=1 — set
+// only on domains you fully own (e.g. the klonkt.com fleet). Self-hosters get the safe default.
+// NB: Helmet defaults includeSubDomains to true, so the safe default must disable it explicitly.
+const hstsOptions = { maxAge: 31536000, includeSubDomains: false, preload: false };
+if (process.env.HSTS_STRICT === '1') { hstsOptions.includeSubDomains = true; hstsOptions.preload = true; }
+
 app.use(helmet({
   contentSecurityPolicy: {
@@ -139,5 +147,5 @@
     },
   },
-  hsts: { maxAge: 31536000, includeSubDomains: true, preload: true },
+  hsts: hstsOptions,
   frameguard: { action: 'sameorigin' },
   referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
