- Rate-limit /api/flows/start to 10 req/min per user (in-memory, matches login pattern)
- Add middleware.ts: validates x-csrf-token header against csrf_token cookie on all
API POST requests; issues the cookie on GET if missing; sets CSP, X-Frame-Options,
X-Content-Type-Options, and Referrer-Policy on all responses
- Add lib/csrf.ts: client-side apiFetch() wrapper that injects the CSRF header
- Update all client components (login, useFlowRun, docker, caddy, git, systemd)
to use apiFetch() for POST requests
- Cookie config in login route already correct (NODE_ENV check, httpOnly, sameSite=strict)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ops-agent/src/lib/flow-runner.ts: loads YAML flows, validates all steps
against the command whitelist, executes sequentially; supports dry_run
(emits WOULD RUN lines) and on_failure: abort|continue per step
- ops-agent/src/routes/flow.ts: POST /agent/v1/flow { flow_key, dry_run }
streams step_start/stdout/stderr/step_done/done SSE events
- ops-agent/src/index.ts: register flow route, add FLOWS_PATH env var
- ops-agent/flows.example/: three flow definitions — update_scrum4me_web,
update_mcp_worker, update_caddy_config; deploy to /etc/ops-agent/flows/
- ops-agent/commands.yml.example: add curl_smoke_scrum4me_web and
docker_compose_ps_worker smoke-test commands
- app/api/flows/run/route.ts: Next.js proxy — creates FlowRun/FlowStep
DB records per step, forwards SSE stream to browser
- hooks/useFlowRun.ts: add startFlow(flowKey, dryRun) method; handle
step_start events to display step headers in the terminal
- components/StreamingTerminal.tsx: add 'info' line type (sky-400) for
step headers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>