> ## Documentation Index
> Fetch the complete documentation index at: https://docs.platinur.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect Your Data Warehouse

> Choose a warehouse engine, bind it to the account, and manage connection credentials.

## Choosing a warehouse

A newly registered Platinur account has no warehouse bound. The operator opens **Configuration** and selects a warehouse engine from the selector. Filling in the required connection details and clicking **Test connection** verifies reachability; a successful test binds the engine to the account.

Until a warehouse is bound, source loading and modeling are unavailable.

## Supported engines

| Engine     | Status | Notes                                                                         |
| ---------- | ------ | ----------------------------------------------------------------------------- |
| ClickHouse | GA     | Connect your own cluster or ClickHouse Cloud service.                         |
| Snowflake  | Beta   | Key-pair (RSA) authentication — password sign-in is blocked by Snowflake MFA. |
| BigQuery   | Beta   | Service-account JSON + dataset location.                                      |
| Databricks | Beta   | Unity Catalog. Personal-access token.                                         |
| Redshift   | Beta   | User/password or IAM credentials.                                             |

Microsoft Synapse and Microsoft Fabric are not supported.

## Choosing an engine is a one-time decision

Once a successful test binds the engine kind, the engine kind is fixed for that account. Attempting to save a different engine kind returns **HTTP 409** with the message "reset the account to choose a different one."

The connection details and credentials for the bound engine remain editable at any time — change a hostname, rotate a key, or swap service-account credentials without affecting the binding.

## Per-engine credentials

Credentials are stored as secret references inside Platinur's secret store, never written to YAML or logs. Fields marked **secret** are encrypted at rest and never echoed back through the portal.

### ClickHouse

You need: a reachable ClickHouse cluster (self-managed or ClickHouse Cloud) and a user with the permissions below. Supply the hostname and credentials in the form; Platinur connects to your cluster over the network, with TLS by default.

| Form field              | What it is                                                                      | How to obtain it                                                             |
| ----------------------- | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| **Host**                | Hostname of the ClickHouse server, no scheme or port                            | Your cluster hostname, or the endpoint from ClickHouse Cloud service details |
| **HTTP port**           | HTTP(S) interface port (default 8443 with TLS, 8123 without)                    | Read from cluster config; ClickHouse Cloud defaults to 8443                  |
| **Native port**         | Native TCP interface port (default 9440 with TLS, 9000 without)                 | Read from cluster config; ClickHouse Cloud defaults to 9440                  |
| **Username**            | ClickHouse login name (default `default`)                                       | Create a dedicated user in ClickHouse or use `default`                       |
| **Password** *(secret)* | Password for the ClickHouse user                                                | Create a dedicated user and password in ClickHouse, or use an existing one   |
| **Analytics database**  | Target database Platinur writes dbt output into (default `analytics`)           | Create this database, or grant `CREATE DATABASE` so Platinur creates it      |
| **Raw database**        | Fallback raw schema name when no source-specific schema applies (default `raw`) | Leave as `raw`; Platinur creates it if it does not exist                     |
| **Use TLS**             | Enable HTTPS/TLS for all connections                                            | Enable for ClickHouse Cloud and any TLS-terminated cluster                   |

The ClickHouse user needs `CREATE DATABASE` on the server and full DDL/DML on Platinur's output databases (`raw`, `stg_*`, `prod_*`, and `*_validation`), plus `SELECT` on source databases it should model from. For source data loaded outside Platinur, see [External Source Schemas](/sources/external-schemas).

**Network access.** If your cluster sits behind a firewall or IP allowlist, allowlist Platinur's egress IP (available from support) on both configured ports.

**ClickHouse Cloud.** The defaults match ClickHouse Cloud: HTTPS on 8443, native TLS on 9440, and **Use TLS** enabled. Use the hostname and credentials from your service's connection details. Trial and development services idle when unused, and the first query after idling is slow while the service wakes — a sluggish first connection test or source load after a quiet period is expected.

***

### Snowflake

You need: a Snowflake account, a dedicated virtual warehouse, a dedicated database, a custom role, and a service user. Authenticate the service user with an RSA key pair — the private key is stored as a secret ref. Password sign-in is not supported (Snowflake enforces MFA for it). Platinur creates and manages schemas inside the database you supply.

<Warning>
  **Use key-pair authentication, not a password.** Snowflake now enforces multi-factor
  authentication for password sign-in. A non-interactive service like Platinur cannot answer an
  MFA challenge, so password auth fails with `Multi-factor authentication is required for this
      account`. Enrolling a passkey on your own user does not help — it applies to your human login,
  not the service user, and a headless connection cannot complete MFA regardless. Authenticate the
  service user with an RSA key pair (below), which is exempt from MFA. Optionally mark it a
  service-type user so it cannot use a password at all: `ALTER USER PLATINUR_SVC SET TYPE = SERVICE`.
</Warning>

| Form field                                 | What it is                                             | How to obtain it                                                                                               |
| ------------------------------------------ | ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| **Account identifier**                     | Snowflake account locator (e.g. `ORGNAME-ACCOUNTNAME`) | Snowsight → Account menu (bottom-left) → Account details; copy the org-account slug                            |
| **User**                                   | Snowflake login name for the service user              | **Create** — see provisioning snippet below (`PLATINUR_SVC`)                                                   |
| **Private key (PEM)** *(secret, required)* | Full PEM-encoded PKCS#8 RSA private key                | **Create** — generated with `openssl` (unencrypted); paste the complete file including header and footer lines |
| **Role**                                   | Snowflake role Platinur assumes for all operations     | **Create** — see provisioning snippet below (`PLATINUR_ROLE`)                                                  |
| **Warehouse**                              | Virtual warehouse used for queries and dbt runs        | **Create** — see provisioning snippet below (`PLATINUR_WH`)                                                    |
| **Database**                               | Database Platinur builds all schemas into              | **Create** — see provisioning snippet below (`PLATINUR`)                                                       |
| **Default schema**                         | Starting schema within the database (default `public`) | Leave as `public`; Platinur creates layer schemas (`stg_staging`, `stg_dw`, etc.) automatically                |

**Account identifier format.** The modern org-account form `ORGNAME-ACCOUNTNAME` works directly and is preferred. On a legacy account without an org slug, use the locator form `<locator>.<region>.<cloud>` visible in Snowsight → Account details.

**Key-pair auth.** Generate a PKCS#8 private key and extract the public key:

```bash theme={null}
# Generate an unencrypted PKCS#8 RSA private key
openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -out platinur_rsa_key.p8

# Extract the matching public key
openssl rsa -in platinur_rsa_key.p8 -pubout -out platinur_rsa_key.pub
```

Register the public key on the Snowflake user (run as a Snowflake user admin):

```sql theme={null}
ALTER USER PLATINUR_SVC
  SET RSA_PUBLIC_KEY = '<contents of platinur_rsa_key.pub, without the BEGIN/END header lines>';
```

Paste the full contents of `platinur_rsa_key.p8` (header, body, and footer) into the **Private key (PEM)** field.

**Provisioning snippet (run as ACCOUNTADMIN or SYSADMIN):**

```sql theme={null}
-- Virtual warehouse
CREATE WAREHOUSE IF NOT EXISTS PLATINUR_WH
  WAREHOUSE_SIZE = 'X-SMALL'
  AUTO_SUSPEND   = 60
  AUTO_RESUME    = TRUE
  INITIALLY_SUSPENDED = TRUE;

-- Target database
CREATE DATABASE IF NOT EXISTS PLATINUR;

-- Dedicated role
CREATE ROLE IF NOT EXISTS PLATINUR_ROLE;

-- Service user — key-pair only (no password). TYPE = SERVICE marks it a non-human
-- automation user that cannot use a password or MFA. Register its public key with the
-- `ALTER USER ... SET RSA_PUBLIC_KEY` statement from the "Key-pair auth" step above.
CREATE USER IF NOT EXISTS PLATINUR_SVC
  TYPE              = SERVICE
  DEFAULT_ROLE      = PLATINUR_ROLE
  DEFAULT_WAREHOUSE = PLATINUR_WH;

-- Warehouse usage
GRANT USAGE ON WAREHOUSE PLATINUR_WH TO ROLE PLATINUR_ROLE;

-- Full ownership of the target database so Platinur can manage schemas
GRANT OWNERSHIP ON DATABASE PLATINUR TO ROLE PLATINUR_ROLE COPY CURRENT GRANTS;

-- Read access to each source database Platinur should model from.
-- Repeat the three lines below for every source database.
-- GRANT USAGE ON DATABASE <your_source_db> TO ROLE PLATINUR_ROLE;
-- GRANT USAGE ON ALL SCHEMAS IN DATABASE <your_source_db> TO ROLE PLATINUR_ROLE;
-- GRANT SELECT ON ALL TABLES IN DATABASE <your_source_db> TO ROLE PLATINUR_ROLE;

-- Bind role to user
GRANT ROLE PLATINUR_ROLE TO USER PLATINUR_SVC;
```

**Form field mapping:**

* `PLATINUR_SVC` → **User**
* Contents of `platinur_rsa_key.p8` → **Private key (PEM)**
* `PLATINUR_ROLE` → **Role**
* `PLATINUR_WH` → **Warehouse**
* `PLATINUR` → **Database**
* Org-account slug from Snowsight → **Account identifier**

***

### BigQuery

You need: a GCP project, a service account with BigQuery IAM roles, a downloaded JSON key file, and a GCS bucket for dlt load staging. The entire JSON key is stored as a secret ref. All BigQuery datasets are created in the location you specify and cannot be moved after creation.

| Form field                                | What it is                                                             | How to obtain it                                                                                    |
| ----------------------------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| **Project ID**                            | GCP project that owns the BigQuery datasets                            | **Read** — GCP console project selector, or `gcloud config get-value project`                       |
| **Default dataset**                       | BigQuery dataset used as the default dbt target (default `platinur`)   | **Create** — Platinur creates it on first run; pick a name meaningful to your project               |
| **Location**                              | Dataset region, e.g. `US`, `EU`, `us-central1`                         | **Choose** — must match all datasets and the GCS staging bucket; immutable after creation           |
| **Service-account key (JSON)** *(secret)* | Full service-account JSON key file contents                            | **Create** — download after creating the service account; see snippet below                         |
| **Max bytes billed / query**              | Per-query cost guard in bytes (default 1 GB)                           | Set based on your BigQuery budget; raise for large dbt models                                       |
| **Staging GCS bucket URL**                | `gs://bucket/prefix` dlt writes load files here before BigQuery ingest | **Create** — provision a GCS bucket in the same location; required to run Integrations source loads |

**Location is immutable.** Platinur creates every dataset (output layers, raw, and the validation sandbox) in the location you enter here. Cross-location joins fail immediately. Choose a single region or multi-region value and create your GCS staging bucket in the same location.

**Provisioning snippet:**

```bash theme={null}
PROJECT_ID="<project-id>"
SA_NAME="platinur-svc"
SA_EMAIL="${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
STAGING_BUCKET="gs://my-platinur-staging"

# Create the service account
gcloud iam service-accounts create "${SA_NAME}" \
  --display-name="Platinur service account" \
  --project="${PROJECT_ID}"

# BigQuery: create/update datasets and tables
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
  --member="serviceAccount:${SA_EMAIL}" \
  --role="roles/bigquery.dataEditor"

# BigQuery: run queries and load jobs
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
  --member="serviceAccount:${SA_EMAIL}" \
  --role="roles/bigquery.jobUser"

# GCS: read and write load-staging files
gcloud storage buckets add-iam-policy-binding "${STAGING_BUCKET}" \
  --member="serviceAccount:${SA_EMAIL}" \
  --role="roles/storage.objectAdmin"

# Download the JSON key — paste its contents into the form field
gcloud iam service-accounts keys create platinur-svc-key.json \
  --iam-account="${SA_EMAIL}" \
  --project="${PROJECT_ID}"
```

Keep `platinur-svc-key.json` secure; delete it locally after pasting into the form. If you prefer dataset-scoped grants instead of project-level `bigquery.dataEditor`, create the target datasets first and bind `roles/bigquery.dataEditor` per dataset. `roles/bigquery.jobUser` must remain at the project level.

**Form field mapping:**

* GCP project ID → **Project ID**
* Contents of `platinur-svc-key.json` → **Service-account key (JSON)**
* `US` / `EU` / region string → **Location**
* `platinur` (or chosen name) → **Default dataset**
* `gs://my-platinur-staging/...` → **Staging GCS bucket URL**

***

### Databricks

You need: a Databricks workspace, a running SQL warehouse, a Unity Catalog with a dedicated catalog, a personal access token (PAT) or OAuth M2M token, and a dlt staging location. Platinur uses 3-level Unity Catalog addressing (`catalog.schema.table`) — the legacy `hive_metastore` is not supported.

| Form field                        | What it is                                                                     | How to obtain it                                                                                                |
| --------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| **Workspace host**                | Workspace URL without `https://`, e.g. `dbc-xxxx.cloud.databricks.com`         | **Read** — copy the hostname from your browser's address bar when logged into the workspace                     |
| **SQL warehouse HTTP path**       | HTTP path of the SQL warehouse Platinur connects to                            | **Read** — SQL Warehouses → select warehouse → Connection details tab → HTTP path                               |
| **Access token (PAT)** *(secret)* | Personal access token or OAuth M2M token                                       | **Create** — workspace → user name (top-right) → User settings → Developer → Access tokens → Generate new token |
| **Unity catalog**                 | Name of the Unity Catalog catalog Platinur builds into                         | **Create** — see provisioning snippet below (`platinur`)                                                        |
| **Default schema**                | Starting schema within the catalog (default `default`)                         | Leave as `default`; Platinur creates layer schemas automatically                                                |
| **Staging Unity Catalog volume**  | UC volume path dlt writes load files to, e.g. `/Volumes/platinur/staging/dlt`  | **Create** — `CREATE VOLUME` inside the catalog; preferred staging method (no extra bucket credentials needed)  |
| **Staging cloud bucket URL**      | Cloud bucket (`s3://`, `abfss://`, `gs://`) as an alternative staging location | **Create** — provision a cloud bucket accessible from the workspace; use only when a UC volume is not available |

At least one staging field (**Staging Unity Catalog volume** or **Staging cloud bucket URL**) must be set to run Integrations source loads. The UC volume approach is preferred — the workspace token authorizes it directly with no additional bucket credentials.

**Where to find the SQL warehouse HTTP path.** In your Databricks workspace, open **SQL Warehouses** in the left sidebar, click your warehouse, then open the **Connection details** tab. The HTTP path looks like `/sql/1.0/warehouses/abc123def456`.

**Provisioning snippet (run as a Unity Catalog admin):**

```sql theme={null}
-- Create a dedicated catalog for Platinur
CREATE CATALOG IF NOT EXISTS platinur
  COMMENT 'Platinur analytics engineering output';

-- Grant the service principal (or the user whose PAT you use) access to the catalog.
-- Replace <principal> with the service principal application ID or user email.
GRANT USE CATALOG  ON CATALOG platinur TO `<principal>`;
GRANT CREATE SCHEMA ON CATALOG platinur TO `<principal>`;
GRANT USE SCHEMA   ON CATALOG platinur TO `<principal>`;
GRANT CREATE TABLE  ON CATALOG platinur TO `<principal>`;
GRANT MODIFY       ON CATALOG platinur TO `<principal>`;

-- Create a schema and managed volume for dlt staging (preferred)
CREATE SCHEMA IF NOT EXISTS platinur.staging;

CREATE VOLUME IF NOT EXISTS platinur.staging.dlt
  COMMENT 'dlt load-file staging for Platinur Integrations';

GRANT READ VOLUME  ON VOLUME platinur.staging.dlt TO `<principal>`;
GRANT WRITE VOLUME ON VOLUME platinur.staging.dlt TO `<principal>`;

-- Grant read access to source catalogs/schemas Platinur should model from.
-- Repeat for each source schema.
-- GRANT USE CATALOG ON CATALOG <source_catalog> TO `<principal>`;
-- GRANT USE SCHEMA  ON SCHEMA  <source_catalog>.<source_schema> TO `<principal>`;
-- GRANT SELECT ON ALL TABLES IN SCHEMA <source_catalog>.<source_schema> TO `<principal>`;
```

Generate a PAT in the workspace under your user name (top-right) → **User settings** → **Developer** → **Access tokens** → **Generate new token**. Copy it immediately — it is shown only once.

**Form field mapping:**

* Workspace hostname (no `https://`) → **Workspace host**
* HTTP path from Connection details → **SQL warehouse HTTP path**
* Generated PAT → **Access token (PAT)**
* `platinur` → **Unity catalog**
* `/Volumes/platinur/staging/dlt` → **Staging Unity Catalog volume**

***

### Redshift

You need: a Redshift cluster endpoint, a target database, a dedicated service user (password auth) or an IAM-enabled cluster (IAM auth), and an S3 bucket with access credentials for dlt staging. All sensitive values are stored as secret refs.

| Form field                                   | What it is                                                                         | How to obtain it                                                                                                  |
| -------------------------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **Endpoint host**                            | Cluster endpoint hostname (strip the `:port` suffix)                               | **Read** — Redshift console → Clusters → your cluster → General information → Endpoint                            |
| **Port**                                     | Redshift port (default 5439)                                                       | **Read** — shown alongside the endpoint in the console                                                            |
| **Database**                                 | Database name Platinur connects to                                                 | **Create** or **Read** — use an existing analytics database or create one                                         |
| **Auth method**                              | `password` or `iam`                                                                | Choose based on your cluster's auth configuration                                                                 |
| **User**                                     | Redshift username                                                                  | **Create** — see provisioning snippet below (`PLATINUR_SVC`)                                                      |
| **Password** *(secret)*                      | Password for the Redshift user (password auth)                                     | **Create** — set in `CREATE USER`                                                                                 |
| **Cluster identifier (IAM)**                 | Short cluster name used for IAM token exchange (IAM auth only)                     | **Read** — the cluster name without the endpoint hostname suffix, e.g. `my-cluster`                               |
| **IAM profile (IAM)**                        | Named AWS profile with `redshift:GetClusterCredentials` permission (IAM auth only) | **Read** — the named profile from your own AWS IAM configuration; leave blank to use the default credential chain |
| **Default schema**                           | Default schema Platinur uses (default `public`)                                    | Leave as `public`; Platinur creates layer schemas automatically                                                   |
| **SSL mode**                                 | SSL connection mode (default `prefer`)                                             | Set to `require` for strict TLS enforcement                                                                       |
| **Staging S3 bucket URL**                    | `s3://bucket/prefix` dlt writes load files here before Redshift `COPY`             | **Create** — provision an S3 bucket in the same region as the cluster; required to run Integrations source loads  |
| **Staging AWS access key ID** *(secret)*     | IAM access key ID for the staging bucket (static-key auth)                         | **Create** — IAM → Users → staging IAM user → Security credentials → Create access key                            |
| **Staging AWS secret access key** *(secret)* | IAM secret access key (static-key auth)                                            | **Create** — shown once when the access key is created                                                            |
| **Staging IAM role ARN**                     | IAM role the cluster assumes for `COPY` (role-based staging auth)                  | **Create** or **Read** — IAM → Roles; attach the role to the cluster in the Redshift console                      |

The **Staging S3 bucket URL** is required for dlt Integrations loads. Provide either a static key pair (**Staging AWS access key ID** + **Staging AWS secret access key**) or an IAM role ARN (**Staging IAM role ARN**) to authorize `COPY` access. Do not supply both.

**Provisioning snippet (password auth; run as a superuser in the target database):**

```sql theme={null}
-- Create the Platinur service user
CREATE USER PLATINUR_SVC
  PASSWORD '<choose-a-strong-password>'
  CONNECTION LIMIT 10;

-- Allow the user to create schemas in the target database.
-- Platinur manages its own output schemas (stg_staging, stg_dw, stg_marts, etc.).
GRANT CREATE ON DATABASE analytics TO PLATINUR_SVC;

-- Grant read access to source schemas Platinur should model from.
-- Repeat for each schema containing raw source tables.
-- GRANT USAGE ON SCHEMA <source_schema> TO PLATINUR_SVC;
-- GRANT SELECT ON ALL TABLES IN SCHEMA <source_schema> TO PLATINUR_SVC;
-- ALTER DEFAULT PRIVILEGES IN SCHEMA <source_schema>
--   GRANT SELECT ON TABLES TO PLATINUR_SVC;
```

**IAM auth.** Set **Auth method** to `iam`, enter the short **Cluster identifier** (the cluster name, not the full endpoint hostname), and optionally an **IAM profile** name. The IAM principal must have `redshift:GetClusterCredentials` and `redshift:CreateClusterUser` on the cluster.

**S3 staging with an IAM role.** Attach the IAM role to the cluster in the Redshift console (Clusters → your cluster → Properties → IAM roles), then paste the role ARN into **Staging IAM role ARN**. Leave the static key fields blank.

**Form field mapping:**

* Cluster endpoint hostname → **Endpoint host**
* `analytics` (or your db name) → **Database**
* `PLATINUR_SVC` → **User**
* `<choose-a-strong-password>` → **Password**
* S3 bucket URL → **Staging S3 bucket URL**
* IAM access key → **Staging AWS access key ID** + **Staging AWS secret access key** (or role ARN → **Staging IAM role ARN**)

## Output namespaces

Regardless of engine, output namespaces follow the same fixed convention: `{stg|prod}_{layer}`.

On **ClickHouse** these are flat databases: `stg_staging`, `stg_dw`, `stg_marts` for staging and `prod_staging`, `prod_dw`, `prod_marts` for production.

On all other engines these are schemas (Snowflake, Redshift), datasets (BigQuery), or schemas within the Unity Catalog (Databricks), created under the bound database, project, or catalog. Platinur creates and manages these namespaces; they must not be modified outside Platinur.

The same convention applies to source data: each configured or externally loaded source lands in its own `raw_<source>` namespace, with a fallback `raw` namespace for sources that do not specify one. See [External Source Schemas](/sources/external-schemas) and [Source Load Modes](/sources/load-modes).

A throwaway `<analytics>_validation` sandbox is created and dropped automatically for each validation run — do not depend on it persisting.

## Account reset

The account reset is the one supported way to unbind the warehouse engine and start over with a different engine kind. It is an irreversible administrative action.

**Endpoint:** `POST /api/account/reset` — owner/admin only.

**Required body:**

```json theme={null}
{
  "confirm": "RESET",
  "drop_warehouse_objects": false
}
```

* `confirm` must be the literal string `"RESET"`.
* `drop_warehouse_objects: true` instructs Platinur to drop its own env output and validation namespaces (`stg_*`, `prod_*`, `*_validation`) before clearing the binding. Set to `false` to leave those namespaces in place.

The reset never touches customer raw or source schemas — only Platinur-owned output namespaces are eligible for the optional drop.

After a reset the account is empty again: no warehouse binding, no generated models, no run history. A new engine can then be selected and tested from Configuration.
