Skip to content

Milestone 23a: 3-pane asset review workspace (keyboard-first) - #43

Merged
Exonical merged 2 commits into
mainfrom
devin/1779658439-milestone-23a-review-workspace
May 24, 2026
Merged

Exonical merged 2 commits into
mainfrom
devin/1779658439-milestone-23a-review-workspace

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

Replaces the previous "one rule = one page" review flow with a single 3-pane workspace at /collections/{cid}/assets/{aid}/workspace. On a 300-rule STIG the user no longer round-trips through /rules/{ruleId} for every check.

Layout (mirrors the upstream stig-manager screenshot)

  • Left pane (~30%) — rule list for the selected STIG. Severity pill (CAT I/II/III), group id, title, current result + status pill. Filters: severity (CAT I/II/III), status (Saved / Submitted / Unreviewed), result (Fail / Pass / N/A), free-text search. All filters are client-side once rules are loaded.
  • Middle pane (~40%) — selected rule's detail (Vulnerability Discussion / Check / Fix / CCIs) via GET /stigs/rules/{ruleId} (only the rows you click are fetched, so opening a 434-rule STIG doesn't pull 434 detail bodies up front).
  • Right pane (~30%), stacked: Review Resources card (History tab populated from GET /collections/{cid}/review-history; Other Assets + Status Text tabs scaffolded — Other Assets is the M23b follow-up) above an inline Evaluation form (result, detail, comment, status) with prev/next chevrons and last-touched attribution footer.

STIG picker lives in the page header. Switching STIGs clears ?rule so the workspace lands on the new STIG's first rule.

Keyboard-first (only fires when no input/textarea is focused — text fields swallow the keys naturally):

  • j / ArrowDown, k / ArrowUp — next / prev rule (auto-scrolls into view)
  • f / p / n / u — set Result to fail / pass / notapplicable / notchecked
  • Ctrl+Enter — save
  • Ctrl+Shift+Enter — save + advance to the next unreviewed rule in the filtered list
  • / — focus the rule-list search box

URL state — ?stig=<benchmarkId>&rule=<ruleId>. Selecting a row pushes rule; switching STIGs replaces it. Reload / share link both work.

Entry point — the asset detail page gets a primary "Open Review Workspace" CTA next to Edit / Delete. The per-rule /rules/{ruleId} editor stays mounted (no breaking changes for direct links).

Out of scope for M23a (deliberately deferred so this PR stays focused):

  • M23b — multi-tab chrome (Home / Collection / Asset / STIG tabs at the very top of the upstream screenshot) and the Other Assets cross-asset view
  • M23c — Attachments tab on Review Resources (needs a new endpoint + store table)

Server changes — none. Every endpoint the workspace needs already shipped between M8 and M21c.

Review & Testing Checklist for Human

  • Open /collections/{cid}/assets/{aid}/workspace for an asset with at least one assigned STIG; verify the 3 panes render and the rule list is virtualisation-friendly (try a 400+ rule STIG)
  • Click a row → middle pane shows Vulnerability Discussion / Check / Fix / CCIs for that rule
  • Press j / k → selection moves; pressing / focuses the search box; pressing f / p / n / u updates the result without saving
  • Type a detail, press Ctrl+Enter → review row is saved (poll /collections/{cid}/reviews/{aid}); pressing Ctrl+Shift+Enter advances to the next unreviewed rule
  • Switch STIG in the picker → URL ?stig= updates and rule list reloads

Notes

The Playwright test covers the "workspace mounts + STIG picker + / keyboard focus" smoke path against the live compose stack. Saving + Ctrl+Enter is exercised by the existing per-rule editor test and by the usePutReview invalidation hook; we intentionally don't re-exercise the same mutation surface in the workspace e2e to keep the suite fast.

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

@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

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

M23a end-to-end test — 8/8 passed

Tested against the local compose stack (docker compose up -d → SPA at :54000, API at :54001, Keycloak at :8080). Signed in as admin, imported the bundled XCCDF fixture (TEST_OS_STIG / V2R3, 2 rules), created collection m23-workspace-test (id 17) and asset ws-asset-1 (id 6) mapped to it, then ran the adversarial test plan against /collections/17/assets/6/workspace.

No escalations — every assertion matched the plan's pass criteria. The keyboard-first claims hold up: j/k advance selection without touching the rule list, / focuses the filter, p flips the result dropdown to pass, and Ctrl+Enter persists the review without a page reload (URL unchanged, counts decrement unreviewed → 0, attribution footer renders Last touched by admin …).

  • Test 1 It should open the workspace via the asset detail CTA — passed
  • Test 2 It should render all 3 panes with the selected STIG — passed
  • Test 3 It should swap the middle pane when a different rule is selected — passed
  • Test 4 It should advance selection on j and k — passed
  • Test 5 It should focus the search box on / — passed
  • Test 6 It should save without a page reload via Ctrl+Enter — passed
  • Test 7 It should set result via the p quick-key — passed
  • Test 8 It should rehydrate state from the URL on reload — passed
Evidence — screenshots
1. Asset detail with Open Review Workspace CTA
2. 3-pane workspace at first render
3. Middle pane swapped to SV-100002
5. / focused search; filtered to 1 of 2 rules
6. After Ctrl+Enter: counts updated, row badge "pass · saved", attribution footer
8. After F5: state rehydrated from URL; saved review reloaded from server
Detailed per-test breakdown

Test 1 — CTA → workspace. Navigated to /collections/17/assets/6. The header rendered an "Open Review Workspace" button next to Edit / Delete. Click transitioned to /collections/17/assets/6/workspace?stig=TEST_OS_STIG&rule=SV-100001r1_rule with the workspace container visible.

Test 2 — 3-pane rendering. All three panes visible simultaneously. STIG selector shows TEST_OS_STIG (V2R3). Rule list has 2 rows (V-100001 CAT II, V-100002 CAT I), both UNREVIEWED. Header counts: 2 of 2 rules · 0 fail · 0 pass · 0 N/A · 2 unreviewed. Middle pane shows SV-100001r1_rule with Vulnerability Discussion, Check, Fix, CCIs (CCI-000048, CCI-000366). Right pane has History / Other Assets / Status Text tabs plus the inline Evaluation form.

Test 3 — row click swaps middle pane + URL. Clicked V-100002. URL gained ?rule=SV-100002r1_rule; middle pane re-rendered with the SELinux rule (Vuln Discussion + Check + Fix + CCI-000366).

Test 4 — j / k keyboard nav. Clicked outside any input. k moved URL ?rule= from SV-100002r1_rule to SV-100001r1_rule (middle pane swapped to strong passwords). j moved it back to SV-100002r1_rule (middle pane re-swapped to SELinux).

Test 5 — / focuses search. Pressed /. Search input received focus. Typed selinux → list narrowed 2 of 2 rules → 1 of 2 rules · 1 unreviewed.

Test 6 — Ctrl+Enter saves without reload. With V-100002 + Result=pass + Detail="tested in workspace via Ctrl+Enter", pressed Ctrl+Enter. URL stayed at /collections/17/assets/6/workspace?stig=TEST_OS_STIG&rule=SV-100002r1_rule — no path mutation. Header counts updated 0 pass · 2 unreviewed → 1 pass · 1 unreviewed. Row gained pass · saved badge. Attribution footer rendered: Last touched by admin · 5/24/2026, 9:59:59 PM · status saved.

Test 7 — p quick-key. With no input focused, pressed p. Result dropdown switched from notchecked to pass. (This precondition fed Test 6.)

Test 8 — F5 deep-link rehydration. Pressed F5 at ?stig=TEST_OS_STIG&rule=SV-100002r1_rule. URL params survived. Middle pane re-rendered SV-100002. Rule list row for V-100002 still highlighted with pass · saved badge. Evaluation form re-loaded Result=pass and Detail text from the server. Counts stayed at 1 pass · 1 unreviewed.

Out of scope (intentional): M23b multi-tab chrome, M23c Attachments tab, mobile-layout Esc shortcut.

Devin session: https://app.devin.ai/sessions/022810763c4643c0848ba894c1512b92

@Exonical
Exonical merged commit 713dab6 into main May 24, 2026
6 checks passed
@Exonical
Exonical deleted the devin/1779658439-milestone-23a-review-workspace branch May 24, 2026 22:12
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