- ops-agent/src/auth.ts: constant-time compare via timingSafeEqual to prevent timing attacks; store secret as Buffer
- ops-agent/src/index.ts + ops-agent.service: bind on 127.0.0.1:3099 (was 4242, per plan)
- app/api/agent/[...path]/route.ts: Next.js proxy route that verifies ops_session cookie then forwards requests to agent with Authorization: Bearer <secret>
- .env.example + deploy/ops-dashboard.env.example: add OPS_AGENT_SECRET and OPS_AGENT_URL
- README.md: rotation procedure for the shared secret
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CommandDef now uses cmd[] array instead of exec string — no shell splitting
- validateArgs() checks every request arg against allowed list; rejects unknown values
- spawn() called with shell:false (execFile semantics); cwd from config
- Audit log (JSON) per call to stdout → captured by systemd journal
- commands.yml.example updated to new schema with 4 read-only commands
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>