update_server/docs/agents/handoffs/07-security-deploy.md
2026-06-10 20:51:17 +03:00

7.4 KiB

Agent

Name: Agent 07 - Security And Deployment Hardening

Stage: Security And Deployment Hardening

Date: 2026-04-15

Scope

Hardened the existing Go/chi/SQLite application for internet-facing deployment without changing the product model or admin/client flow.

Completed in this stage:

  • added stricter HTTP server defaults:
    • ReadHeaderTimeout
    • MaxHeaderBytes
    • higher default read/write/idle timeouts suitable for uploads and authenticated downloads
  • added global security headers and route-specific cache controls:
    • Content-Security-Policy
    • X-Frame-Options
    • X-Content-Type-Options
    • Referrer-Policy
    • Permissions-Policy
    • Cross-Origin-Opener-Policy
    • Cross-Origin-Resource-Policy
    • Strict-Transport-Security when APP_BASE_URL is https
    • Cache-Control: no-store on admin and protected client API responses
    • Vary: Cookie or Vary: Authorization on the appropriate routes
  • added trusted-proxy awareness so forwarded headers are only trusted when TRUST_PROXY_HEADERS=true;
  • added in-memory rate limiting for:
    • POST /admin/login
    • protected client API routes under /api/v1
  • added CSRF protection for all admin POST flows, including login, logout, project/tag/API key forms, tag attach or detach, archive or restore, and multipart release upload;
  • rotated or cleared the admin CSRF cookie on login and logout, and scoped both session and CSRF cookies to /admin;
  • tightened local data directory permissions for SQLite and data storage;
  • added regression coverage for CSRF rejection, hardened cookie defaults, security headers, and both rate-limited route groups;
  • added first-pass deployment assets:
    • multi-stage Dockerfile
    • hardened docker-compose.yml
    • Caddy example
    • Nginx example
    • env example
    • deployment, Proxmox, backup, and restore notes.

Files Changed

  • /Users/delete/projects/update_server/internal/config/config.go
  • /Users/delete/projects/update_server/internal/app/app.go
  • /Users/delete/projects/update_server/internal/db/open.go
  • /Users/delete/projects/update_server/internal/auth/service.go
  • /Users/delete/projects/update_server/internal/http/router.go
  • /Users/delete/projects/update_server/internal/http/security.go
  • /Users/delete/projects/update_server/internal/http/rate_limit.go
  • /Users/delete/projects/update_server/internal/http/csrf.go
  • /Users/delete/projects/update_server/internal/http/auth_handlers.go
  • /Users/delete/projects/update_server/internal/http/admin_common.go
  • /Users/delete/projects/update_server/internal/http/admin_api_keys.go
  • /Users/delete/projects/update_server/internal/http/view_data.go
  • /Users/delete/projects/update_server/internal/http/auth_integration_test.go
  • /Users/delete/projects/update_server/internal/http/projects_integration_test.go
  • /Users/delete/projects/update_server/internal/http/api_keys_integration_test.go
  • /Users/delete/projects/update_server/internal/http/security_integration_test.go
  • /Users/delete/projects/update_server/web/templates/layouts/base.gohtml
  • /Users/delete/projects/update_server/web/templates/pages/login.gohtml
  • /Users/delete/projects/update_server/web/templates/pages/project_form.gohtml
  • /Users/delete/projects/update_server/web/templates/pages/project_detail.gohtml
  • /Users/delete/projects/update_server/web/templates/pages/tag_form.gohtml
  • /Users/delete/projects/update_server/web/templates/pages/api_key_form.gohtml
  • /Users/delete/projects/update_server/web/templates/partials/csrf_field.gohtml
  • /Users/delete/projects/update_server/.dockerignore
  • /Users/delete/projects/update_server/Dockerfile
  • /Users/delete/projects/update_server/docker-compose.yml
  • /Users/delete/projects/update_server/deploy/Caddyfile.example
  • /Users/delete/projects/update_server/deploy/nginx.update-server.conf.example
  • /Users/delete/projects/update_server/deploy/update-server.env.example
  • /Users/delete/projects/update_server/docs/DEPLOYMENT.md
  • /Users/delete/projects/update_server/docs/agents/handoffs/07-security-deploy.md

Database Changes

  • no migrations or schema changes were required;
  • SQLite remains the production database;
  • deployment notes now explicitly call out WAL-mode backup and restore handling for:
    • db.sqlite
    • db.sqlite-wal
    • db.sqlite-shm
    • artifacts/.

API Or Route Changes

  • no new product endpoints were added;
  • middleware behavior changed for existing routes:
    • all /admin responses now emit hardened headers and no-store caching rules;
    • all /admin POST routes now require a valid CSRF token;
    • POST /admin/login is rate limited by client IP;
    • protected /api/v1 routes now emit hardened headers and no-store caching rules;
    • protected /api/v1 routes are rate limited by client IP before API-key auth;
  • session cookies are now scoped to /admin and retain HttpOnly, SameSite=Lax, and conditional Secure;
  • CSRF cookies are now scoped to /admin and use HttpOnly, SameSite=Strict, and conditional Secure.

Commands And Tests Run

  • gofmt -w internal/config/config.go internal/app/app.go internal/db/open.go internal/auth/service.go internal/http/router.go internal/http/security.go internal/http/rate_limit.go internal/http/csrf.go internal/http/auth_handlers.go internal/http/view_data.go internal/http/admin_common.go internal/http/admin_api_keys.go internal/http/auth_integration_test.go internal/http/projects_integration_test.go internal/http/api_keys_integration_test.go internal/http/security_integration_test.go - passed
  • go test ./internal/http - passed
  • go test ./... - passed
  • go build ./cmd/server - passed
  • go build ./cmd/migrate - passed
  • docker compose config - could not run in this environment because docker is not installed

Known Limitations

  • rate limiting is in-memory and per-process, so counters reset on restart and are not shared across multiple app instances;
  • Docker and reverse-proxy examples were added and reviewed statically, but they were not live-validated here because Docker is unavailable in this workspace;
  • Strict-Transport-Security only appears when APP_BASE_URL is configured with https, which is the intended production setup behind TLS termination;
  • the proxy still must be configured correctly to keep the app private and to strip or control forwarded headers before TRUST_PROXY_HEADERS=true is safe.

Run the Agent 07 validation pass, with special attention to:

  • CSRF enforcement on every admin POST flow, including multipart upload;
  • security headers and private-cache headers on admin and protected client API responses;
  • login and client API rate limiting behavior;
  • cookie flags and /admin cookie scoping;
  • deployment docs and example proxy/container files on a host that has Docker and a reverse proxy available.

Notes For Validator

  • verify that a missing or invalid admin CSRF token returns 403 and that the normal admin flows still succeed when the token is present;
  • verify that session cookies are only scoped to /admin and that secure-cookie behavior follows the configured APP_BASE_URL scheme;
  • verify that TRUST_PROXY_HEADERS=false leaves client IP handling on the socket remote address;
  • verify that protected /api/v1 responses include Cache-Control: no-store, Vary: Authorization, and the shared security headers;
  • if possible, validate docker compose up --build plus one reverse-proxy example on a real machine, since that could not be executed in this environment.