From dp
Assign a Snowflake role to a user in ImagineLearning/DataPlatformSnowflakeTerraform. Encodes the user.tf + role_grants.tf edit convention, valid role list, branch/PR format, and the new-vs-existing-user rules. Used by /dp:assign-role.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dp:assign-roleThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Encodes how the IL Data Platform team grants a Snowflake role to a user via Terraform. Users are provisioned through Okta SSO, but their Snowflake attributes and role grants are managed declaratively in `ImagineLearning/DataPlatformSnowflakeTerraform`. Granting a role = a two-file edit + a PR.
Encodes how the IL Data Platform team grants a Snowflake role to a user via Terraform. Users are provisioned through Okta SSO, but their Snowflake attributes and role grants are managed declaratively in ImagineLearning/DataPlatformSnowflakeTerraform. Granting a role = a two-file edit + a PR.
This skill is the convention source. The /dp:assign-role command drives the workflow (pull → branch → edit → plan → confirm → push → PR) using these rules.
snowflake_role definitions) — that's a different change, not a grant.src/role_grants.tf (add the user to the role's users list) and — only if the user isn't already declared — src/user.tf (add a snowflake_user resource).DP-XXXX ticket appears in the branch name, the PR title, the commit message, AND the inline # DP-XXXX comment on each added line. No ticket → stop and ask.references/valid-roles.md) before editing. Terraform does NOT validate role names — a typo fails at terraform apply in CI, after merge. Catch it here.terraform plan output if available) first. Role grants are access-control changes.@edgenuity/DataPlatform CODEOWNERS review. Open it and stop.[OK], [WARN], [FAIL]).ImagineLearning/DataPlatformSnowflakeTerraform (remote may be edgenuity/DataPlatformSnowflakeTerraform — use the configured origin).master.src/user.tf — one resource "snowflake_user" "<id>" block per user.src/role_grants.tf — one resource "snowflake_role_grants" "<role>" block per role; the users = [...] list is what grants the role.* @edgenuity/DataPlatform — every PR needs their review.terraform plan on the PR and terraform apply on merge to master. No local apply needed.The repo path comes from the user (via --repo-path) or is discovered: look for a local clone of DataPlatformSnowflakeTerraform. If none is found, stop and ask the user for the path.
first.last@imaginelearning.com → resource id first_last (lowercase, dots → underscores, drop the domain).
megan.heine@imaginelearning.com → megan_heinejacob.dygico@imaginelearning.com → jacob_dygicoIf two people would collide on the same id, the repo uses a suffix like _il (e.g. ambily_varghese_il). Check src/user.tf for an existing block before assuming a new id is free.
Search src/user.tf for resource "snowflake_user" "<id>":
user.tf change needed. Go to Step C.# resource "snowflake_user" "<id>" or appear only as commented lines in role_grants.tf) — uncomment the full block in user.tf. Go to Step C.src/user.tf (new users only)Exact format (match the existing file's indentation — 4 spaces, aligned =):
# DP-XXXX: <First Last>
resource "snowflake_user" "<id>" {
default_role = snowflake_role.<default_role>.name
default_warehouse = snowflake_warehouse.analyst_wh.name
disabled = false
display_name = "<First Last>"
email = "<email>"
first_name = "<First>"
last_name = "<Last>"
login_name = "<EMAIL-UPPERCASE>"
name = "<EMAIL-UPPERCASE>"
}
default_role — for a brand-new user whose first/only role is the one being granted, set it to snowflake_role.<role>.name. If the user is being added a secondary role and already has a default, do not change their default.default_warehouse — snowflake_warehouse.analyst_wh.name is the common default for viewer/analyst roles. If unsure, match what similar users in the file use; do not invent a warehouse name.login_name / name — the email, uppercased (e.g. MEGAN.HEINE@IMAGINELEARNING.COM).src/role_grants.tfFind resource "snowflake_role_grants" "<role>". Inside its users = [ ... ] list, add:
snowflake_user.<id>.name, # DP-XXXX: <First Last>
# snowflake_user.<id>.name, # DP-NNNN: Pending ...), uncomment that line and update its trailing comment to the current ticket rather than adding a duplicate.The authoritative list is the set of snowflake_role_grants resource names in src/role_grants.tf. A snapshot is in references/valid-roles.md — read it to validate the requested role. If the requested role isn't in the snapshot, re-derive the live list:
grep -oP 'resource "snowflake_role_grants" "\K[^"]+' src/role_grants.tf | sort
Match case-insensitively (DATA_ENGINEER → data_engineer). If no match, stop with [FAIL] Role '<x>' not found. Valid roles: <closest matches>.
DP-XXXX-grant-<role>-to-<id> (e.g. DP-3549-grant-core_viewer-to-megan_heine). The repo also has historical feature/DP-XXXX-... branches; the bare DP-XXXX-... form is fine.DP-XXXX: Grant <ROLE> for <First Last> (multiple users: list them).@edgenuity/DataPlatform via CODEOWNERS — don't add reviewers manually.| Case | Handling |
|---|---|
| User already active with the role | No-op. Tell the user the grant already exists; don't open an empty PR. |
| User commented-out as "Pending" | Uncomment in both files; update the trailing comment to the current ticket. |
| New user, unknown default warehouse | Use analyst_wh for viewer/analyst roles; otherwise match a peer in user.tf. Never invent a warehouse. |
| Multiple roles in one request | One branch/PR; add the user to each role's block; set default_role to the primary one only. |
| Role name typo | Caught by the valid-roles check. Terraform won't catch it until CI apply. |
Email not @imaginelearning.com | Service accounts use svc_* ids and may differ. For a human grant, confirm the domain with the user before proceeding. |
| Working tree dirty | Stop. Don't switch branches over uncommitted work. |
terraform not installed locally | Skip the plan step; note it. CI will plan on the PR. |
DP-\d+). Derive the user id.--repo-path or discover a local DataPlatformSnowflakeTerraform clone. Confirm it's a git repo with a clean working tree.git fetch origin master && git checkout master && git reset --hard origin/master.git checkout -b DP-XXXX-grant-<role>-to-<id>.user.tf if the user wasn't already active.terraform is on PATH and src/ initializes, run terraform plan in src/ and capture output. Skip gracefully if not.git diff and the plan summary. AskUserQuestion to confirm before any push.src/user.tf + src/role_grants.tf; commit with the convention message; git push -u origin <branch>.gh pr create (or GitHub MCP) with the title convention and a body summarizing the grant + ticket. Print the PR URL. Stop — do not merge.| Need | Skill |
|---|---|
| Understand DataPlatformSnowflake dbt conventions | dp:dbt, dp:dbt-fix-conventions |
| Publish a fix summary to Confluence | dp:publish-ticket-confluence |
| Generic code generation from a Jira ticket | il:generate-code (this skill can be loaded by it when paths touch DataPlatformSnowflakeTerraform) |
npx claudepluginhub imaginelearning/dp-claude-plugin --plugin dpProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Searches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.