security: make dashboard API authorization route-bound and deny by default
#2,466 opened on Jul 12, 2026
Repository metrics
- Stars
- (4,293 stars)
- PR merge metrics
- (PR metrics pending)
Description
Summary
Bind dashboard route registration and permission policy into one deny-by-default contract. Owner surfaces: dashboard/backend/auth/middleware.go, dashboard/backend/auth/schema.go, and dashboard/backend/router/proxy_routes.go.
Current behavior
Protected routes and permission resolution are maintained separately. Unmapped API routes inherit a read permission, while declared Replay and feedback permissions are not applied at their proxy boundary. This makes new routes fail open and makes some role controls ineffective.
Expected behavior
Every protected route and method has exactly one permission, sensitivity, and audit declaration at registration time. Unknown or incomplete registrations are denied, and Replay, feedback, inference, config, ML, and OpenClaw permissions remain independently enforceable.
Acceptance
- Register route, methods, permission, audit action, and sensitivity together.
- Deny unknown or policy-incomplete routes.
- Enforce
replay.readfor Replay andfeedback.submitfor feedback/learning; define an explicit inference permission. - Fail startup or a contract test when any protected route lacks policy metadata.
- Prove independent grant and revoke behavior for config, Replay, feedback, inference, ML, and OpenClaw roles.
Validation
- Add an exhaustive registered-route and method inventory test with exactly one permission mapping per entry.
- Add custom-role positive and negative tests plus unknown-route denial.
- Run
cd dashboard/backend && go test -race ./auth ./router ./handlers. - Run the affected dashboard and router E2E profile selected by
make agent-e2e-affected.
Related
- Parent audit: #2375
- Security index: #2357
- Replay access boundary: #1146
- Feedback provenance: #1452