Skip to content

Snowflake: add connectionName config field and session-token auth in SnowflakeClient#6

Draft
costrouc wants to merge 2 commits into
mainfrom
snowflake-connection-support
Draft

Snowflake: add connectionName config field and session-token auth in SnowflakeClient#6
costrouc wants to merge 2 commits into
mainfrom
snowflake-connection-support

Conversation

@costrouc

@costrouc costrouc commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Two small, backward-compatible changes that let Posit Assistant drive Snowflake
Cortex from a user's connections.toml (the file the Python connector / Snowflake
CLI use):

  1. ai-config — a non-secret connectionName field on the snowflake
    connection sub-section, so a consumer can record which named connection to
    use.
  2. ai-provider-bridgeSnowflakeClient support for the session-token
    auth scheme, needed for external-browser (SSO) sign-in.

All the discovery/parsing, token acquisition, and UI live in the consumer
(posit-dev/assistant, companion PR); this PR is only the enabling ai-lib
primitives.

Changes

ai-config

  • snowflakeConfigSchema gains an optional connectionName: z.string().
  • ResolvedConnection.snowflake gains connectionName?: string.
  • Regenerated providers.schema.json.

The field is optional and non-secret; it flows through the existing
connection-resolution/merge path with no other changes. It is not part of the
provider/protocol/client-kind vocabulary, so the cross-package shape guard is
unaffected
.

ai-provider-bridge

  • SnowflakeClient now recognizes an internal sentinel value (SESSION) on the
    X-Snowflake-Authorization-Token-Type header. When present, the client
    authenticates with Authorization: Snowflake Token="<token>" (the scheme
    Snowflake session tokens use) instead of a Bearer token, via a fetch wrapper
    applied on both the Anthropic (Claude) and OpenAI paths. The sentinel
    header is stripped before the request is sent.
  • The existing Bearer paths (keypair JWT, PAT, OAuth) are unchanged — the new
    branch only activates when a caller opts in with the sentinel.

Why a fetch wrapper: authorization is on the SDK-managed header filter, so a
session token can't be injected via customHeaders; wrapping fetch is the
reliable way to set the final Authorization header after the SDK builds the
request.

Why

Snowflake Cortex's REST API accepts different auth schemes depending on the
credential:

  • keypair JWT / PAT / OAuth → Authorization: Bearer <token> + a token-type
    header (already supported), and
  • external-browser SSO → a session token sent as
    Authorization: Snowflake Token="<token>" (this PR).

Recording the selected connectionName (non-secret) in providers.json lets the
consumer resolve the right connection on each request without persisting secrets.

Testing

  • npm run build (regenerates providers.schema.json)
  • npm run check-types — per-workspace typechecks + the cross-package shape
    guard
    all pass
  • npm testai-config (173) and ai-provider-bridge (210) suites pass

Compatibility / risk

  • Backward compatible. connectionName is optional; the SESSION path is
    inert unless a caller sends the sentinel. No behavior change for existing
    providers or Bearer-based Snowflake auth.
  • No new dependencies.

Companion PR

Consumed by posit-dev/assistant (Snowflake connections.toml discovery,
per-authenticator token acquisition, connection-selection UI). That PR pins the
submodule to this commit.

costrouc added 2 commits July 9, 2026 16:27
Adds an optional, non-secret `connectionName` to the snowflake connection
sub-section so a consumer can record which connections.toml connection to use
for Snowflake Cortex. Regenerates providers.schema.json. Non-vocabulary change;
the shape guard is unaffected.
…rowser SSO

External-browser SSO yields a Snowflake session token that must be sent as
`Authorization: Snowflake Token="<token>"` rather than a Bearer token. When the
credential's `X-Snowflake-Authorization-Token-Type` header is the internal
`SESSION` sentinel, the client installs that header via a fetch wrapper on both
the Anthropic (Claude) and OpenAI paths and strips the sentinel before sending.
Keypair/PAT/OAuth Bearer paths are unchanged.
@costrouc costrouc marked this pull request as draft July 9, 2026 20:58
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