Commit c704bdfa94
Verified · cmc
Layout: unified · split
docs/superpowers/specs/2026-09-22-parity-followup-design.md +28 −16
| @@ -160,23 +160,35 @@ Matches the web's `/admin` and `/admin/users` and nothing else. Account | ||
| 160 | 160 | show, invite, runners, repository administration, the audit log and |
| 161 | 161 | instance statistics stay `no` on both surfaces. |
| 162 | 162 | |
| 163 | - `DashboardModels` decodes `queues` and `server`. The `dashboard` | |
| 164 | command sends `queues` to instance admins only, so its presence is | |
| 165 | the admin signal, as it is for the web (`internal/httpd/admin.go`). | |
| 166 | - The account menu shows Admin when `queues` is present. The admin | |
| 167 | screen shows the queues and the server commit, and links to | |
| 168 | accounts. | |
| 169 | - `AdminUsersViewModel` pages `admin user list [--state | |
| 170 | active|pending|disabled|admin]` through `PagedListModel`, and sends | |
| 171 | `admin user promote|demote|disable|enable <username>` per row. | |
| 163 | - **Who sees it.** `whoami` returns `admin`. The My Profile tab reads it | |
| 164 | when it appears (and again on an account switch) and passes it to | |
| 165 | `AccountMenu`, which shows Admin only when it is true. The menu has no | |
| 166 | model of its own and the dashboard's data lives on another tab, so | |
| 167 | this is the one read that reaches it; `SessionStore` is unchanged. | |
| 168 | - **The admin screen** reads `dashboard` and decodes its admin-only | |
| 169 | `queues` and `server` blocks, the read the web's `/admin` page makes | |
| 170 | (`internal/httpd/admin.go`). It shows the server commit, a link to | |
| 171 | Accounts, and the web's six sections in the web's order — webhook | |
| 172 | deliveries, mail, push, mirrors, builds, dependency checks — each with | |
| 173 | its heading count, its counts line, its retrying or failed rows, and | |
| 174 | the web's empty-queue sentence. A dashboard without `queues` (the | |
| 175 | caller is not an admin) is an empty state saying so. | |
| 176 | - **Accounts** pages `admin user list [--state active|pending|disabled|admin]` | |
| 177 | through `PagedListModel`, with the web's five filters (all, active, | |
| 178 | pending, disabled, admins) as a segmented picker. Each row carries the | |
| 179 | web's two actions, in a per-row menu: Demote for an admin, Promote | |
| 180 | for an active account and a disabled Promote for anyone else; Enable | |
| 181 | for a disabled account and Disable otherwise. Each sends | |
| 182 | `admin user promote|demote|disable|enable <username>` and reloads. | |
| 172 | 183 | - Demote and disable ask for the username to be typed before they |
| 173 | send, as the web does. Promote and enable use the app's standard | |
| 174 | `confirmationDialog`. A row shows only the actions its state allows. | |
| 175 | ||
| 176 | Tests: `queues` decodes and absent means not admin; `admin user list` | |
| 177 | argv per state; each write's argv; demote and disable stay disabled | |
| 178 | until the typed name matches. The live suite skips admin unless the | |
| 179 | signed-in account is an admin; `ios-smoke` is not. | |
| 184 | send, as the web does. Promote and enable ask with a plain alert. | |
| 185 | ||
| 186 | Tests: the six sections' headings, counts, summaries and row text from | |
| 187 | a recorded payload; a dashboard without `queues`; `whoami`'s `admin`, | |
| 188 | including a failed read counting as not admin; each row state's two | |
| 189 | actions; `admin user list` argv per filter and across a page; each | |
| 190 | write's argv and its reload; a refusal surfacing. The live suite | |
| 191 | asserts that `ios-smoke`, which is not an admin, is not offered Admin. | |
| 180 | 192 | |
| 181 | 193 | ## Upstream: krz/gitbay |
| 182 | 194 | |