Skip to content

Milestone 18f: Admin UI (Users / User Groups / Jobs / AppInfo) + Grants tab#34

Merged
Exonical merged 1 commit into
mainfrom
devin/1779423021-milestone-18f-admin
May 22, 2026
Merged

Milestone 18f: Admin UI (Users / User Groups / Jobs / AppInfo) + Grants tab#34
Exonical merged 1 commit into
mainfrom
devin/1779423021-milestone-18f-admin

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

Summary

Replaces the M18f stubs with real implementations across the admin surface and ships the Collection-detail Grants tab.

New routes / pages

  • /admin shell (<AdminLayout/>) — sub-nav across Users / User Groups / Jobs / App info; scope-gated tab visibility.
  • /admin/users — list + filter (username contains) + create / edit dialog (rename, status). Read-only when the caller only holds stig-manager:user:read.
  • /admin/user-groups — list + create / edit dialog with membership multi-select over the existing User list.
  • /admin/jobs — task registry (left), job list (right), per-job run history + 3-second-poll output tail for the latest run, ad-hoc run + delete affordances for stig-manager:op.
  • /admin/app-info — Build / Counts / Runtime / Postgres / Requests cards + AppData tables list. Refreshes every 15 s.

New Collection-detail tab

  • <GrantsTab/> (Manage+) — lists every user / user-group grant on the collection with an inline add-grant form (subject kind ↔ subject ↔ role 1–4) and per-row delete for Manage role and above. The "Coming in M18f" stub is gone.

API client (web/src/lib/api/index.ts)

  • Users: fetchUsers / fetchUser / createUser / updateUser / deleteUser + types (UserSummary, UserCreateInput, UserPatchInput, UsersFilter, UserStatus).
  • User groups: fetchUserGroups / fetchUserGroup / createUserGroup / updateUserGroup / deleteUserGroup + types.
  • Jobs: fetchJobs / fetchJob / fetchJobTasks / fetchJobRuns / fetchJobRunOutput / createJob / startJobRun / deleteJob + Job / JobTask / JobRun / JobRunOutput / JobEvent types.
  • AppInfo / AppData: fetchAppInfoDetail / fetchAppDataTables with a typed AppInfoDetail shape mirroring the API's stable subset (Build / Counts / Postgres / Runtime / Requests) plus an AppDataTable list.
  • Collection grants: fetchCollectionGrants / postCollectionGrants / putCollectionGrant / deleteCollectionGrant + CollectionGrant / GrantPostInput.
  • Every admin call sends elevate=true so the API permits cross-collection visibility.

TanStack Query hooks (web/src/lib/api/hooks.ts)

  • QUERY_KEYS extended with users / userAdmin / userGroups / userGroup / jobs / job / jobTasks / jobRuns / jobRunOutput / appInfoDetail / appDataTables / collectionGrants.
  • New hooks: useUsers / useUser / useCreateUser / useUpdateUser / useDeleteUser, useUserGroups / useUserGroup / useCreateUserGroup / useUpdateUserGroup / useDeleteUserGroup, useJobs / useJob / useJobTasks / useJobRuns / useJobRunOutput / useCreateJob / useStartJobRun / useDeleteJob, useAppInfoDetail / useAppDataTables, useCollectionGrants / usePostCollectionGrants / usePutCollectionGrant / useDeleteCollectionGrant. Invalidation wired through the canonical query keys so list/detail caches stay coherent.

Navigation

  • ADMIN_NAV now has Users / User Groups / Jobs / App info (Jobs moved off the primary nav).

Playwright (e2e/tests/web.spec.ts)

  • 7 new tests bringing the suite to 25/25: admin shell, users list, user-groups page, jobs task-registry, end-to-end create-run job, app-info page, collection grants tab (Owner grant on freshly-created collection).

Roadmap: M18e → Merged (PR #33). M18f → In Review. Next on a separate branch: M18g (STIG Library — benchmarks / rules / CCIs browse + XCCDF import).

Review & Testing Checklist for Human

  • Sign in as admin; the sidebar shows the Admin section with all four entries.
  • /admin/users lists the demo users; create a new user, verify it appears in the table, edit its status to unavailable, then delete it.
  • /admin/user-groups: create a group with at least one member, verify membership round-trips through PATCH.
  • /admin/jobs: create a Job over the noop task, click the run button, confirm the runs list populates and the output card shows lines within ~5s.
  • /admin/app-info: all five cards (Build / Counts / Runtime / Postgres / Requests) render, plus the AppData tables list.
  • On any Collection where you are Owner: open the Grants tab; the existing Owner grant is in the table; add a grant for another user, then delete it.
  • Sign in as evaluator; confirm the admin section is hidden (no stig-manager:user:read or :op:read scopes).

Notes

  • Job event scheduling (cron/recurring/once) is intentionally not exposed in this milestone — only ad-hoc runs via POST /jobs/{jobId}/runs. The data layer already supports schedules; UI for it will come alongside the cron scheduler in a follow-up.
  • The useUserGroupEditDialog always sends the membership snapshot on save (PATCH semantics on the API side replace the list), even if it's unchanged from the loaded value. This is intentional so the user always sees the same outcome as a fresh form submission.
  • Polled useJobRunOutput defaults to a 3 s interval; consumers can override via the refetchIntervalMs option.

Link to Devin session: https://app.devin.ai/sessions/022810763c4643c0848ba894c1512b92
Requested by: @Exonical

…ts tab

Co-Authored-By: Bryce Anglin <brycemanglin@gmail.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@Exonical Exonical merged commit 737dd1b into main May 22, 2026
6 checks passed
@Exonical Exonical deleted the devin/1779423021-milestone-18f-admin branch May 22, 2026 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant