Commit Graph
9 Commits
Author SHA1 Message Date
Claude 63a9ba2e4d feat(connectors): config models check the design's field formats (Atlassian, GitHub)
The Confluence, Jira and GitHub config models get field validators for
the design's format rules: a numeric page ID, no lastModified filter or
ORDER BY in a CQL query, no ORDER BY in a JQL query, and repository names
without an owner. The plan endpoint returns them as form_errors, with
the design's line as the message. The checks no longer test these
formats themselves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFMazQbuG8ui3jxBxm47sC
2026-10-17 03:12:09 +00:00
Claude d0866e3caf feat(connectors): Outlook checks follow the design's rows, copy and states
Outlook follows the design:
- Names and order: the 7 checks are the design's 6 rows. The mailbox
  count shares the "List mailboxes" row, which now validates the
  credential binding. Every row after it runs after it.
- Every failure gives a short line and a description that names the
  grant the app needs. Passing checks give what they found ("Up to {n}
  mailboxes", "Read mail in {mailbox}", "Read an event in {mailbox}"...).
  A mailbox the admin did not name stays unnamed.
- Find selected mailboxes and Find selected groups are partial finds:
  some missing is INCOMPLETE, none found is FAILED. The samples open the
  first selected mailbox that answers and walk the groups that resolve.
- Checks that passed without testing anything now say so: an empty
  mailbox and a calendar with no events are INCOMPLETE; the calendar check
  with calendars off and the find checks with nothing selected do not
  apply. Graph's empty pages are INCOMPLETE.
- The mailbox and group problem lists are typed, so the checks and the
  connector's validation read one list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFMazQbuG8ui3jxBxm47sC
2026-10-17 03:12:02 +00:00
Claude d98c097011 feat(connectors): OneDrive checks follow the design's rows, copy and states
OneDrive follows the design:
- Names and order: the 9 checks are the design's 8 rows. The drive count
  shares the "List users" row, which now validates the credential binding.
  Dependencies follow the design's run order; "Find a OneDrive" also runs
  after "Find selected users", so no user found stops it.
- Every failure gives a short line and a description that names the
  grant the app needs. Passing checks give what they found ("Up to {n}
  OneDrives", "Opened the OneDrive of {user}", "Read members of
  {group}"...).
- Find selected users is a partial find: some missing is INCOMPLETE and
  the drive checks walk the found users; none found is FAILED. An entry
  that is not an email and a list of blanks have their rows.
- Checks that passed without testing anything are now INCOMPLETE: an empty
  OneDrive for the permission read, and groups that all hide their
  members. A group that went away is INCOMPLETE, and a user list that does
  not end is INCOMPLETE, not an unexpected error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFMazQbuG8ui3jxBxm47sC
2026-10-17 03:12:02 +00:00
Claude f97f502523 feat(connectors): SharePoint checks follow the design's rows, copy and states
SharePoint follows the design:
- Names and order: the 15 checks are the design's 15 rows ("Find selected
  sites", "Sample documents", "Sign in with certificate", "Read nested
  groups"...). Dependencies follow the design's run order. Sample
  documents also runs after Find selected sites, and the two Entra group
  checks also after Sign in with certificate, because they read SharePoint
  REST.
- Every failure gives a short line and a description that names the
  site, library, folder or group and the grant the app needs.
- Find selected sites and Find selected libraries are partial finds: some
  missing is INCOMPLETE and the checks after them run on the found ones;
  none found is FAILED. More than 5 sites or libraries pass with a caveat.
- Passing checks give what they found ("Read a file in {library}",
  "Certificate valid until {date}", "Read members of {group}"...).
- Checks that passed without testing anything now say so: no file in
  scope is INCOMPLETE; no library, page, site group or Entra group in
  scope is SKIPPED; a file that went away passes with a caveat.
- An empty scope fails: every selected or listed site excluded fails the
  site check.
- A SharePoint REST 401 is "No token for the SharePoint host".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFMazQbuG8ui3jxBxm47sC
2026-10-17 03:12:02 +00:00
Claude bdcc56c746 feat(connectors): Microsoft checks share their sign-in row and Graph error rows
The SharePoint, OneDrive and Outlook checks share:
- One sign-in probe, "Sign in to Microsoft". Every check after it depends
  on it, so a bad secret is one failed row and the rest are "Not run".
- The design's sign-in lines. Descriptions name the connector's account
  fields for the account's sign-in method. An expired secret or
  certificate says so.
- The certificate's end date, read from the .pfx: "Certificate valid
  until ...", with a caveat in the last 30 days.
- "Signed in as {app name}", from the token's claims.
- Form runs fail an unreachable sign-in. OneDrive and Outlook sign-in
  validate the credential binding, as SharePoint does.
- Graph errors: a 429 is RateLimitedValidationError and stops the run, no
  answer is UnreachableValidationError, and a 401 and an unexpected answer
  have their rows. Callers pass the rows of a 403 and a 404.
- MicrosoftGraphError is a SourceApiError with the request and the
  response body, so Error Details show them.
- One MicrosoftTokenInfo for the three gateways' check_token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFMazQbuG8ui3jxBxm47sC
2026-10-17 03:12:02 +00:00
Claude 218d5ef709 feat(connectors): HubSpot checks follow the design's rows, copy and states
HubSpot follows the design:
- Names and order: the 9 checks are the design's 9 rows ("Sign in to
  HubSpot", "Read tickets", "List linked records", "Read record
  viewers"...). Dependencies follow the design's run order. "List linked
  records" and "Sample notes" run after the sign-in, not after the read
  checks: an empty type would stop them, but they can sample a record of
  another type. They leave out a denied type, which its read check
  reports.
- Every failure gives a short line and a description. A denial names the
  private app scope that HubSpot needs. Passing checks give what they
  found ("Signed in to account {id}", "Found {n} tickets", "{n} users
  found"...).
- Checks that passed without testing anything now say so. An empty type
  is SKIPPED. No record of any selected type FAILS the first read check.
  No record in scope skips the samples. A record without notes, and no
  listed user, are INCOMPLETE.

Fixes from the design's review:
- A rate limit past the retries is RateLimitedValidationError, which
  stops the run.
- Sign-in reports a missing token, an unreachable HubSpot and a timeout.
  On a form run, an unreachable HubSpot or a timeout fails sign-in.
- HubSpotApiError is a SourceApiError with the request and HubSpot's
  error body, so Error Details show them. The gateway raises
  HubSpotConnectionError for a failed or timed-out connection.
- Permission sync validation accepts a portal with no records.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFMazQbuG8ui3jxBxm47sC
2026-10-17 02:50:21 +00:00
Claude 5216a53d26 feat(connectors): Notion checks follow the design's rows, copy and states
Notion follows the design:
- Names and order: the 6 checks are the design's 6 rows ("Sign in to
  Notion", "Find shared pages", "Find root page"...). Sample page content
  runs after Find shared pages or Find root page; the other checks run
  after sign-in.
- Every failure gives a short line and a description. A denial names the
  integration capability the probe needs. Passing checks give what they
  found ("Signed in as {bot} in {workspace}", "Found shared page
  {title}", "Names readable for {n} users"...).
- Checks that passed without testing anything now say so. No page or no
  database to sample is SKIPPED. A database with no rows passes with a
  caveat.
- Find root page does not apply without a root page, also on a run
  without a config: indexing then reads every shared page.

Fixes from the design's review:
- A rate limit is RateLimitedValidationError, which stops the run.
- Sign-in reports a missing token, an unreachable server and a request
  timeout. On a form run, the last two fail sign-in.
- A 404 on a page or database that search returned is a denial.
- NotionApiError is a SourceApiError with the request and Notion's
  response body, so Error Details show them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFMazQbuG8ui3jxBxm47sC
2026-10-17 02:50:17 +00:00
Claude 98a13d477c feat(connectors): Linear checks follow the design's rows, copy and states
Linear follows the design:
- Names and order: the 9 checks are the design's 8 rows ("Sign in to
  Linear", "Find selected teams", "Sample issues", "Read account
  role"...). The two account-role checks share one row. Dependencies
  follow the design's run order.
- Every failure gives a short line and a description. A rejected
  credential and a guest name what the credential needs for its kind:
  a new API key, or a new OAuth connection. Passing checks give what
  they found ("Signed in as {email}", "Found all {n} teams", "Read
  issue {identifier}", "Listed all {n} workspace users"...).
- Find selected teams and Find selected projects are partial finds:
  some missing is INCOMPLETE and Sample issues runs on the found ones;
  none found is FAILED.
- An empty scope FAILS Sample issues. No team to test SKIPS List team
  members. No issue to read sharing of is INCOMPLETE.

Fixes from the design's review:
- A rate limit (HTTP 429 or the RATELIMITED code) is
  RateLimitedValidationError, which stops the run. The gateway does not
  retry it.
- Sign-in reports an unreachable Linear, a timeout, a missing
  credential, a refused OAuth renewal and a busy refresh lock. On a
  form run, an unreachable Linear fails sign-in.
- The gateway's API errors are SourceApiErrors with the request and
  Linear's body, so Error Details show them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFMazQbuG8ui3jxBxm47sC
2026-10-17 02:50:12 +00:00
Claude 5b10f2fbe8 feat(connectors): Slack checks follow the design's rows, copy and states
Slack follows the design:
- Names and rows: the 16 checks show as the design's 13 rows ("Sign in
  to Slack", "List Grid workspaces", "Find selected channels"...). The
  three public listings share one row, and the two private listings
  share one row. Dependencies follow the design's run order. Sign-in
  and the Grid workspace listing unlock the form.
- Every failure gives a short line and a description. A missing scope
  names the bot scope in one form. Passing checks give what they found
  ("Signed in as @{bot} in {workspace}", "2 workspaces in the org",
  "Read a thread in #{channel}"...).
- Find selected channels is a partial find: some not visible is
  INCOMPLETE, none visible is FAILED.
- Checks that passed without testing anything now say so. No sample to
  read is INCOMPLETE. A bot in no private channel SKIPS the private
  message and member checks. Find selected channels and Compile channel
  patterns do not apply when there is nothing to find or compile.

Fixes from the design's review:
- Slack's empty first page: the public message sample and the
  permission-sync listing follow the cursor across 2 pages of 100.
- A rate limit is RateLimitedValidationError, which stops the run.
- Sign-in reports "Cannot reach Slack", and fails on a form run. Each
  rejected-token error has its own line.
- slack_api_error_detail puts the request and Slack's response body in
  a SourceApiError, so Error Details show them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFMazQbuG8ui3jxBxm47sC
2026-10-17 02:37:16 +00:00