Skip to content

fix(integrations): expose stored service-account catalog connections - #7624

Open
BillLeoutsakosvl346 wants to merge 8 commits into
stagingfrom
fix/platform-service-account-catalog
Open

fix(integrations): expose stored service-account catalog connections#7624
BillLeoutsakosvl346 wants to merge 8 commits into
stagingfrom
fix/platform-service-account-catalog

Conversation

@BillLeoutsakosvl346

Copy link
Copy Markdown
Contributor

Summary

  • Add a catalog service-account relationship independent of the existing authentication marker, derived from block credential fields and the canonical service registry.
  • Expose NetSuite, Snowflake, Harmonic, and Claude Platform connections through deployment availability, catalog setup links, and existing credential-discovery/creation guards.
  • Preserve OAuth configuration, credential provider IDs, integration allowlists, workspace and organization restrictions, and preview visibility. No authentication-enum redesign or product changes.

Verification

  • 121 focused integration, provider-catalog, service-account application, organization-credential, and connection-route tests passed.
  • 83 documentation-generator tests passed.
  • App and deployment-config type-checks passed.
  • API validation, integration-catalog check, deployment-config check, full generated-docs check, and git diff whitespace check passed.
  • Biome passed on changed TypeScript files; three existing scanner-fixture warnings remain unchanged.

Generated changes are limited to four catalog relationships and their four provider projections. No credentials, real customer data, or live provider requests are included.

@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs Ready Ready Preview Sep 9, 2026 4:58am UTC

Request Review

@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the previously reported connection-routing issues are resolved and no actionable new failure remains.

Summary

  • Projects NetSuite, Snowflake, Harmonic, and Claude Platform through generated deployment availability and provider metadata.
  • Updates integration detail pages, search results, suggested actions, and special tags to expose the appropriate service-account connection flow.
  • Preserves deployment availability, integration allowlists, workspace and organization restrictions, preview visibility, and OAuth configuration behavior.
  • Adds focused tests for catalog generation, availability, credential visibility, connection routing, and integration UI behavior.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    B[Block credential field] --> G[Catalog generator]
    R[Canonical service registry] --> G
    G --> C[Integration catalog]
    C --> D[Deployment availability]
    C --> V[Credential visibility]
    C --> U[Workspace integration surfaces]
    D --> U
    V --> U
    U --> M[Stored service-account modal]
Loading

waleedlatif1 and others added 2 commits September 8, 2026 20:04
`ServiceAccountIntegrationMatch` named a service-account integration but
left its icon to a second `resolveOAuthServiceForSlug` lookup, which is
null for a stored-credential integration whose catalog entry is not
`oauth`. The chat's inline connect control read the icon from that lookup,
so `useServiceAccountConnectTarget` saw an undefined icon and rendered
nothing for exactly the four integrations this branch exposes.

Resolving the icon once, where the match is built, removes the second
lookup and the class of bug with it.

Also:
- Offer the service-account connect control while deployment availability
  is still unknown, matching `oauthAvailable` directly above it. A
  pessimistic default rendered a disabled "Unavailable" verdict for the
  whole permission-config load on an integration whose only path is a
  stored service account.
- Drop the `listCredentialProviderCatalog` case that mocked
  `createIntegrationCredentialVisibility` wholesale: it asserted catalog
  wiring that did not change and passed without the fix. The projection
  and both `requireAvailableServiceAccountCredentialProvider` branches are
  already covered in this file.
- Move the new visibility case below the `beforeEach` that configures it,
  and set the block mock through `mockImplementation` like its neighbours
  instead of relying on hook ordering to undo a `mockReturnValue`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9K4apTYamQFpRYT3tcjVQ
@waleedlatif1

Copy link
Copy Markdown
Collaborator

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

Every new case in this branch was parameterized on the service id, which
made Claude Platform quietly absent from all of them: its block type is
`managed_agent`, so a serviceId-keyed lookup finds no availability entry
and no allowlist key. Pair each case with its block type and add the
fourth integration, so the authorization tightening and the availability
projection are pinned for all four rather than three.

Also:
- Guard the icon the previous commit added to `ServiceAccountIntegrationMatch`.
  It had no test, and its absence renders nothing at all rather than a
  broken chip, so the gap was invisible in exactly the way that produced
  the bug.
- Assert `isDeploymentGatedIntegrationType` for the four, alongside the
  unconditional `ready` that keeps the gate from hiding them.
- Narrow the connect-control's unknown-availability default to the case it
  was written for. Relaxing it for every integration widened the header
  control from a chip to a dropdown and back on every OAuth integration
  that also offers a service account, as the permission config landed.
- Read `atlassianProduct` from the service-account match that mounts the
  modal rather than the OAuth match, which is null for a stored-credential
  integration. Verified behavior-identical across all 39 integrations that
  can mount it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9K4apTYamQFpRYT3tcjVQ
@waleedlatif1

Copy link
Copy Markdown
Collaborator

@greptile

…oint

Three surfaces decided whether to offer a connect flow by asking whether
the integration was `authType: 'oauth'`, which is false for one
authenticated by a stored service account. Each failed differently.

Suggested actions was the worst of them, and the failure predates this
branch: `defineServices` enumerates every OAuth provider, including the
four whose `authType` is `service_account`, so "Integrate with Snowflake"
was already offered on the home screen — and clicking it resolved no OAuth
target and fell off the end of the handler. Snowflake, NetSuite, Harmonic
and GitHub all had dead rows. They now hand off to the integration's detail
page, carrying the service-account deep link when that is the flow on
offer, so the modal still opens in one click.

Sidebar search needed both halves fixed to work: the `authType` gate
dropped the deep link, and the mode callback matched on the `limited` state
an OAuth integration reaches when only its service account is available.
An integration whose *only* credential is a service account is plain
`ready`, so it fell through to `null`. Gate on having a credential service
and test what is actually connectable instead.

The detail page reserved "Unavailable" for a verdict it had no business
making: an API-key integration still runs on the user's own key, so it now
keeps the catalog's ordinary call to action, which also collapses a
duplicated fallback branch. The catalog card is deliberately left alone —
its `authType === 'oauth'` guard is what stops it from calling a usable
block unavailable, and it was the detail page that diverged.

Also fail open on a *failed* availability fetch rather than a pending one,
per review: while the config is in flight the answer is imminent and an
optimistic default would flip the header control's shape, but once both
queries settle with nothing the request failed, and withholding the control
strands a user who has a valid stored account behind a fetch they cannot
retry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9K4apTYamQFpRYT3tcjVQ
@waleedlatif1

Copy link
Copy Markdown
Collaborator

@greptile

Comment thread apps/sim/app/workspace/[workspaceId]/w/components/sidebar/sidebar.tsx Outdated
…known

The search deep link fell back to OAuth whenever deployment availability
could not be read — while it loads, and after a failed fetch. That was safe
while only OAuth integrations reached the fallback, but this branch also
routes stored-service-account ones through it, and they have no OAuth flow
for the detail page to open: the link resolved to nothing and cost the
search result the one click it exists to save.

Carry the catalog's own answer instead. `getConnectMode` now receives it and
returns it verbatim when it cannot do better, which also keeps `null`
meaning what it meant — the deployment offers no connect flow — rather than
doubling as "unknown".

Covers the builder, which had no tests: the per-credential-kind deep link,
the resolver contract, and the allowlist filter.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9K4apTYamQFpRYT3tcjVQ
@waleedlatif1

Copy link
Copy Markdown
Collaborator

@greptile

The page this branch exists to fix had no tests, and its header action is
the branch's whole user-visible surface: five integration classes crossed
with a loading, loaded and failed availability answer, expressed as nested
ternaries.

Covers the decision for both classes that matter — one whose only credential
is a stored service account, and one that also offers OAuth — across all
three availability states, plus the two "Unavailable" cases in either
direction.

The control-kind tag in the helper is load-bearing. A `ChipDropdown` trigger
renders the same "Add to Sim" placeholder as the plain chip, so an assertion
on label text alone cannot tell one connect option from two, and the case
guarding the narrowed unknown-availability default passed against the
over-broad version it was written to reject. Tagging on `aria-haspopup`
makes it fail. Each of the six cases was checked against a mutation of the
behavior it describes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9K4apTYamQFpRYT3tcjVQ
@waleedlatif1

Copy link
Copy Markdown
Collaborator

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator

@greptile

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.

2 participants