Skip to content

feat(credentials): saved credentials and credential-only block versions, with keyless AWS/Databricks OIDC - #9763

Open
waleedlatif1 wants to merge 22 commits into
stagingfrom
feat/oidc-credentials
Open

waleedlatif1 wants to merge 22 commits into
stagingfrom
feat/oidc-credentials

Conversation

@waleedlatif1

@waleedlatif1 waleedlatif1 commented Nov 7, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • 79 blocks that took secrets typed into the block now have a credential-only version that signs in with a saved, shareable credential instead: all 19 AWS blocks, Databricks, and 59 single-token services (Tavily, Mem0, Zep, Discord, Cloudflare, Intercom, …). A block that already had a _v2 moves to _v3.
  • AWS and Databricks credentials can be keyless: Sim runs its own OIDC issuer (/oidc/workload), so a credential assumes a customer's AWS role (AssumeRoleWithWebIdentity) or federates into a Databricks service principal (RFC 8693) with no stored secret. Key and secret modes remain (AWS access keys, access keys that assume a role; Databricks PAT, service principal secret).
  • Each token service gets a credential type with a cheap vendor check on save (tokenCheckValidator), a policy that maps the credential onto the tools' inline params, and a connect form.

Existing workflows don't change

  • Legacy blocks are identical to staging apart from hideFromToolbar: true and sunset: { status: 'legacy', replacedBy }. Placed blocks keep running and editing as before, with an upgrade badge. Nothing is migrated or rewritten.
  • Where a legacy params builder validated or trimmed the secret, it was extracted into a function the legacy block still calls with its original checks (blocks/legacy-builders.test.ts pins the same errors and pass-through).
  • serializer/saved-credentials.test.ts checks every legacy block still serializes and requires its inline secret, and every successor serializes per operation with only a credential.
  • Without an authorized credential, AWS operations receive the identical request; S3 get_object inline signatures are byte-identical to staging (golden test).
  • Without WORKLOAD_IDENTITY_SIGNING_KEY (or with a malformed one), the issuer returns 404 and the dialogs don't offer keyless.

How successors are built

  • A successor spreads its legacy block; withSavedCredential swaps the secret fields for a credential picker in the same place (inheriting the secret's condition and required), points dependent fields and selectors at the credential, and leaves trigger fields alone. Its replaced fields come from the same SAVED_CREDENTIAL_OAUTH table the tools use.
  • Tools declare oauth.credentialSuppliedParams (and credentialParams for token credentials). The executor overwrites mapped params only after authorizing the credential and fails closed; serializer validation, agent tool-input fields, and v2 execute skip credential-supplied params by the one shared rule.
  • check-block-registry enforces the contract for every successor: provider and kind match the picker, every supplied param is filled, and every param that steers the request host is filled by the credential (probed against each tool's real URL builder), so a shared credential can't be sent to a host the caller picks.
  • The docs generator resolves multi-level spreads and same-file params builders; other blocks' docs are unchanged.

Security

  • Keyless subjects are per credential and HMAC-signed for the preparing user and workspace. Saving a keyless AWS role is refused unless the role denies a random subject, so a trust policy that skips sub can't be assumed from another workspace.
  • The credential reaches AWS operations through trusted operation context, never tool input, and is re-bound to the run's workspace. Tokens last 5 minutes, carry a per-relying-party audience, and never reach outputs or the model.
  • Validators refuse redirects and cap response bodies; a 403 counts as a scoped-but-valid key only where the vendor uses it that way, and never when the body names a bad key.

Deploy notes

  • Set WORKLOAD_IDENTITY_SIGNING_KEY (RSA PKCS#8 PEM) per environment, including Trigger workers. Rotate by moving the old key to WORKLOAD_IDENTITY_PREVIOUS_KEY.
  • The issuer defaults to <NEXT_PUBLIC_APP_URL>/oidc/workload; customer trust policies pin it, so set WORKLOAD_IDENTITY_ISSUER explicitly before anyone relies on it.

Known limits / follow-ups

  • Keyless modes are workspace-only; organization credentials offer key/secret modes.
  • AWS role assumption and Databricks token exchange run per tool call (no caching); very large parallel loops could approach STS limits.
  • Reconnecting a key-based AWS/Databricks credential opens on the keyless mode by default; the server rejects a keyless save with no stored subject.
  • s3_get_object signs its own request, so the executor resolves its session directly; every other AWS tool runs through its operation family.

Type of Change

  • New feature

Testing

  • New and updated suites: workload-identity issuer and subject, AWS and Databricks credential setup (subject pinning, host allowlist), AWS executor signing and refusals, token validators (incl. Brex and Flint), host-steering probe, serializer per-operation coverage for every legacy and successor block, legacy params builders, withSavedCredential, S3 signing goldens. Each new guard was reverted to watch its tests go red.
  • Targeted Vitest runs over the touched areas (1,724 tests), bun run lint, type-check (pre-push), check-block-registry.ts origin/staging, and the docs, catalog, manifest, successor, tool-metadata, deployment-config, React Query, boundary, client-boundary, api-validation:strict, test-pattern, comment, utils and unused-export audits. Full check:audits and the full suite run in CI.
  • Sent fake keys to every token-check endpoint to confirm each rejects a bad key; S3 saved access keys checked end to end against a real bucket.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Nov 10, 2026 7:03am UTC

Request Review

@waleedlatif1
waleedlatif1 force-pushed the feat/oidc-credentials branch from 17321d8 to ce54794 Compare November 9, 2026 23:39
@waleedlatif1 waleedlatif1 changed the title feat(credentials): saved AWS and Databricks credentials with keyless OIDC feat(credentials): saved AWS/Databricks credentials with keyless OIDC, via credential-only block versions Nov 10, 2026
@waleedlatif1 waleedlatif1 changed the title feat(credentials): saved AWS/Databricks credentials with keyless OIDC, via credential-only block versions feat(credentials): saved credentials and credential-only block versions, with keyless AWS/Databricks OIDC Nov 10, 2026
@waleedlatif1
waleedlatif1 marked this pull request as ready for review November 10, 2026 06:35

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2163 files

Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.

Turn on auto-fix | Re-trigger cubic

@greptile-apps

greptile-apps Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[High impact] This update appears safe to merge; no new actionable issues were found.

Summary

The PR adds saved credentials, credential-only block versions, and keyless AWS and Databricks connections.

  • New integration blocks use saved credentials for service sign-in.
  • AWS and Databricks credentials can sign in without stored provider secrets.
  • The executor fills credential-backed tool fields after authorizing the selected credential.

Reviews (4) · Last reviewed commit: "fix(credentials): never cache the issuer..." · Reviewed by Greptile

…OIDC

Adds an optional saved credential to every AWS block and the Databricks
block, alongside the existing inline key fields, plus Sim's own
workload-identity (OIDC) issuer so a credential can assume a customer's
AWS role or federate into a Databricks service principal without any
stored secret.

Existing workflows are unchanged: the inline fields stay, show, and
validate exactly as before until someone selects a saved credential.

- Issuer at /oidc/workload (discovery + JWKS), signing key from
  WORKLOAD_IDENTITY_SIGNING_KEY; 404 and keyless option off when unset
- Credential-scoped subjects, HMAC-bound to the preparing user and
  workspace, so a member cannot reuse another credential's subject
- aws-service-account: access keys, keys + AssumeRole (external ID), or
  keyless AssumeRoleWithWebIdentity; resolved server-side per call
- databricks-service-account: PAT, service principal M2M secret, or
  keyless RFC 8693 token federation
- AWS families accept the executor-authorized credential through trusted
  operation context; clients add the session token only for that pair
- S3 get_object signs x-amz-security-token for temporary credentials;
  inline signatures are byte-identical to before
- Tool credential binding honors optional (required: false) policies
…ntials

- Models can no longer inject a credential selector (or the token, session
  token, or host derived from one) into a hybrid tool call, which would
  have swapped an agent tool's inline keys for another workspace credential
- Databricks connections own the workspace host (authoritative `domain`)
- Drop the advanced credential-ID input: with a single picker, "is a
  credential selected" can no longer disagree with the active canonical mode
- OIDC subject proofs are bound to their provider
- Databricks token and identity fetches refuse redirects
- Correct the AWS module doc on presigned URLs carrying a session token
…ial plumbing

- Reconnecting a keyless AWS role or Databricks principal keeps its trusted
  subject by default instead of issuing a new one that breaks the
  customer's trust policy
- The connect dialogs offer the keyless mode only where the deployment can
  sign tokens; the prepare endpoint reports availability instead of failing
- Register AWS (all 19 block types) and Databricks as stored-credential
  integrations, so org settings, the v2 credentials API, and Copilot can
  create and see them
- Optional STS region for GovCloud and China access keys
- One subject binder and config parser shared by both providers (neutral
  copy), one modal core for submit/errors/trust display
- Generic `authorizedServiceAccountCredential` operation context instead of
  an AWS-specific field; Databricks resolver checks credential type and
  honors cancellation
- Model-blocked params derive from each tool's authoritative params
…nline keys

Existing AWS and Databricks blocks are left exactly as on staging, only
marked legacy and hidden from the toolbar; placed instances keep running
and show an upgrade badge. Each gets a credential-only successor
(s3_v2 ... databricks_v2, textract_v3) built by spreading the legacy block
and swapping its secret fields for a required saved-credential picker.

- withSavedCredential derives the successor's fields, inputs, and params
  builder; S3 and Textract split their builders so legacy key checks stay
- tools declare credentialSuppliedParams so serializer validation and the
  canonical-id check stop asking credential-only blocks for inline keys
- CloudWatch gets saved-credential log group/stream selectors that sign
  inside the credential's STS session
- docs generator resolves multi-level spreads and same-file param builders
- the AWS/Databricks providers are derived from the catalog again, so the
  hand-maintained token-credential mapping is reverted
…l, not inline keys

The generator omits a tool's credential-supplied params on pages for
blocks that sign in with a saved credential, as it already omits
accessToken. Intros now point at the AWS/Databricks credential guides.
Regenerates OpenAPI, CLI API, and CLI docs for the new selector keys.
A webhook trigger can register with a field named like the block's
secret (PagerDuty, Fathom, EmailBison, GitLab). withSavedCredential now
leaves trigger-mode fields, and their dependencies, exactly as they are.
…locks

Wave 0 of moving inline-secret blocks onto saved credentials.

- tokenCredentialOAuth(provider, credentialParams) declares which tool
  params a saved token fills; credentialSuppliedParams is derived from it
- the executor fills those params after authorization, overriding any
  caller value, and fails closed when the credential lacks a field
- hosted keys are never injected when a saved credential supplies the key
- v2 tool execute no longer demands credential-supplied params when a
  credentialId is passed (fixes AWS/Databricks direct calls)
- withSavedCredential accepts an optional/conditional requirement
- check-block-registry verifies every credential-only successor's tools
  authorize the picker's provider and actually fill what they declare
- redact secretAccessKey/awsSecretAccessKey keys in logs
- serializer contract test covers every operation of each successor
Reference migration for wave 1. A generic tokenCheckValidator verifies a
token with one documented authenticated request (no redirects); Tavily
uses GET /usage. Legacy tavily is unchanged apart from its legacy marker.
- agent tool-input no longer synthesizes inline secret fields a block's
  saved-credential picker supplies; one shared rule
  (credentialSuppliedParamsFor) now drives tool-input, serializer
  validation, and the canonical-id check
- the picker inherits the replaced secret's condition and requirement, so
  sts_v2's unsigned calls (web identity, SAML) need no credential
- withSavedCredential replaces both halves of a canonical secret pair and
  refuses options that would silently do nothing
- Databricks fills its inline apiKey/host through credentialParams, so its
  tools are byte-identical to staging apart from the policy line
- AWS operation families record their tool ids; a test and an executor
  guard ensure every AWS-credential tool resolves the credential
- the registry contract check fails on unpinned host params, optional
  credentials over required params, malformed pickers, and kind mismatch
- hosted-key admission (v2) and pre-resolution validation honor a selected
  saved credential; credential errors name fields in plain words
…en blocks

Each block keeps its legacy definition (only hideFromToolbar + sunset) and
gains a credential-only <type>_v2. Every service gets a token-paste
provider with a one-request validator against a documented, read-only,
credit-free endpoint, and its tools fill the inline key from the saved
credential via tokenCredentialOAuth.

Blocks: affinity, agentmail, agentphone, ahrefs, apify, apollo, brex,
brightdata, browser_use, buffer, circleback, clerk, cloudflare,
crunchbase, daytona, elevenlabs, enrich, gamma, hex, huggingface,
incidentio, instantly, langsmith, launchdarkly, linq, loops, luma,
mailchimp, otter, persona, pinecone, profound, quartr, rb2b, rippling,
rocketlane, semrush, sendgrid, similarweb, sixtyfour, smartlead,
sportmonks, square, tailscale, trigger_dev, uptimerobot, youcom, youtube.

The registry contract check now probes each request tool's real URL
builder to find params that steer the host, and requires the saved
credential to fill them.
- Pinecone and Semrush leave wave 1: Pinecone's per-call indexHost would
  let a shared key reach any host, and Semrush has no credit-free check
  that rejects a wrong key. Both are back to staging exactly.
- tokenCheckValidator: forbiddenMeansScoped accepts a valid key that lacks
  the check endpoint's scope (Apollo, Brex, Bright Data, Apify, Rippling,
  Persona); acceptsBody proves keys whose rejection arrives in a 200 body
  (Buffer GraphQL)
- the host-steering probe lives in scripts/saved-credential-contract.ts:
  typed placeholders for required params only, id/host shapes, bare and
  scheme probes, and a broad destination-name fallback where the URL
  cannot be built; covered by a fixture test
- S3 refuses a bucket or region that would move the signed request's host
- spread-inheriting docs keep their base block's outputs (restores the
  Smartlead, Trigger.dev, and Instantly output tables)
- incident.io's credential is optional for alert events, which use their
  own alert source token
- withSavedCredential refuses replaced secrets that show or require
  differently; copy, intro, and hint fixes from the audit
- host probe also defeats unparsed suffix checks and finds hosts behind
  optional switches, probing every placeholder shape; broader destination
  names where a URL cannot be built; the contract check fails when a
  successor's tool is missing from the executable registry
- the optional-credential rule evaluates a conditional picker per
  operation; incident.io hides its picker on alert events instead
- withSavedCredential takes an explicit picker condition and refuses one
  that depends on a replaced secret at any nesting depth
- a scoped 403 counts only when it is the vendor's JSON response, never a
  firewall or CDN page
- S3 names a bad bucket or region in its error
- pinecone/semrush catalog dates restored to staging
Their legacy params builders throw without an inline secret, so each is
extracted into a module function with a requireKey flag: the legacy block
keeps identical validation and messages, the credential-only v2 skips only
the key check. discord_v2 hides its picker for webhook posts, which never
use the bot token. BlockToolParams is now a shared type for extracted
builders (S3, Textract, Discord).
Blocks that already had a v2 get a credential-only v3 that spreads it:
cursor, dub, extend, fireflies, intercom, pulse, quiver, reducto. The v2
becomes legacy and every older version's replacedBy points at v3. Extend,
Pulse, and Reducto's v2 builders trimmed the key inline, so each is
extracted into a builder that takes the key as an argument; the legacy v2
passes the trimmed key exactly as before.

Flint gets flint_v2 with a dedicated validator: its API has no read
endpoint, so an unknown task id answering 404 proves the key.

tokenCheckValidator gains rejectsKey for vendors that answer a bad key
with a server error (Fireflies returns 500 auth_failed), so the user is
told the key is wrong rather than the vendor down.
- token checks for the 59 new providers live in one module
  (validators/token-checks.ts) and their tool policies in
  tools/shared/saved-credentials.ts, so the tool-registry boundary stays
  within its baselines instead of adding ~60 modules to every graph
- the host-steering probe builds URLs through the shared transport
  (new prepareToolRequestUrl) and also flags a host validated against a
  vendor allowlist when two accepted values reach different tenants
- the AWS routing test reads typed metadata through getToolMetadata
- Flint accepts only its documented JSON 'Task not found' 404; Intercom no
  longer treats a 403 (suspended workspace, plan without API) as valid;
  Fireflies keeps its error text in logs when a 5xx isn't auth_failed
- Cursor help text, placeholder wording, Pulse intro, sorted secret fields
- Refuse a keyless AWS role whose trust policy doesn't pin the credential's
  subject, so no other workspace can assume it
- Treat a malformed workload-identity signing key as not configured
- Brex: reject an unknown token's scope-style 403; the token-check factory
  now runs rejectsKey before accepting a scoped 403
- Flint: probe with a docs-shaped task id and a size-capped body read
- Drop the versioned BlockMeta entries that doubled templates; alias bare
  block types in the app icon map so template icon clusters resolve
- Widen the host-probe fallback names and rotate digits in alternates
- Copy: picker placeholder casing, Databricks v2 description, Pulse and
  Tailscale skills, AWS/Persona/Rippling intros, AWS credential docs
- Tests: AWS executor signing, AWS/Databricks credential setup, legacy
  params builders, serializer coverage for blocks without operations
- withSavedCredential reads the replaced fields from SAVED_CREDENTIAL_OAUTH,
  so blocks and tools share one table instead of two hand-kept copies
- Reuse isTriggerModeSubBlock, getDependsOnFields, and a shared
  isSavedCredentialPicker; build the replacedBy map once in the registry check
- newWorkloadIdentitySubject owns the subject format; the AWS trust-pin probe
  runs alongside verification
- The issuer parses a bad signing key once instead of per request
- Token checks share the accepted result and the capped JSON reader
- Keyless setup query gets its own key root, so broad credential
  invalidations can't refetch an open setup and mint a new subject
- Named staleTime constant for the setup query
- Correct stale comments (relying parties, Databricks param names)
- Tighten tests: assert the refusal reason, make the BYOK guard reachable,
  drop a duplicate and a test that could not fail
- A scoped 403 whose body can't be read is provider_unavailable, never accepted
- Provider error snippets read through the bounded reader
- Props interfaces for KeylessTrustFields and useWorkloadIdentitySetup; TSDoc on issuer responses
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Nov 10, 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.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 2165 files

Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.

Turn on auto-fix | Re-trigger cubic

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Nov 10, 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.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2165 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.

Turn on auto-fix | Re-trigger cubic

This branch was previously deployed

1 inactive deployment
Preview — 909acd47 Deployed Nov 10, 2026 by vercel[bot]
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