# terraform-infra: Snowflake role + service user

Repo: `theorchard/terraform-infra`. Files (same two files regardless of
paradigm, one role block + one service_user block per environment):

- `prod/snowflake/delphi/roles/terraform.tfvars` — the `roles` variable
- `prod/snowflake/delphi/service_users/terraform.tfvars` — the `service_users` variable

## 1. Role block

Append to the `roles` list, once per environment:

```hcl
  {
    name = "{{SERVICE_USER}}"
    granted_account_roles = [
      "DEPLOY_WAREHOUSE_WAREHOUSE_ACCESS",
    ]
    granted_database_roles = [
      "{{ENV_DB_NAME}}.DB_READWRITE"
    ]
  },
```

`DEPLOY_WAREHOUSE_WAREHOUSE_ACCESS` in `granted_account_roles` is required on
every db-deploy role — that's what lets the service user use `DEPLOY_WAREHOUSE`.
`granted_database_roles` should reference `{{ENV_DB_NAME}}.DB_READWRITE` — the
per-environment database for paradigm B, or the single shared database for
paradigm A (grant scoped to that environment's role/schema if the database
itself supports schema-scoped roles — check how the existing paradigm-A
sibling's role block is written and follow the same pattern rather than
assuming `DB_READWRITE` applies unscoped).

## 2. Service user block

Append to the `service_users` map, once per environment:

```hcl
  "{{SERVICE_USER}}" = {
    default_role   = "{{SERVICE_USER}}"
    default_wh     = "DEPLOY_WAREHOUSE"
    rsa_public_key = "{{RSA_PUBLIC_KEY_BODY}}"
    roles = [
      "{{SERVICE_USER}}",
    ]
    comment = "Service user for database deployments to the {{ENV_DB_NAME}} database."
  }
```

Don't set a `team` field on the service user — it's not part of this block.

`rsa_public_key` is the *body* of that environment's `rsa_key.pub` — PEM
header/footer and newlines stripped into one line. Get it with the bundled
script rather than doing it by hand:

```
scripts/extract_public_key.sh path/to/rsa_key.pub
```

(`${CLAUDE_PLUGIN_ROOT}/skills/onboard-snowflake-database/scripts/extract_public_key.sh`
when invoked from within the skill.)

Never paste the *private* key (`rsa_key.p8`) anywhere in this repo or in any
chat output — only the public key goes into Terraform.

## 3. Open the PR

One PR covering all the role + service-user blocks for this onboarding (both
environments if multi-env). Get explicit user confirmation before pushing the
branch or opening the PR — see the confirmation gates in the main SKILL.md.

Open this PR **in parallel with** the database-repo PR (`references/database-repo.md`
step 5), not before or after it — they're independent files in independent
repos, so there's no reason to serialize the two. There **is** an ordering
requirement before running the Jenkins deploy job later: this PR must be
**merged and applied** (the service user/role must actually exist in
Snowflake) before `db-deploy-pipeline` is run for any environment, or the
connection-check changeset will fail with an authentication/authorization
error. Confirm apply status with the user before proceeding to the Jenkins
step — don't assume merge implies apply.
