feat(connectors): two-step rows link a count check to its parent row

Merged
EV
19h ago
+721-5

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 (in models.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's row_id defaults to its parent's.
  • CapabilityCheckResult.step and DraftCheckState.step carry 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) and CheckRunSnapshot (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)

SourceRowStep → parent
ConfluenceList spacesconfluence_space_listing → confluence_spaces_visible
JiraList groupsjira_group_listing_complete → jira_group_listing
Google DriveList Workspace usersgoogle_drive_user_count → google_drive_workspace_users
Google DriveList shared drivesgoogle_drive_shared_drive_listing → google_drive_shared_drives
SlackList public channelsslack_readable_channel_listing → slack_public_channel_listing
OneDriveList usersonedrive_drive_count → onedrive_users
OutlookList mailboxesoutlook_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 the TwoStepEntry/TwoStepRow models in models.py), so the draft form, stored report, and run history all return the same two_step_rows view.
  • get_capability_checks validates the links and raises ValueError on 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.