Fluid Forge
Why Forge
Concepts
Get Started
  • Consume a Data Product
  • See it run
  • Demos
  • Local (DuckDB)
  • Source-Aligned (Postgres → DuckDB)
  • AI Forge + Data Models
  • MCP Output Port — Serve to AI Agents
  • GCP (BigQuery)
  • Snowflake Team Collaboration
  • Declarative Airflow
  • Orchestration Export
  • Jenkins CI/CD
  • Universal Pipeline
  • 11-Stage Production Pipeline
  • Catalog Forge End-to-End
CLI Reference
  • Agent Policy (concept)
  • MCP Output Port — Serve to Agents
  • MCP deep-dive
  • AI-assisted authoring
  • LLM providers & backends
  • Overview
  • Quickstart
  • Examples
  • Your own CI
  • Your own scaffolding
  • Custom validator
  • Apply hook
  • Reference
  • Overview
  • Architecture
  • GCP (BigQuery)
  • AWS (S3 + Athena)
  • Snowflake
  • Local (DuckDB)
  • Custom Providers
  • Roadmap
GitHub
Why Forge
Concepts
Get Started
  • Consume a Data Product
  • See it run
  • Demos
  • Local (DuckDB)
  • Source-Aligned (Postgres → DuckDB)
  • AI Forge + Data Models
  • MCP Output Port — Serve to AI Agents
  • GCP (BigQuery)
  • Snowflake Team Collaboration
  • Declarative Airflow
  • Orchestration Export
  • Jenkins CI/CD
  • Universal Pipeline
  • 11-Stage Production Pipeline
  • Catalog Forge End-to-End
CLI Reference
  • Agent Policy (concept)
  • MCP Output Port — Serve to Agents
  • MCP deep-dive
  • AI-assisted authoring
  • LLM providers & backends
  • Overview
  • Quickstart
  • Examples
  • Your own CI
  • Your own scaffolding
  • Custom validator
  • Apply hook
  • Reference
  • Overview
  • Architecture
  • GCP (BigQuery)
  • AWS (S3 + Athena)
  • Snowflake
  • Local (DuckDB)
  • Custom Providers
  • Roadmap
GitHub
  • Introduction

    • Home
    • Why Fluid Forge
    • Getting Started
    • Snowflake Quickstart
    • See it run
    • Forge Data Model
    • Vision & Roadmap
    • Playground
    • FAQ
  • Concepts

    • Concepts
    • Builds, Exposes, Bindings
    • What is a contract?
    • Quality, SLAs & Lineage
    • Governance & Policy
    • Agent Policy (LLM/AI governance)
    • Providers vs Platforms
    • Fluid Forge vs alternatives
  • Data Products

    • Consume a Data Product
    • Product Types — SDP, ADP, CDP
  • Walkthroughs

    • Walkthrough: Local Development
    • Source-Aligned: Postgres → DuckDB → Parquet
    • AI Forge And Data-Model Journeys
    • Walkthrough: MCP Output Port
    • Walkthrough: Deploy to Google Cloud Platform
    • Walkthrough: Snowflake Team Collaboration
    • Declarative Airflow DAG Generation - The FLUID Way
    • Generating Orchestration Code from Contracts
    • Jenkins CI/CD for FLUID Data Products
    • Universal Pipeline
    • The 11-Stage Pipeline
    • End-to-End Walkthrough: Catalog → Contract → Transformation
  • CLI Reference

    • CLI Reference
    • Core workflow

      • fluid init
      • fluid demo
      • fluid forge
      • fluid validate
      • fluid plan
      • fluid apply
      • fluid diff
      • fluid status
    • Build & ship

      • fluid bundle
      • fluid generate
      • fluid generate artifacts
      • fluid validate-artifacts
      • fluid verify-signature
      • fluid generate iac
      • fluid generate-airflow
      • fluid generate-pipeline
      • fluid viz-graph
      • fluid publish
      • fluid ship
      • fluid rollback
      • fluid schedule-sync
    • AI & Agents

      • fluid ai
      • fluid agents
      • fluid mcp
      • fluid memory
      • fluid stats
      • fluid skills
    • Quality & governance

      • fluid test
      • fluid verify
      • fluid contract-tests
      • fluid contract-validation
      • fluid policy
      • fluid policy check
      • fluid policy compile
      • fluid policy apply
    • Standards & interoperability

      • fluid odps
      • fluid odps-bitol
      • fluid odcs
      • fluid export
      • fluid export-odps
      • fluid exporters
      • fluid import
      • fluid market
      • fluid datamesh-manager
    • Project & workspace

      • fluid product-new
      • fluid product-add
      • fluid workspace
      • fluid contract
      • fluid split
      • fluid config
      • fluid providers
      • fluid plugins
      • fluid provider-init
      • fluid auth
      • fluid secrets
      • fluid ide
      • fluid scaffold-ci
      • fluid scaffold-composer
      • fluid scaffold-ide
      • fluid docs
      • fluid runs
      • fluid retention
      • fluid describe
      • fluid doctor
      • fluid roadmap
      • fluid version
    • Catalog adapters

      • Source Catalog Integration (V1.5)
      • Publishing to a Catalog — Overview
      • BigQuery Catalog
      • Snowflake Horizon Catalog
      • Databricks Unity Catalog
      • Google Dataplex Catalog
      • AWS Glue Data Catalog
      • DataHub Catalog
      • Data Mesh Manager Catalog
      • OpenMetadata Catalog
    • CLI by task

      • CLI by task
      • Add quality rules
      • Add agent governance
      • Debug a failed pipeline run
      • Switch clouds with one line
  • Recipes

    • Recipes
    • Recipe — add a quality rule
    • Recipe — switch clouds with one line
    • Recipe — tag PII in your schema
    • Write a contract that consumes another contract
    • Generate per-environment overlays
  • SDK & Plugins

    • SDK & Plugins
    • Quickstart — your first plugin
    • Examples

      • Runnable examples
      • Example: hello-scaffold — the minimal viable plugin
      • Example: gitlab-ci-scaffold — generate a complete CI project
      • Example: steward-validator — a custom governance rule
      • Example: prod-key-guard — apply-time invariant check
    • Journeys

      • Journeys
      • Your own CI/CD

        • You have your own CI/CD setup, no problem
        • GitLab CI — the bundle template
        • GitHub Actions — the bundle template
        • Jenkins — the bundle template
        • CircleCI — the bundle template
      • You have a strict project layout, no problem
      • You have governance rules, no problem
      • You want a check at apply time, no problem
    • Reference

      • Reference
      • Roles reference
      • Entry points reference
      • Trust model
      • Packaging
      • Companion packages
  • Providers

    • Providers
    • Provider Architecture
    • GCP Provider
    • AWS Provider
    • Snowflake Provider
    • Local Provider
    • Creating Custom Providers
    • Provider Roadmap
  • AI & Agents

    • MCP Server
    • Built-in And Custom Forge Guidance
    • Forge Discovery Guide
    • Forge Memory Guide
    • Authoring Forge Tools
    • Guided fluid forge UX
    • LLM Providers
    • LiteLLM Backend
    • Capability Warnings
    • Cost Tracking
    • FLUID Forge Contract GPT Packet
    • Agentic Primitives
  • Operate & Deploy

    • Airflow Integration
    • Blueprints
    • Source-Aligned Acquisition
  • Govern & Secure

    • Governance, Compliance & the Business Case
    • Governance & Compliance
    • Network Safety
    • Credential Resolver — Security Model
  • Configuration & Reference

    • Environment Variables
    • Typed Errors
    • Typed CLI Errors
    • API Stability — fluid_build.api
  • Architecture & Releases

    • V1.5 Catalog Integration — Architecture Deep-Dive
    • V1.5 + V2 Hardening — Release Notes
  • Project

    • Contributing to Fluid Forge
    • Fluid Forge Docs Baseline: CLI 0.9.0
    • Fluid Forge Docs Baseline: CLI 0.8.11
    • Fluid Forge Docs Baseline: CLI 0.8.10
    • Fluid Forge Docs Baseline: CLI 0.8.9
    • Fluid Forge Docs Baseline: CLI 0.8.8
    • Fluid Forge Docs Baseline: CLI 0.8.7
    • Fluid Forge Docs Baseline: CLI 0.8.6
    • Fluid Forge Docs Baseline: CLI 0.8.5
    • Fluid Forge Docs Baseline: CLI 0.8.4
    • Fluid Forge Docs Baseline: CLI 0.8.3
    • Fluid Forge Docs Baseline: CLI 0.8.0
    • Fluid Forge Docs Baseline: CLI 0.7.11
    • Fluid Forge Docs Baseline: CLI 0.7.9
    • Fluid Forge v0.7.1 - Multi-Provider Export Release

Credential Resolver — Security Model

The CredentialResolver is the V1.5 security boundary that keeps catalog credentials out of agent-driven MCP sessions. This page documents the resolution chain, the storage rules, and the fail-closed behavior — so security teams can audit and so users know exactly where their secrets live.

The contract

The MCP server never holds catalog credentials. Each tool call receives a credential_id string. The resolver maps the string to a concrete credential at call time, from the highest-trust source available.

The CLI surface uses the same resolver, so a fluid forge data-model from-source --source snowflake --credential-id snowflake-prod and a Claude Code forge_from_source MCP call exercise the identical credential path.

Resolution chain (highest trust first)

1. inline_credentials (CLI only — direct API call)
            │
            ▼  not provided?
2. OS keyring (macOS Keychain / Windows Credential Manager /
   Linux secret-service via `keyring` package)
            │
            ▼  not found?
3. ~/.fluid/sources.yaml  (non-sensitive fields only — never
   secrets in plain text)
            │
            ▼  not found?
4. Environment variables (catalog-specific names —
   SNOWFLAKE_PRIVATE_KEY_PATH, DATABRICKS_TOKEN, etc.)
            │
            ▼  not found?
5. Cloud metadata service (opt-in via allow_metadata_service=True
   — instance profiles, workload identity)
            │
            ▼  still not found?
6. Fail-closed → raise CredentialNotFoundError with a
   suggestions[] list pointing the operator at `fluid ai setup
   --source <catalog> --credential-id <name>`.

What lands where

For ~/.fluid/sources.yaml, secrets are never stored in plain text. The wizard splits each source into two categories:

Field typeStorage
Non-sensitive (host, account, region, role, default DB/schema, user)~/.fluid/sources.yaml (plain YAML, world-readable mode 0644 OK)
Sensitive (token, password, private key passphrase, API key, secret)OS keyring entry under fluid:<source-name>:<field>

Example ~/.fluid/sources.yaml:

sources:
  snowflake-prod:
    catalog: snowflake
    account: myorg-abc12345
    user: analyst@example.com
    auth_method: key_pair
    private_key_path: /Users/me/.ssh/snowflake_key.p8
    # private_key_passphrase: <in OS keyring>
    warehouse: COMPUTE_WH
    role: ANALYST

  databricks-prod:
    catalog: databricks
    host: https://dbc-12345.cloud.databricks.com
    auth_method: pat
    # token: <in OS keyring>
    default_catalog: main
    default_schema: biz_lab

The keyring entries are visible (and revocable) via your OS:

  • macOS: Keychain Access app, search for "fluid:".
  • Windows: Credential Manager → Generic Credentials.
  • Linux: secret-tool search service fluid.

Per-catalog credential classes

Each catalog has a typed *Credentials Pydantic model with SecretStr fields for sensitive values:

class SnowflakeCredentials(BaseModel):
    account: str                                  # non-sensitive
    user: str                                     # non-sensitive
    auth_method: Literal["key_pair", "password", "externalbrowser", "oauth"]
    private_key_path: Path | None = None          # non-sensitive (path only)
    private_key_passphrase: SecretStr | None = None
    password: SecretStr | None = None
    role: str | None = None
    warehouse: str | None = None
    database: str | None = None
    schema_name: str | None = None

SecretStr is a Pydantic primitive that:

  • prints as ********** in any __repr__ / model_dump_json call;
  • requires explicit .get_secret_value() to access the underlying string;
  • is excluded from audit_context() results so no secret ever lands in an audit event.

The seven classes — SnowflakeCredentials, UnityCredentials, BigQueryCredentials, DataplexCredentials, GlueCredentials, DataHubCredentials, DataMeshManagerCredentials — are all in the public API (pinned by tests/test_public_api_stability.py).

Inline credentials are CLI-only

The MCP wire format has no inline_credentials field. The schema in fluid_build/cli/mcp.py::_CREDENTIALS_PROP only accepts credential_id:

{
  "credentials": {
    "credential_id": "snowflake-prod"
    // no token, no password — server rejects extra secret keys
  }
}

This is enforced by:

  1. The MCP inputSchema (advertised at tools/list) showing credential_id as the only required field on credentials.
  2. Server-side validation that rejects credential blocks with inline secret keys.
  3. Tests pinning that no MCP tool path ever accepts inline secrets.

CLI direct callers can still pass inline credentials when needed (e.g. one-off scripts that don't want to set up sources.yaml) — the resolver checks inline first.

Cloud metadata service is opt-in

For workloads running on AWS EC2 / ECS / Lambda / Cloud Run / GKE that have an instance profile or workload identity attached, the resolver can fall back to the cloud metadata service. This is off by default because:

  • Metadata service auth typically grants broad scopes.
  • Operators should explicitly choose between scoped credentials and broad-IAM auth.

Opt in per call:

fluid forge data-model from-source \
  --source glue \
  --credential-id glue-prod \
  --allow-metadata-service \
  --database my_db -o my_db.fluid.yaml

Or via MCP:

{ "tool": "forge_from_source", "arguments": {
  "source": "glue",
  "credentials": { "credential_id": "glue-prod" },
  "allow_metadata_service": true,
  ...
}}

When metadata service is the only credential source available AND allow_metadata_service=False, the resolver raises CredentialNotFoundError rather than silently using broad IAM.

Audit trail per resolution

Every successful credential resolution writes an audit event:

{
  "event": "credential.resolved",
  "credential_id": "snowflake-prod",
  "catalog_name": "snowflake",
  "source": "keyring",        // or "sources.yaml" / "env" / "metadata_service" / "inline"
  "auth_method": "key_pair",
  "timestamp": "2026-04-25T14:33:21.123Z"
}

The actual secret values are NEVER in the audit event — only the metadata about which source supplied them. Query with:

fluid memory show audit --filter credential.resolved

Failure modes

CredentialNotFoundError is raised with a suggestions: list[str] field that contains the exact command the operator should run:

raise CredentialNotFoundError(
    f"No credentials configured for source 'snowflake-prod'.",
    suggestions=[
        "Run: fluid ai setup --source snowflake --name snowflake-prod",
        "Or set: SNOWFLAKE_ACCOUNT, SNOWFLAKE_USER, "
        "SNOWFLAKE_PRIVATE_KEY_PATH (key_pair auth)",
    ],
)

The next-action is in the message — not buried in the docs.

See also

  • Catalogs index — per-catalog auth options
  • V1.5 architecture — full security model
  • fluid ai setup — interactive wizard
Edit this page on GitHub
Last Updated: 4/26/26, 10:42 PM
Contributors: fas89, Claude Opus 4.7
Prev
Network Safety