diff --git a/apps/docs/content/guides/cli.mdx b/apps/docs/content/guides/cli.mdx
index 13297eba2c2be..65484bc4c962b 100644
--- a/apps/docs/content/guides/cli.mdx
+++ b/apps/docs/content/guides/cli.mdx
@@ -6,7 +6,7 @@ subtitle: 'Developing locally using the Supabase CLI.'
sidebar_label: 'Overview'
---
-You can use the Supabase CLI to run the entire Supabase stack locally on your machine, by running `supabase init` and then `supabase start`. To install the CLI, see the [installation guide](/docs/guides/cli/getting-started#installing-the-supabase-cli).
+You can use the Supabase CLI to run the entire Supabase stack locally on your machine, by running `supabase init` and then `supabase start`. To install the CLI, read [the installation guide](/docs/guides/cli/getting-started#installing-the-supabase-cli).
The Supabase CLI provides tools to develop your project locally, deploy to the Supabase Platform, handle database migrations, and generate types directly from your database schema.
diff --git a/apps/docs/content/guides/local-development/cli/getting-started.mdx b/apps/docs/content/guides/local-development/cli/getting-started.mdx
index eb4f2186b2e2b..8b531f49e4bd2 100644
--- a/apps/docs/content/guides/local-development/cli/getting-started.mdx
+++ b/apps/docs/content/guides/local-development/cli/getting-started.mdx
@@ -72,28 +72,12 @@ The Supabase CLI requires **Node.js 20 or later** when run via `npx` or `npm`. O
-
-
-Installing the Supabase CLI globally using `npm install -g supabase` is **not supported**.
-
-For global usage, install the CLI via Homebrew, Scoop, or the standalone binary.
-
-Alternatively, you can run the CLI using `npx supabase` or install it locally as a dev dependency.
-
-
-
You can also install the CLI as dev dependency via [npm](https://www.npmjs.com/package/supabase):
```sh
npm install supabase --save-dev
```
-
-
-Global installation using `npm install -g supabase` is not supported. For global CLI usage, install via [Homebrew](/docs/guides/local-development/cli/getting-started?queryGroups=platform&platform=macos), [Scoop](/docs/guides/local-development/cli/getting-started?queryGroups=platform&platform=windows), or the [standalone binary](/docs/guides/local-development/cli/getting-started?queryGroups=platform&platform=linux).
-
-
-
@@ -157,7 +141,7 @@ npx supabase@beta --help
## Updating the Supabase CLI
-When a new [version](https://github.com/supabase/cli/releases) is released, you can update the CLI using the same methods.
+When a new [version](https://github.com/supabase/cli/releases) is released, you can update the CLI using the same channels.
-
-
-
-
-
-
-
-
-
-
-
-
-
+The Supabase CLI uses Docker containers to manage the local development stack. Follow the official guide to install and configure [Docker Desktop](https://docs.docker.com/desktop) on your machine.
Alternately, you can use a different container tool that offers Docker compatible APIs.
@@ -296,15 +241,13 @@ Alternately, you can use a different container tool that offers Docker compatibl
- [OrbStack](https://orbstack.dev/) (macOS)
- [colima](https://github.com/abiosoft/colima) (macOS)
-
-
Inside the folder where you want to create your project, run:
```bash
supabase init
```
-This will create a new `supabase` folder. It's safe to commit this folder to your version control system.
+This creates a new `supabase` folder. It's safe to commit this folder to version control.
Now, to start the Supabase stack, run:
@@ -312,11 +255,11 @@ Now, to start the Supabase stack, run:
supabase start
```
-This takes time on your first run because the CLI needs to download the Docker images to your local machine. The CLI includes the entire Supabase toolset, and a few additional images that are useful for local development (like a local SMTP server and a database diff tool).
+This takes time on your first run because the CLI needs to download the Docker images to your local machine. The CLI includes the entire Supabase stack, and a few additional images useful for local development (like a local SMTP server and a database diff tool).
## Access your project's services
-Once all of the Supabase services are running, you'll see output containing your local Supabase credentials. It should look like this, with urls and keys that you'll use in your local project:
+Once all the Supabase services are running, you'll see output containing your local Supabase credentials. It should look like the below, with urls and keys that you use in your local project:
```
Started supabase local development setup.
@@ -427,7 +370,7 @@ For advanced logs analysis using the Logs Explorer, it is advised to use the Big
-All logs will be stored in the local database under the `_analytics` schema.
+All logs are stored in the local database under the `_analytics` schema.
diff --git a/apps/docs/content/troubleshooting/database-error-saving-new-user-RU_EwB.mdx b/apps/docs/content/troubleshooting/database-error-saving-new-user-RU_EwB.mdx
index d054f6f4020e4..64a2d0b389c91 100644
--- a/apps/docs/content/troubleshooting/database-error-saving-new-user-RU_EwB.mdx
+++ b/apps/docs/content/troubleshooting/database-error-saving-new-user-RU_EwB.mdx
@@ -7,22 +7,88 @@ keywords = [ "users" ]
database_id = "5d1c44ed-b2f6-4509-9312-1eeb8838e701"
[[errors]]
+http_status_code = 500
+code = "unexpected_failure"
message = "Database error saving new user"
+
+[[errors]]
+http_status_code = 500
+code = "unexpected_failure"
+message = "Database error creating new user"
---
-You generally get this error when trying to invite a new user from the dashboard or when trying to insert a user into a table using the table editor in the Supabase dashboard.
+You generally get this error when trying to invite a new user from the dashboard or when trying to insert a user into a table using the table editor in the Supabase dashboard. You may also see this error in logs in connection to failed signups.
This error is normally associated with a side effect of a database transaction.
**Common causes of this error:**
-- You have a trigger/trigger function setup on the `auth.users` table
+- You have a trigger/trigger function setup on the `auth.users` table that has an error
- You have added a constraint on the `auth.users` table which isn't being met
- You are using Prisma and it has broken all the permissions on the `auth.users` table
-**Debugging this error:**
+## Debugging this error:
+
+**Step 1: Check the Auth logs**
+
+Start in the [Auth logs explorer](/dashboard/project/_/logs/auth-logs) in your project dashboard. The logs surface the specific error message and give you the most direct signal about what went wrong.
+
+**Step 2: Check the Postgres logs**
+
+If the Auth logs point to a database-level issue, open the [Postgres logs explorer](/dashboard/project/_/logs/postgres-logs) to look for corresponding errors.
+
+---
+
+## Common errors
+
+### NULL value in auth schema column
+
+**Example Auth log error:**
+
+```
+500: Database error querying schema
+error finding user: sql: Scan error on column index 8, name "confirmation_token": converting NULL to string is unsupported
+```
+
+**Cause:**
+
+The `auth` schema is managed by Supabase and expects specific column formats. This error typically happens when users are inserted directly via SQL or using an AI tool that uses a direct SQL `INSERT`, rather than through the [Auth API](/docs/reference/javascript/auth-api). A direct insert can leave required columns as `NULL` when the Auth service expects an empty string.
+
+**Fix:**
+
+Run the following in the [SQL editor](/dashboard/project/_/sql), replacing `confirmation_token` with whichever column appears in your error message:
+
+```sql
+update auth.users
+set confirmation_token = ''
+where confirmation_token is null;
+```
+
+This sets all `NULL` values in that column to an empty string, which is what the Auth service expects.
+
+---
+
+### Relation does not exist
+
+**Example Auth log error:**
+
+```
+failed to close prepared statement: ERROR: current transaction is aborted, commands ignored until end of transaction block (SQLSTATE 25P02): ERROR: relation "profiles" does not exist (SQLSTATE 42P01)
+```
+
+**Example Postgres log error:**
+
+```
+event_message: "relation "profiles" does not exist"
+context: "PL/pgSQL function public.handle_new_user() line 3 at SQL statement"
+```
+
+**Cause:**
+
+A trigger on `auth.users` is calling a function (in this case `handle_new_user`) that tries to insert into a table that does not exist. This is common when a `profiles` table is referenced in a trigger function but was never created, or was accidentally dropped.
+
+**Fix:**
-- You can use the [Auth logs explorer](https://app.supabase.com/project/_/logs/auth-logs) to find the issue with more information
-- You can use the [Postgres logs explorer](https://app.supabase.com/project/_/logs/postgres-logs)
+1. Check whether the missing table should exist in your `public` schema. If it should, create the table for the trigger to succeed and the error should resolve.
-https://user-images.githubusercontent.com/79497/225517698-b6e3ccaf-cd70-4acd-8124-ffbcee310d63.mp4
+2. If the table is not needed, review the function definition and update or remove the reference. You can view and edit your database functions from the [Database Functions](/dashboard/project/_/database/functions) page in the dashboard.
diff --git a/apps/docs/features/docs/MdxAnchor.tsx b/apps/docs/features/docs/MdxAnchor.tsx
new file mode 100644
index 0000000000000..30b2b54db4242
--- /dev/null
+++ b/apps/docs/features/docs/MdxAnchor.tsx
@@ -0,0 +1,46 @@
+import { ExternalLink as ExternalLinkIcon } from 'lucide-react'
+import { type ComponentPropsWithoutRef } from 'react'
+import { cn } from 'ui'
+
+const isExternalHref = (href?: string) => {
+ if (!href || !/^https?:\/\//i.test(href)) return false
+ try {
+ return !/(^|\.)supabase\.com$/i.test(new URL(href).hostname)
+ } catch {
+ return false
+ }
+}
+
+// Walk the tree and concatenate text so the aria-label matches the visible link
+const flattenChildrenToText = (node: unknown): string => {
+ if (node == null || typeof node === 'boolean') return ''
+ if (typeof node === 'string' || typeof node === 'number') return String(node)
+ if (Array.isArray(node)) return node.map(flattenChildrenToText).join('')
+ if (typeof node === 'object' && node !== null && 'props' in node) {
+ const props = (node as { props?: { children?: unknown } }).props
+ return flattenChildrenToText(props?.children)
+ }
+ return ''
+}
+
+export function MdxAnchor({ href, children, ...rest }: ComponentPropsWithoutRef<'a'>) {
+ if (!isExternalHref(href)) {
+ return (
+
+ {children}
+
+ )
+ }
+ const label = flattenChildrenToText(children).trim()
+ return (
+
+ {children}
+
+
+ )
+}
diff --git a/apps/docs/features/docs/MdxBase.shared.tsx b/apps/docs/features/docs/MdxBase.shared.tsx
index 134ffc1ed3191..591a8bf20cbba 100644
--- a/apps/docs/features/docs/MdxBase.shared.tsx
+++ b/apps/docs/features/docs/MdxBase.shared.tsx
@@ -19,6 +19,7 @@ import { SharedData } from '~/components/SharedData'
import StepHikeCompact from '~/components/StepHikeCompact'
import { CodeSampleDummy, CodeSampleWrapper } from '~/features/directives/CodeSample.client'
import { NamedCodeBlock } from '~/features/directives/CodeTabs.components'
+import { MdxAnchor } from '~/features/docs/MdxAnchor'
import { Accordion, AccordionItem } from '~/features/ui/Accordion'
import { CodeBlock } from '~/features/ui/CodeBlock/CodeBlock'
import InfoTooltip from '~/features/ui/InfoTooltip'
@@ -100,6 +101,7 @@ const components = {
Tabs,
TabPanel,
InfoTooltip,
+ a: MdxAnchor,
h2: (props: any) => (
{props.children}
diff --git a/apps/docs/public/img/guides/cli/docker-mac-light.png b/apps/docs/public/img/guides/cli/docker-mac-light.png
deleted file mode 100644
index ca0c3f88543e7..0000000000000
Binary files a/apps/docs/public/img/guides/cli/docker-mac-light.png and /dev/null differ
diff --git a/apps/docs/public/img/guides/cli/docker-mac.png b/apps/docs/public/img/guides/cli/docker-mac.png
deleted file mode 100644
index 733eada80a12b..0000000000000
Binary files a/apps/docs/public/img/guides/cli/docker-mac.png and /dev/null differ
diff --git a/apps/docs/public/img/guides/cli/docker-win-light.png b/apps/docs/public/img/guides/cli/docker-win-light.png
deleted file mode 100644
index 13778f6457728..0000000000000
Binary files a/apps/docs/public/img/guides/cli/docker-win-light.png and /dev/null differ
diff --git a/apps/docs/public/img/guides/cli/docker-win.png b/apps/docs/public/img/guides/cli/docker-win.png
deleted file mode 100644
index 9a2b389deb361..0000000000000
Binary files a/apps/docs/public/img/guides/cli/docker-win.png and /dev/null differ
diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.schema.ts b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.schema.ts
index f2a663138fa61..dd0da8a8e4769 100644
--- a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.schema.ts
+++ b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.schema.ts
@@ -43,6 +43,14 @@ export const DestinationPanelFormSchema = z.object({
ducklakeS3UrlStyle: z.enum(['path', 'vhost']).optional(),
ducklakeS3UseSsl: z.boolean().optional(),
ducklakeMetadataSchema: z.string().optional(),
+ // Snowflake fields
+ snowflakeAccountId: z.string().optional(),
+ snowflakeUser: z.string().optional(),
+ snowflakePrivateKey: z.string().optional(),
+ snowflakePrivateKeyPassphrase: z.string().optional(),
+ snowflakeDatabase: z.string().optional(),
+ snowflakeSchema: z.string().optional(),
+ snowflakeRole: z.string().optional(),
})
export type DestinationPanelSchemaType = z.infer
diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.utils.test.ts b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.utils.test.ts
index 571688989fa57..bd07b6bd471ee 100644
--- a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.utils.test.ts
+++ b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.utils.test.ts
@@ -4,6 +4,7 @@ import {
buildDestinationConfig,
buildDestinationConfigForValidation,
getDucklakeValidationIssues,
+ getSnowflakeValidationIssues,
} from './DestinationForm.utils'
const baseDucklakeFormData = {
@@ -37,6 +38,44 @@ const baseDucklakeFormData = {
ducklakeMetadataSchema: ' ducklake_metadata ',
}
+const baseSnowflakeFormData = {
+ name: 'Snowflake Destination',
+ publicationName: 'pub',
+ maxFillMs: undefined,
+ maxTableSyncWorkers: undefined,
+ maxCopyConnectionsPerTable: undefined,
+ invalidatedSlotBehavior: undefined,
+ projectId: undefined,
+ datasetId: undefined,
+ serviceAccountKey: undefined,
+ connectionPoolSize: undefined,
+ maxStalenessMins: undefined,
+ warehouseName: undefined,
+ namespace: undefined,
+ newNamespaceName: undefined,
+ catalogToken: undefined,
+ s3AccessKeyId: undefined,
+ s3SecretAccessKey: undefined,
+ s3Region: undefined,
+ ducklakeCatalogUrl: undefined,
+ ducklakeDataPath: undefined,
+ ducklakePoolSize: undefined,
+ ducklakeS3AccessKeyId: undefined,
+ ducklakeS3SecretAccessKey: undefined,
+ ducklakeS3Region: undefined,
+ ducklakeS3Endpoint: undefined,
+ ducklakeS3UrlStyle: undefined,
+ ducklakeS3UseSsl: undefined,
+ ducklakeMetadataSchema: undefined,
+ snowflakeAccountId: ' MYORG-MYACCOUNT ',
+ snowflakeUser: ' ETL_USER ',
+ snowflakePrivateKey: '-----BEGIN PRIVATE KEY-----\nabc\n-----END PRIVATE KEY-----',
+ snowflakePrivateKeyPassphrase: ' secret passphrase ',
+ snowflakeDatabase: ' ANALYTICS ',
+ snowflakeSchema: ' PUBLIC ',
+ snowflakeRole: ' ETL_ROLE ',
+}
+
describe('DestinationForm.utils DuckLake', () => {
it('builds DuckLake validation config with required fields trimmed and blank optionals removed', () => {
const config = buildDestinationConfigForValidation({
@@ -160,3 +199,74 @@ describe('DestinationForm.utils DuckLake', () => {
).toEqual([])
})
})
+
+describe('DestinationForm.utils Snowflake', () => {
+ it('builds Snowflake validation config with identifiers trimmed and secrets preserved', () => {
+ const config = buildDestinationConfigForValidation({
+ projectRef: 'project-ref',
+ selectedType: 'Snowflake',
+ data: {
+ ...baseSnowflakeFormData,
+ snowflakePrivateKeyPassphrase: '',
+ snowflakeRole: ' ',
+ },
+ })
+
+ expect(config).toEqual({
+ snowflake: {
+ accountId: 'MYORG-MYACCOUNT',
+ user: 'ETL_USER',
+ privateKey: '-----BEGIN PRIVATE KEY-----\nabc\n-----END PRIVATE KEY-----',
+ privateKeyPassphrase: undefined,
+ database: 'ANALYTICS',
+ schema: 'PUBLIC',
+ role: undefined,
+ },
+ })
+ })
+
+ it('builds Snowflake submit config with normalized values', async () => {
+ const createS3AccessKey = vi.fn()
+ const resolveNamespace = vi.fn()
+
+ const config = await buildDestinationConfig({
+ projectRef: 'project-ref',
+ selectedType: 'Snowflake',
+ data: baseSnowflakeFormData,
+ createS3AccessKey,
+ resolveNamespace,
+ })
+
+ expect(config).toEqual({
+ snowflake: {
+ accountId: 'MYORG-MYACCOUNT',
+ user: 'ETL_USER',
+ privateKey: '-----BEGIN PRIVATE KEY-----\nabc\n-----END PRIVATE KEY-----',
+ privateKeyPassphrase: ' secret passphrase ',
+ database: 'ANALYTICS',
+ schema: 'PUBLIC',
+ role: 'ETL_ROLE',
+ },
+ })
+ expect(createS3AccessKey).not.toHaveBeenCalled()
+ expect(resolveNamespace).not.toHaveBeenCalled()
+ })
+
+ it('returns required-field errors for missing Snowflake settings', () => {
+ const issues = getSnowflakeValidationIssues({
+ snowflakeAccountId: '',
+ snowflakeUser: '',
+ snowflakePrivateKey: '',
+ snowflakeDatabase: '',
+ snowflakeSchema: '',
+ })
+
+ expect(issues).toEqual([
+ { path: 'snowflakeAccountId', message: 'Account ID is required' },
+ { path: 'snowflakeUser', message: 'User is required' },
+ { path: 'snowflakePrivateKey', message: 'Private key is required' },
+ { path: 'snowflakeDatabase', message: 'Database is required' },
+ { path: 'snowflakeSchema', message: 'Schema is required' },
+ ])
+ })
+})
diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.utils.ts b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.utils.ts
index 70b3bd5be8ee8..8f7d3a53e1ba9 100644
--- a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.utils.ts
+++ b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationForm.utils.ts
@@ -13,6 +13,7 @@ import {
DestinationConfig,
DucklakeDestinationConfig,
IcebergDestinationConfig,
+ SnowflakeDestinationConfig,
} from '@/data/replication/create-destination-pipeline-mutation'
import {
type CreateS3AccessKeyCredentialVariables,
@@ -27,6 +28,10 @@ const normalizeOptionalString = (value?: string) => {
const normalizeRequiredString = (value?: string) => value?.trim() ?? ''
+const normalizeOptionalUntrimmedString = (value?: string) => {
+ return value && value.length > 0 ? value : undefined
+}
+
type DucklakeFieldPath =
| 'ducklakeCatalogUrl'
| 'ducklakeDataPath'
@@ -116,6 +121,53 @@ export const getDucklakeValidationIssues = (
return issues
}
+type SnowflakeFieldPath =
+ | 'snowflakeAccountId'
+ | 'snowflakeUser'
+ | 'snowflakePrivateKey'
+ | 'snowflakeDatabase'
+ | 'snowflakeSchema'
+
+export type SnowflakeValidationIssue = {
+ path: SnowflakeFieldPath
+ message: string
+}
+
+export const getSnowflakeValidationIssues = (
+ data: Pick<
+ DestinationPanelSchemaType,
+ | 'snowflakeAccountId'
+ | 'snowflakeUser'
+ | 'snowflakePrivateKey'
+ | 'snowflakeDatabase'
+ | 'snowflakeSchema'
+ >
+): SnowflakeValidationIssue[] => {
+ const issues: SnowflakeValidationIssue[] = []
+
+ if (!data.snowflakeAccountId?.trim().length) {
+ issues.push({ path: 'snowflakeAccountId', message: 'Account ID is required' })
+ }
+
+ if (!data.snowflakeUser?.trim().length) {
+ issues.push({ path: 'snowflakeUser', message: 'User is required' })
+ }
+
+ if (!data.snowflakePrivateKey?.trim().length) {
+ issues.push({ path: 'snowflakePrivateKey', message: 'Private key is required' })
+ }
+
+ if (!data.snowflakeDatabase?.trim().length) {
+ issues.push({ path: 'snowflakeDatabase', message: 'Database is required' })
+ }
+
+ if (!data.snowflakeSchema?.trim().length) {
+ issues.push({ path: 'snowflakeSchema', message: 'Schema is required' })
+ }
+
+ return issues
+}
+
// Helper function to build destination config for validation
export const buildDestinationConfigForValidation = ({
projectRef,
@@ -178,6 +230,18 @@ export const buildDestinationConfigForValidation = ({
metadataSchema: normalizeOptionalString(data.ducklakeMetadataSchema),
},
}
+ } else if (selectedType === 'Snowflake') {
+ return {
+ snowflake: {
+ accountId: normalizeRequiredString(data.snowflakeAccountId),
+ user: normalizeRequiredString(data.snowflakeUser),
+ privateKey: data.snowflakePrivateKey ?? '',
+ privateKeyPassphrase: normalizeOptionalUntrimmedString(data.snowflakePrivateKeyPassphrase),
+ database: normalizeRequiredString(data.snowflakeDatabase),
+ schema: normalizeRequiredString(data.snowflakeSchema),
+ role: normalizeOptionalString(data.snowflakeRole),
+ },
+ }
} else {
throw new Error('Invalid destination type')
}
@@ -256,6 +320,17 @@ export const buildDestinationConfig = async ({
metadataSchema: normalizeOptionalString(data.ducklakeMetadataSchema),
}
destinationConfig = { ducklake: ducklakeConfig }
+ } else if (selectedType === 'Snowflake') {
+ const snowflakeConfig: SnowflakeDestinationConfig = {
+ accountId: normalizeRequiredString(data.snowflakeAccountId),
+ user: normalizeRequiredString(data.snowflakeUser),
+ privateKey: data.snowflakePrivateKey ?? '',
+ privateKeyPassphrase: normalizeOptionalUntrimmedString(data.snowflakePrivateKeyPassphrase),
+ database: normalizeRequiredString(data.snowflakeDatabase),
+ schema: normalizeRequiredString(data.snowflakeSchema),
+ role: normalizeOptionalString(data.snowflakeRole),
+ }
+ destinationConfig = { snowflake: snowflakeConfig }
}
return destinationConfig
diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationPanelFields.tsx b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationPanelFields.tsx
index 55e5f478d8ca4..cf8b7b4bed4f1 100644
--- a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationPanelFields.tsx
+++ b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/DestinationPanelFields.tsx
@@ -345,6 +345,168 @@ export const DuckLakeFields = ({ form }: { form: UseFormReturn }) => {
+ const [showPrivateKeyPassphrase, setShowPrivateKeyPassphrase] = useState(false)
+
+ return (
+
+
Snowflake settings
+
+
+
Connection
+
+ Configure the Snowflake account, user, and target namespace for replicated data.
+