Coves frontend - a photon fork

feat(deploy): production compose project, deploy script, and /api/me client-address fix master

The frontend is deployed as its own Docker Compose project (`coves-frontend`, from /opt/coves-frontend) that joins the backend's coves-prod-network as an external network. The backend's Caddy proxies coves.social pages to it by container name (coves-prod-frontend:3000); the container publishes no port, because ADDRESS_HEADER=x-real-ip makes adapter-node trust that header from any peer and only Caddy overwrites it unconditionally. Reviewed with /second-opinion (code-reviewer, comment-analyzer, pragma:security, Codex gpt-5.6-sol, Kimi K3); the one critical finding is fixed here rather than deferred. Changes: - docker-compose.prod.yml: single `frontend` service built from the Dockerfile, tagged coves/frontend:<git sha> (VERSION), env_file .env.prod, external coves-prod-network, deliberately no ports. - scripts/deploy.sh: mirrors the backend's script — precondition checks (.env.prod, required vars, network exists), build, `up -d --no-deps`, poll the image HEALTHCHECK to healthy, duplicate-container check, and the ENVIRONMENT.md launch gate (nonce'd CSP at ORIGIN/ through Caddy). - .env.prod.example replaces .env.example as the one production template; README, ENVIRONMENT.md and log.ts point at it. - .claude/commands/deploy.md (gitignored, same convention as the backend) is the /deploy runbook. - fix(hooks): the per-request /api/me session check sent only the Cookie header. Behind Caddy that hop runs once per authenticated page view and the AppView's global rate limiter (100/min) keys on X-Real-IP, so every user on the site would have shared this container's single bucket; past the limit the 429 is handled as "unauthenticated" and everyone is silently logged out. The proxy's guarded address stamping is extracted into $lib/server/client-address (stampClientAddress) and used on both hops: replace semantics, never a client-supplied value, and a missing ADDRESS_HEADER degrades to "no address claim" with a once-per-process diagnostic. Three new hooks tests cover it; 1578/1578 pass. - ENVIRONMENT.md launch-gate curl needs -H 'Accept: text/html' — the production apex routes a bare */* request to the AP instance actor. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>