feat: base UI shell with themes, auth pages, profile, and role navigation (phase 4)
- embedded Go templates + vanilla ES-module JS + hand-written CSS, no build step
- exact §10 beige light / dark design tokens, square edges (radius 2px),
system font stack, visible focus rings
- theme toggle persisted to localStorage and the user profile
- login/register/change-password pages wired to the auth API
- profile page: avatar upload (image-sniffed, old file cleanup), bio,
contacts, arbitrary extra key/value fields, optimistic-concurrency 409
- role-based top navigation with placeholders for later-phase areas
- GET /files/{id} with scope-based access (session) or signed token (§5.1)
- security headers incl. CSP without unsafe-inline scripts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -57,7 +57,23 @@ func (r *statusRecorder) Write(b []byte) (int, error) {
|
||||
func (r *statusRecorder) Unwrap() http.ResponseWriter { return r.ResponseWriter }
|
||||
|
||||
func (s *Server) withMiddleware(next http.Handler) http.Handler {
|
||||
return s.recoverPanic(s.assignRequestID(s.resolveClientInfo(s.accessLog(next))))
|
||||
return s.recoverPanic(s.assignRequestID(s.resolveClientInfo(s.securityHeaders(s.accessLog(next)))))
|
||||
}
|
||||
|
||||
// securityHeaders applies the §12 hardening headers. CSP allows no inline
|
||||
// scripts — all JS ships as external modules.
|
||||
func (s *Server) securityHeaders(next http.Handler) http.Handler {
|
||||
const csp = "default-src 'self'; script-src 'self'; style-src 'self'; " +
|
||||
"img-src 'self' data:; connect-src 'self'; font-src 'self'; " +
|
||||
"frame-ancestors 'none'; base-uri 'self'; form-action 'self'"
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
h := w.Header()
|
||||
h.Set("Content-Security-Policy", csp)
|
||||
h.Set("X-Frame-Options", "DENY")
|
||||
h.Set("X-Content-Type-Options", "nosniff")
|
||||
h.Set("Referrer-Policy", "strict-origin-when-cross-origin")
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// recoverPanic guarantees no panic escapes a request path: it logs the stack
|
||||
|
||||
Reference in New Issue
Block a user