improvement(credentials): resolve agent fallback credentials once, Vanta 401 grace, true refusal codes, headless client-credential modes, and registry cleanups

Merged
WA
2d ago
+733-497

Summary

Follow-ups from the v0.9.55 credential audits.

Behavior fixes

  • Agent block: resolves its saved Vertex/Bedrock credential once per call instead of once per same-provider fallback attempt. A Bedrock fallback no longer repeats the STS AssumeRole, the authz check and the audit row. Cross-provider candidates never resolve it. Router and Evaluator already work this way.

  • Vanta: keeps a token minted within the last minute after a 401, the same rule the generic tool path uses. An endpoint that keeps returning 401 can't force a mint on every call, and Vanta limits mints. The 60s constant now lives in one place (token-request-resilience.ts).

  • Coordinated client credentials: a fresh refusal keeps its real code. A host the egress guard refuses (ServiceNow or Infisical, for example) shows host_not_allowed on the first call instead of provider_unavailable. Replays from the memo still use the stored code.

  • Google keyless refusals: each says what's wrong (wrong impersonated account, scope not covered, service not delegated, not a Google Cloud tool). TokenServiceAccountValidationError gains a message option and a userMessage, and generic token resolution holds no Google copy. Codes and statuses are unchanged.

  • Headless client-credentials modes: the provider catalog lists authMethod, clientId and clientSecret (required only for client_credentials) for ServiceNow, Infisical, Shopify, Linear and the Atlassian service account. The CLI checks required fields per auth method. These modes could only be created from the UI before. The change is additive: existing catalog fields and their required values are unchanged.

  • Amplitude and Railway: both use a dropdown, like the other region providers. A DNS failure is provider_unavailable, not a typo. A default-region Amplitude credential is named "Amplitude"; existing names are kept.

  • S3 saved-credential setup flag removed: the knowledge-connector-saved-credentials flag (and its KNOWLEDGE_CONNECTOR_SAVED_CREDENTIALS fallback) only gated setup during the mixed-version deploy window, and the release that reads these connectors is now live on the app and workers. The saved AWS credential option for S3 connectors is always offered. The credential-service, authorization and key-switch checks on create and access update are unchanged. Docs no longer say "where enabled".

  • Refused hosts in token responses: host_not_allowed now maps to a 400 telling the caller to reconnect with a public host, instead of a generic 401.

Cleanups (no behavior change)

  • Dead code: removed the unused tokenReplacesParams argument of tokenCredentialOAuth and its stale TSDoc, and reverted the saved-credential contract relaxation that only existed for it.
  • isSavedCredentialPicker: keyed on the saved-credential registry, so ordinary OAuth pickers (Greenhouse, Help Scout, Ramp) no longer match. credentialSuppliedParamsFor is identical across all 9,824 block/tool pairs.
  • Required-field rule: one rule (isTokenServiceAccountFieldRequired(field, authMethod?)) is used by the secret builder, the contract and the catalog.
  • Repeated definitions: one APOLLO_CREDENTIAL_TYPE_PARAM, one AwsSigningKeys type and helper, one exported TOKEN_AUTH_METHOD.
  • domainIsFixedChoice: domainIsVendorRegion is renamed to this. It covers fixed vendor choices such as regions and token types.

Type of Change

  • Bug fix
  • Improvement

Testing

  • New tests that fail on the old code:
    • Agent same-provider fallback resolves the credential once.
    • A fresh coordinated refusal keeps host_not_allowed.
    • Vanta keeps a young token and renews an aged one (integration).
    • The catalog's required set per auth method matches the server's for every client-credentials provider, Atlassian included.
    • CLI client-credentials create.
    • Amplitude/Railway DNS → provider_unavailable.
  • Unit runs: 6,640 tests pass across lib/credentials, lib/oauth, lib/internal (vanta, aws, llm), connectors, the knowledge connectors, tools/index, tools/shared, providers and the contract script. 23 sim-cli credential tests pass.
  • Integration: vanta-token.integration.ts (23) and coordinated-client-token.integration.ts (32) pass against a throwaway local Postgres.
  • Lint and audits:
    • bun run lint and check-block-registry.ts origin/staging pass.
    • The generated-artifact checks pass: check:openapi, check:cli-api, check:cli-docs, check:mcp-operations, check:tool-metadata and check:integration-catalog.
    • The code-rule checks pass: check:api-validation:strict, check:test-patterns, check:comment-hygiene, check:explicit-any, check:client-boundary, check:boundaries, check:utils, check:file-names, check:docs and check:tool-registry-boundary --check.
  • Type-check and the full suite run in CI.

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)