Problem
GET /v1/installations, /v1/installations/:id/health, /v1/installations/:id/repair, and /repair/refresh (src/api/routes.ts ~2560-2591) carry no inline role/ownership check — they're reachable only because the coarse canSessionAccessPath gate falls through to the global operator check for any path not on its explicit allowlist, and none of these are on that allowlist. Today only the true fleet operator can see or act on installation health — no hosted tenant has any self-service equivalent for their own installation's health/repair.
Area
src/api/routes.ts, src/services/control-panel-roles.ts.
Proposal
Add a tenant-scoped equivalent, reusing /v1/app/maintainer-dashboard's exact scoping pattern (loadControlPanelRoleSummary/loadControlPanelAccessScope, src/services/control-panel-roles.ts) so a hosted tenant can see and trigger repair on their own installation without operator involvement. Explicitly does not include bulk/installation-level pause-all-repos controls (#7676) — that's a separate, real design decision (granularity, blast radius, audit trail), not assumed here.
Deliverables
Resources
src/api/routes.ts (~2560-2591)
src/services/control-panel-roles.ts (loadControlPanelRoleSummary, loadControlPanelAccessScope — the required scoping pattern)
Boundaries
Does not add bulk/cross-repo controls (#7676, separate). Single-installation self-service only.
maintainer-only — a scoping bug here lets one tenant read or trigger repair on another tenant's installation (the same class of risk #7660 was re-locked for); the scoping design needs maintainer review before implementation, even though the mechanism itself is otherwise mechanical.
Problem
GET /v1/installations,/v1/installations/:id/health,/v1/installations/:id/repair, and/repair/refresh(src/api/routes.ts~2560-2591) carry no inline role/ownership check — they're reachable only because the coarsecanSessionAccessPathgate falls through to the global operator check for any path not on its explicit allowlist, and none of these are on that allowlist. Today only the true fleet operator can see or act on installation health — no hosted tenant has any self-service equivalent for their own installation's health/repair.Area
src/api/routes.ts,src/services/control-panel-roles.ts.Proposal
Add a tenant-scoped equivalent, reusing
/v1/app/maintainer-dashboard's exact scoping pattern (loadControlPanelRoleSummary/loadControlPanelAccessScope,src/services/control-panel-roles.ts) so a hosted tenant can see and trigger repair on their own installation without operator involvement. Explicitly does not include bulk/installation-level pause-all-repos controls (#7676) — that's a separate, real design decision (granularity, blast radius, audit trail), not assumed here.Deliverables
Resources
src/api/routes.ts(~2560-2591)src/services/control-panel-roles.ts(loadControlPanelRoleSummary,loadControlPanelAccessScope— the required scoping pattern)Boundaries
Does not add bulk/cross-repo controls (#7676, separate). Single-installation self-service only.
maintainer-only — a scoping bug here lets one tenant read or trigger repair on another tenant's installation (the same class of risk #7660 was re-locked for); the scoping design needs maintainer review before implementation, even though the mechanism itself is otherwise mechanical.