- store: SQLite (WAL, foreign keys ON, CGO-free driver) + the embedded migration runner; each module's migrations are name-prefixed (D-012) - audit: the append-only audit log; the actor threads via context (R-1) - users: the user_id/GUID/email anchors (D-013) - config: the YAML settings file (D-035) + validation - httpx: cookies · loopback detection · trusted-proxy XFF · CSRF · security headers · redaction - middleware: correlation id · audit · rate limiting - mail: the invite/recovery mailer seam - server: the core DOOR — the resolution switch, the dispatch registry (RegisterModule), the role gates, /setup · enroll/login · recovery flows, the reserved `static` workflow, and the loopback-only bootstrap (D-025)
28 lines
961 B
Go
28 lines
961 B
Go
package httpx
|
|
|
|
import "net/http"
|
|
|
|
// ContentSecurityPolicy is the strict default CSP (SPEC-003 §4). It allows only
|
|
// same-origin assets; the PWA manifest and service worker are same-origin too.
|
|
const ContentSecurityPolicy = "default-src 'self'; " +
|
|
"img-src 'self' data:; " +
|
|
"style-src 'self'; " +
|
|
"script-src 'self'; " +
|
|
"connect-src 'self'; " +
|
|
"object-src 'none'; " +
|
|
"base-uri 'none'; " +
|
|
"form-action 'self'; " +
|
|
"frame-ancestors 'none'"
|
|
|
|
// SetSecurityHeaders writes the baseline security headers on every response
|
|
// (SPEC-003 §4). HSTS is set only when the app is served over https (secure).
|
|
func SetSecurityHeaders(w http.ResponseWriter, secure bool) {
|
|
h := w.Header()
|
|
h.Set("X-Content-Type-Options", "nosniff")
|
|
h.Set("Referrer-Policy", "no-referrer")
|
|
h.Set("X-Frame-Options", "DENY")
|
|
h.Set("Content-Security-Policy", ContentSecurityPolicy)
|
|
if secure {
|
|
h.Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
|
|
}
|
|
}
|