docs: propose dashboard RBAC, tenant isolation, and operator views (issue #76) - #91
Merged
Conversation
…ssue #76) A design proposal, not an accepted ADR -- deliberately left for human review before implementation starts, unlike ADR-013/014/015 this session: this one decides who can see which tenant's data, a real security boundary rather than a narrower technical decision. #76 itself says this needs its own design pass before implementation, given its size; this is that pass. Grounds the proposal in what already exists rather than inventing new mechanism: - Authentication is already done (ADR-014): session API keys via wallet-signature login. - Ownership is already done (#12): workloads.owner_id, already scoped correctly by internal/workloadapi's gRPC surface -- just never wired into the dashboard's HTTP surface, which reads everything unauthenticated today. - Operator-view data (queue depth, worker claims, retry counts) already exists as plain columns on `workloads` (attempt_count, next_attempt_at, worker_id, worker_lease_until) -- no new schema needed for that slice. Proposes: a single `users.role` column (tenant/operator, not a many-to-many table -- deliberately avoids speculative complexity), a three-tier endpoint classification (public/tenant/operator) covering every existing and planned dashboard endpoint, an explicit correction that "validator views" are public data (not a fourth role -- validators authenticate to the Agent/chain, never to the dashboard), `controlplane-admin grant-role` mirroring the existing break-glass operator-tool pattern, a `requireRole` middleware wrapping routes at registration (auditable in one place), a first-pass secret-redaction table that flags workload `definition`'s env vars as the one real leakage risk needing an explicit redaction decision before tenant workload views can ship, three open questions for the accepting reviewer instead of silently guessing at them, and a 6-slice implementation sequence mirroring ADR-013's slicing discipline. Leaves #76 open: RBAC implementation itself, user/operator views, the secret-redaction decision, and E2E tests are all still outstanding -- this document unblocks them, it doesn't build them. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A design proposal, not an accepted ADR — deliberately left for explicit review before implementation starts, unlike ADR-013/014/015 this session. This one decides who can see which tenant's data, a real security boundary rather than a narrower technical decision. Issue #76 itself says this needs its own design pass before implementation, given its size — this is that pass.
New:
docs/control-plane/dashboard-rbac-and-tenant-isolation-proposal.mdGrounding
Built on what already exists rather than inventing new mechanism:
workloads.owner_id, already scoped correctly byinternal/workloadapi's gRPC surface — just never wired into the dashboard's HTTP surface, which reads everything unauthenticated today.workloads(attempt_count,next_attempt_at,worker_id,worker_lease_until) — no new schema needed for that slice.Proposal summary
users.rolecolumn (tenant/operator), not a many-to-many table — deliberately avoids speculative complexity the MVP doesn't need yet.controlplane-admin grant-rolemirroring the existing break-glass operator-tool pattern (create-user/issue-key).requireRolemiddleware wrapping routes at registration — the whole authorization surface auditable in one function, not scattered per-handler checks.definition's env vars as the one real leakage risk, needing an explicit redaction decision before tenant workload views can ship (not an oversight to catch later).Testing
Docs-only change, no code. Cleanly based on current
main(no dependency on the still-unmerged #89).This leaves #76 open: RBAC implementation itself, user/operator views, the secret-redaction decision, and E2E tests are all still outstanding — this document unblocks them, it doesn't build them.
🤖 Generated with Claude Code