feat(connectors): two-step rows link a count check to its parent row
Description
Framework PR for the connector checks redesign (two-step rows), stacked on #16209. A count or list check is now linked to the check whose row it completes. The API tells the frontend how each two-step row shows.
The link
CheckStep(inmodels.py) makes a check the second step of a parent's row:step_of: the parent's check_id.running_summary: the row's line while the step runs, e.g. "Spaces visible, counting…".unfinished_caveat: the caveat when the step does not finish, e.g. "Could not count every space.".
CapabilityCheck(step=...)sets it. A step'srow_iddefaults to its parent's.CapabilityCheckResult.stepandDraftCheckState.stepcarry the link, so every result names its parent.
Registry validation. get_capability_checks calls validate_step_links on the source's checks (EE perm-sync checks included). It raises ValueError when:
- the parent is not a check of the same source, or is the step itself;
- the parent is a step itself (no chains);
- the step is not on the parent's row, or does not depend on the parent;
- a parent has two steps.
How a two-step row shows (two_step.py:two_step_row)
- Until the parent passed, the parent decides the row.
- After the parent passed:
- Step pending or running: In progress, with the running line ("counting…").
- Step passed, failed, could not decide (
inconclusive) or partial: the step's result fills the row. - Step did not finish (timeout, unreachable, unexpected, rate limit, or skipped or stopped by the admin): the parent's Successful row, plus the caveat.
- Step not applicable, or held by a gate of the run (findings off, nothing in scope): the parent's row as it is.
- A step whose parent does not apply shows alone.
API for the frontend (C7). The result lists stay as they are. Three responses get two_step_rows, one entry per two-step row:
DraftCheckRunSnapshot(create form and pair dry run), as a computed field.CapabilityReportSnapshot(stored report) andCheckRunSnapshot(run history).
Each entry has row_id, parent_check_id, step_check_id, shown_check_id, counting, summary and caveat. The row takes the state, description, Error Details and findings of shown_check_id. Two exceptions: with counting the row is In progress, and caveat adds a ⓘ caveat to the parent's Successful row. summary is always the row's line. The rules live in the backend only, so the three surfaces show the same row. Variants on the same row (for example Slack's permission-sync listing) stay ordinary row_id merges.
Links (the design's 7 two-step rows)
| Source | Row | Step → parent |
|---|---|---|
| Confluence | List spaces | confluence_space_listing → confluence_spaces_visible |
| Jira | List groups | jira_group_listing_complete → jira_group_listing |
| Google Drive | List Workspace users | google_drive_user_count → google_drive_workspace_users |
| Google Drive | List shared drives | google_drive_shared_drive_listing → google_drive_shared_drives |
| Slack | List public channels | slack_readable_channel_listing → slack_public_channel_listing |
| OneDrive | List users | onedrive_drive_count → onedrive_users |
| Outlook | List mailboxes | outlook_mailbox_count → outlook_mailbox_listing |
The running lines and caveats are the design's text.
Dependency changes. A step must run after its parent. Three steps ran after sign-in only, and now run after the parent:
- Slack
slack_readable_channel_listing→slack_public_channel_listing. - OneDrive
onedrive_drive_count→onedrive_users. - Outlook
outlook_mailbox_count→outlook_mailbox_listing.
When the parent fails, the step is "Not run", and the row shows the parent's failure.
Different from the design
- Jira's step is a validation check (optional), not a discovery check. "Only {returned} of {total} groups listed" is Failed and "Jira did not report a group total" is Incomplete, as the design says. A timeout gives the parent's row with "Could not count every group.".
- The design's Skipped outcomes "No spaces to list" (Confluence) and "No shared drives visible" (Google Drive) are not new rows here. A step that finds nothing in scope leaves the parent's row as it is.
No frontend changes.
How Has This Been Tested?
- New unit tests (
test_two_step_rows.py):- registry validation: a sound link, and each unsound case (missing parent, chain, other row, no dependency, two steps, own parent);
- the row rules: the parent until it passed, counting, a finished step, an unfinished step with the caveat, a step that was not due, and a step without its parent;
- each connector's links, for every registered source;
- a run whose step fails with an unexpected error, through
two_step_rows_of_results; - a draft snapshot that shows "counting…" and serializes
two_step_rows.
- Connector, server and EE unit tests: 5871 passed, 25 skipped, 1 failed. The failure (
test_browser_lifecycle.py) needs DNS, which the sandbox blocks. Pre-commit is clean.
Additional Options
- [Optional] Please cherry-pick this PR to the latest release version.
- [Optional] Override Linear Check
Generated by Claude Code
Summary by cubic
A count or list check can now be the second step of a parent's row via CheckStep (step_of, the running line, and the caveat when the step does not finish), and the step's outcome fills the parent's row once the parent passes.
- The row display rules live in
two_step.py(with theTwoStepEntry/TwoStepRowmodels inmodels.py), so the draft form, stored report, and run history all return the sametwo_step_rowsview. get_capability_checksvalidates the links and raisesValueErroron unsound ones: missing parent, chains, wrong row, missing dependency, or two steps per parent.- Wires the design's seven links (Confluence, Jira, Google Drive ×2, Slack, OneDrive, Outlook); three steps now depend on their parent instead of sign-in only.
- A failed parent leaves the step "Not run" and shows the parent's failure; an unfinished step (timeout, rate limit, stop, skip) shows the parent's Successful row with the caveat, and a step that does not apply leaves the parent's row unchanged.
- No frontend changes. New unit tests cover registry validation, the row rules, each connector's links, and a run whose step fails unexpectedly.
Summary by CodeRabbit
- New Features
- Added two-step capability-check reporting with parent and child progress, results, summaries, and incomplete-status caveats.
- Exposed consistent two-step rows in live runs, saved reports, snapshots, and run history.
- Added progress details for relevant Confluence, Google Drive, Jira, OneDrive, Outlook, and Slack checks.
- Bug Fixes
- Improved validation of capability-check relationships and dependencies, preventing invalid or ambiguous step configurations.