feat(credentials): saved credentials and credential-only block versions, with keyless AWS/Databricks OIDC
Merged
WA
1d ago+16517+16517+01234567890123456789012345678901234567890123456789-3926-3926-0123456789012345678901234567890123456789
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
_v2moves 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: trueandsunset: { 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.tspins the same errors and pass-through). serializer/saved-credentials.test.tschecks 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_objectinline 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;
withSavedCredentialswaps the secret fields for a credential picker in the same place (inheriting the secret's condition andrequired), points dependent fields and selectors at the credential, and leaves trigger fields alone. Its replaced fields come from the sameSAVED_CREDENTIAL_OAUTHtable the tools use. - Tools declare
oauth.credentialSuppliedParams(andcredentialParamsfor 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-registryenforces 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
subcan'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 toWORKLOAD_IDENTITY_PREVIOUS_KEY. - The issuer defaults to
<NEXT_PUBLIC_APP_URL>/oidc/workload; customer trust policies pin it, so setWORKLOAD_IDENTITY_ISSUERexplicitly 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_objectsigns 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. Fullcheck:auditsand 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-auditauthoring gate) - No new warnings introduced
- I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)