HIPAA-ready Snowflake data warehouse for healthcare analytics. Medallion architecture (Bronze/Silver/Gold) with Terraform IaC, dbt transformations, dynamic data masking, role-based access control, and Evidence dashboards. Uses Synthea synthetic patient data in FHIR format.
0
stars
27
commits
Python
primary language
Feb 10, 2026
updated
A production-ready Snowflake data warehouse architecture for healthcare analytics, demonstrating enterprise patterns including RBAC, dynamic data masking, and HIPAA-compliant data handling.
Built entirely with infrastructure-as-code (Terraform), version-controlled transformations (dbt), and code-based BI (Evidence).
This project demonstrates:
Healthcare technology companies needing scalable, secure analytics infrastructure.
Showcase Snowflake architecture skills for fractional consulting opportunities.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SNOWFLAKE DATA WAREHOUSE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ ββββββββββββββ β
β β RAW_DB β β STAGING_DB β β MARTS_DB β βANALYTICS_DBβ β
β β β β β β β β β β
β β ββββββββββ β β ββββββββββ β β ββββββββββ β β β β
β β βSYNTHEA β βββββΆβ βHEALTH β βββββΆβ β CORE β β β Secure β β
β β β Schema β β β β CARE β β β β Schema β β β Shares β β
β β ββββββββββ β β ββββββββββ β β ββββββββββ β β β β
β β β β β β ββββββββββ β β β β
β β Raw CSVs β β Cleaned & β β βANALYT β β β β β
β β from β β Standardizedβ β β ICS β β β β β
β β Synthea β β Data β β β Schema β β β β β
β β β β β β ββββββββββ β β β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ ββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β ROLE HIERARCHY ββ
β β ββ
β β ACCOUNTADMIN ββ
β β β ββ
β β SYSADMIN ββ
β β ββββββββββΌβββββββββ¬βββββββββββββ ββ
β β βΌ βΌ βΌ βΌ ββ
β β LOADER TRANS- ANALYST READER ββ
β β _ROLE FORMER _ROLE _ROLE ββ
β β _ROLE ββ
β β ββ
β β Write RAW Read RAW Read MARTS Read via ββ
β β Only Write all (masked) Data Share ββ
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β DYNAMIC DATA MASKING ββ
β β ββ
β β TRANSFORMER_ROLE sees: ANALYST_ROLE sees: ββ
β β SSN: 999-12-3456 SSN: ***-**-3456 ββ
β β Name: John Smith Name: J*** S*** ββ
β β DOB: 1985-03-15 DOB: 1985-01-01 (year only) ββ
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Component | Technology |
|---|---|
| Cloud Platform | Snowflake (Trial Account) |
| Infrastructure as Code | Terraform with snowflake-labs/snowflake provider |
| Authentication | RSA Key-Pair (no passwords) |
| Data Transformation | dbt-core 1.7.x with dbt-snowflake |
| Synthetic Data | Synthea (FHIR-compliant generator) |
| BI Layer | Evidence (code-based dashboards) |
| CI/CD | GitHub Actions |
Before you begin, ensure you have:
git clone https://github.com/yourusername/snowflake-healthtech-warehouse.git
cd snowflake-healthtech-warehouse
# Create directory for keys
mkdir -p ~/.snowflake
# Generate private key (PKCS8 format, no password)
openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out ~/.snowflake/rsa_key.p8 -nocrypt
# Generate public key
openssl rsa -in ~/.snowflake/rsa_key.p8 -pubout -out ~/.snowflake/rsa_key.pub
# View public key (you'll need this for Snowflake)
cat ~/.snowflake/rsa_key.pub
Log into Snowflake and run:
-- Replace 'your_user' with your actual username
-- Copy the public key content (without the BEGIN/END lines)
ALTER USER your_user SET RSA_PUBLIC_KEY='MIIBIjANBgkq...';
# Copy example environment file
cp .env.example .env
# Edit .env with your settings
nano .env # or use your preferred editor
Required settings:
SNOWFLAKE_ACCOUNT=xy12345.us-east-1 # Your account identifier
SNOWFLAKE_USER=your_username # Your username
SNOWFLAKE_PRIVATE_KEY_PATH=~/.snowflake/rsa_key.p8
./init.sh
This will:
cd terraform
terraform plan # Review changes
terraform apply # Deploy resources
# Generate synthetic patient data
./data/scripts/generate_synthea.sh
# Load data into Snowflake
python scripts/load_data.py
source venv/bin/activate
cd dbt
dbt deps # Install packages
dbt run # Run models
dbt test # Validate data
cd evidence
npm run dev
# Open http://localhost:3000
Run the comprehensive verification scripts to ensure everything is working:
source venv/bin/activate
# Verify all infrastructure was provisioned correctly
python scripts/verify_infrastructure.py
# Test RBAC permissions and data masking
python scripts/test_security.py
# Or run all tests at once
python scripts/run_all_tests.py
The security test demonstrates:
999-12-3456, Name John Smith, DOB 1985-03-15***-**-3456, Name J***, DOB 1985-01-01snowflake-healthtech-warehouse/
βββ .env.example # Environment template (COMMITTED)
βββ .env # Actual secrets (GITIGNORED)
βββ .gitignore # Comprehensive ignore rules
βββ requirements.txt # Python dependencies
βββ init.sh # Setup script
βββ README.md # This file
βββ AGENT_NOTES.md # Notes for AI agents
β
βββ terraform/ # Infrastructure as Code
β βββ main.tf # Root module
β βββ variables.tf # Input variables
β βββ outputs.tf # Output values
β βββ providers.tf # Snowflake provider
β βββ terraform.tfvars.example
β βββ modules/
β βββ databases/ # RAW, STAGING, MARTS, ANALYTICS
β βββ warehouses/ # LOADING, TRANSFORM, ANALYTICS
β βββ roles/ # LOADER, TRANSFORMER, ANALYST, READER
β βββ schemas/ # SYNTHEA, HEALTHCARE, CORE, ANALYTICS
β βββ stages/ # Internal stages for loading
β βββ security/ # Masking policies
β
βββ dbt/ # Data transformations
β βββ dbt_project.yml
β βββ profiles.yml.example
β βββ packages.yml
β βββ models/
β β βββ sources.yml # RAW_DB sources
β β βββ staging/ # 1:1 with source (views)
β β βββ intermediate/ # Business logic joins
β β βββ marts/ # Dimensional models (tables)
β β βββ core/ # dim_patient, fact_encounters
β β βββ analytics/ # Aggregated metrics
β βββ tests/
β βββ macros/
β βββ seeds/
β
βββ data/ # Data generation
β βββ synthea/
β β βββ csv/ # Generated patient data
β βββ scripts/
β βββ generate_synthea.sh
β
βββ scripts/ # Python utilities
β βββ load_data.py # CSV to Snowflake loader
β
βββ evidence/ # BI dashboards
β βββ package.json
β βββ evidence.config.yaml
β βββ sources/
β β βββ snowflake.yaml.example
β βββ pages/
β βββ index.md # Executive dashboard
β βββ patients.md # Demographics
β βββ encounters.md # Visit analytics
β βββ security-demo.md # Masking demonstration
β
βββ .github/workflows/ # CI/CD
β βββ terraform-plan.yml
β βββ terraform-apply.yml
β βββ dbt-run.yml
β
βββ docs/ # Documentation
βββ architecture.md
βββ security.md
βββ demo-script.md
| Role | Can Access | Cannot Access |
|---|---|---|
| LOADER_ROLE | Write to RAW_DB | Read STAGING, MARTS |
| TRANSFORMER_ROLE | Read RAW, Write STAGING/MARTS | N/A |
| ANALYST_ROLE | Read MARTS (masked) | Read RAW, STAGING |
| READER_ROLE | Read via Data Share | Direct database access |
Same query, different results based on role:
SELECT patient_id, ssn, first_name, last_name, date_of_birth
FROM marts_db.core.dim_patient
LIMIT 3;
As TRANSFORMER_ROLE:
| patient_id | ssn | first_name | last_name | date_of_birth |
|---|---|---|---|---|
| 1 | 999-12-3456 | John | Smith | 1985-03-15 |
| 2 | 888-34-5678 | Jane | Doe | 1990-07-22 |
As ANALYST_ROLE:
| patient_id | ssn | first_name | last_name | date_of_birth |
|---|---|---|---|---|
| 1 | *--3456 | J*** | S**** | 1985-01-01 |
| 2 | *--5678 | J*** | D** | 1990-01-01 |
The project includes GitHub Actions workflows for automated deployment.
Configure these secrets in your repository settings (Settings β Secrets and variables β Actions):
| Secret | Description | How to Get |
|---|---|---|
SNOWFLAKE_ACCOUNT | Snowflake account identifier | From your Snowflake URL (e.g., xy12345.us-east-1) |
SNOWFLAKE_USER | Snowflake username | Your Snowflake login username |
SNOWFLAKE_PRIVATE_KEY | RSA private key (full content) | Contents of ~/.snowflake/rsa_key.p8 |
# Copy the entire private key file content
cat ~/.snowflake/rsa_key.p8 | pbcopy # macOS
# Or manually copy the contents including BEGIN/END lines
Then paste as the SNOWFLAKE_PRIVATE_KEY secret value in GitHub.
| Workflow | Trigger | Purpose |
|---|---|---|
terraform-plan.yml | Pull Request | Preview infrastructure changes |
terraform-apply.yml | Push to main | Apply infrastructure changes |
dbt-run.yml | After terraform-apply | Run data transformations |
For production safety, configure an "environment" in GitHub:
productionA 5-7 minute video demonstration is available showing:
This is a portfolio project, but suggestions and feedback are welcome!
MIT License - See LICENSE for details.
Built as a demonstration of Snowflake architecture patterns for healthcare analytics.
Note: This project uses synthetic data generated by Synthea. No real patient information is included.
27 commits
Python
48.0%
HCL
40.5%
Shell
11.4%
HIPAA-ready Snowflake data warehouse for healthcare analytics. Medallion architecture (Bronze/Silver/Gold) with Terraform IaC, dbt transformations, dynamic data masking, role-based access control, and Evidence dashboards. Uses Synthea synthetic patient data in FHIR format.
0
stars
27
commits
Python
primary language
Feb 10, 2026
updated
A production-ready Snowflake data warehouse architecture for healthcare analytics, demonstrating enterprise patterns including RBAC, dynamic data masking, and HIPAA-compliant data handling.
Built entirely with infrastructure-as-code (Terraform), version-controlled transformations (dbt), and code-based BI (Evidence).
This project demonstrates:
Healthcare technology companies needing scalable, secure analytics infrastructure.
Showcase Snowflake architecture skills for fractional consulting opportunities.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SNOWFLAKE DATA WAREHOUSE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ ββββββββββββββ β
β β RAW_DB β β STAGING_DB β β MARTS_DB β βANALYTICS_DBβ β
β β β β β β β β β β
β β ββββββββββ β β ββββββββββ β β ββββββββββ β β β β
β β βSYNTHEA β βββββΆβ βHEALTH β βββββΆβ β CORE β β β Secure β β
β β β Schema β β β β CARE β β β β Schema β β β Shares β β
β β ββββββββββ β β ββββββββββ β β ββββββββββ β β β β
β β β β β β ββββββββββ β β β β
β β Raw CSVs β β Cleaned & β β βANALYT β β β β β
β β from β β Standardizedβ β β ICS β β β β β
β β Synthea β β Data β β β Schema β β β β β
β β β β β β ββββββββββ β β β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ ββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β ROLE HIERARCHY ββ
β β ββ
β β ACCOUNTADMIN ββ
β β β ββ
β β SYSADMIN ββ
β β ββββββββββΌβββββββββ¬βββββββββββββ ββ
β β βΌ βΌ βΌ βΌ ββ
β β LOADER TRANS- ANALYST READER ββ
β β _ROLE FORMER _ROLE _ROLE ββ
β β _ROLE ββ
β β ββ
β β Write RAW Read RAW Read MARTS Read via ββ
β β Only Write all (masked) Data Share ββ
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β DYNAMIC DATA MASKING ββ
β β ββ
β β TRANSFORMER_ROLE sees: ANALYST_ROLE sees: ββ
β β SSN: 999-12-3456 SSN: ***-**-3456 ββ
β β Name: John Smith Name: J*** S*** ββ
β β DOB: 1985-03-15 DOB: 1985-01-01 (year only) ββ
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Component | Technology |
|---|---|
| Cloud Platform | Snowflake (Trial Account) |
| Infrastructure as Code | Terraform with snowflake-labs/snowflake provider |
| Authentication | RSA Key-Pair (no passwords) |
| Data Transformation | dbt-core 1.7.x with dbt-snowflake |
| Synthetic Data | Synthea (FHIR-compliant generator) |
| BI Layer | Evidence (code-based dashboards) |
| CI/CD | GitHub Actions |
Before you begin, ensure you have:
git clone https://github.com/yourusername/snowflake-healthtech-warehouse.git
cd snowflake-healthtech-warehouse
# Create directory for keys
mkdir -p ~/.snowflake
# Generate private key (PKCS8 format, no password)
openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -out ~/.snowflake/rsa_key.p8 -nocrypt
# Generate public key
openssl rsa -in ~/.snowflake/rsa_key.p8 -pubout -out ~/.snowflake/rsa_key.pub
# View public key (you'll need this for Snowflake)
cat ~/.snowflake/rsa_key.pub
Log into Snowflake and run:
-- Replace 'your_user' with your actual username
-- Copy the public key content (without the BEGIN/END lines)
ALTER USER your_user SET RSA_PUBLIC_KEY='MIIBIjANBgkq...';
# Copy example environment file
cp .env.example .env
# Edit .env with your settings
nano .env # or use your preferred editor
Required settings:
SNOWFLAKE_ACCOUNT=xy12345.us-east-1 # Your account identifier
SNOWFLAKE_USER=your_username # Your username
SNOWFLAKE_PRIVATE_KEY_PATH=~/.snowflake/rsa_key.p8
./init.sh
This will:
cd terraform
terraform plan # Review changes
terraform apply # Deploy resources
# Generate synthetic patient data
./data/scripts/generate_synthea.sh
# Load data into Snowflake
python scripts/load_data.py
source venv/bin/activate
cd dbt
dbt deps # Install packages
dbt run # Run models
dbt test # Validate data
cd evidence
npm run dev
# Open http://localhost:3000
Run the comprehensive verification scripts to ensure everything is working:
source venv/bin/activate
# Verify all infrastructure was provisioned correctly
python scripts/verify_infrastructure.py
# Test RBAC permissions and data masking
python scripts/test_security.py
# Or run all tests at once
python scripts/run_all_tests.py
The security test demonstrates:
999-12-3456, Name John Smith, DOB 1985-03-15***-**-3456, Name J***, DOB 1985-01-01snowflake-healthtech-warehouse/
βββ .env.example # Environment template (COMMITTED)
βββ .env # Actual secrets (GITIGNORED)
βββ .gitignore # Comprehensive ignore rules
βββ requirements.txt # Python dependencies
βββ init.sh # Setup script
βββ README.md # This file
βββ AGENT_NOTES.md # Notes for AI agents
β
βββ terraform/ # Infrastructure as Code
β βββ main.tf # Root module
β βββ variables.tf # Input variables
β βββ outputs.tf # Output values
β βββ providers.tf # Snowflake provider
β βββ terraform.tfvars.example
β βββ modules/
β βββ databases/ # RAW, STAGING, MARTS, ANALYTICS
β βββ warehouses/ # LOADING, TRANSFORM, ANALYTICS
β βββ roles/ # LOADER, TRANSFORMER, ANALYST, READER
β βββ schemas/ # SYNTHEA, HEALTHCARE, CORE, ANALYTICS
β βββ stages/ # Internal stages for loading
β βββ security/ # Masking policies
β
βββ dbt/ # Data transformations
β βββ dbt_project.yml
β βββ profiles.yml.example
β βββ packages.yml
β βββ models/
β β βββ sources.yml # RAW_DB sources
β β βββ staging/ # 1:1 with source (views)
β β βββ intermediate/ # Business logic joins
β β βββ marts/ # Dimensional models (tables)
β β βββ core/ # dim_patient, fact_encounters
β β βββ analytics/ # Aggregated metrics
β βββ tests/
β βββ macros/
β βββ seeds/
β
βββ data/ # Data generation
β βββ synthea/
β β βββ csv/ # Generated patient data
β βββ scripts/
β βββ generate_synthea.sh
β
βββ scripts/ # Python utilities
β βββ load_data.py # CSV to Snowflake loader
β
βββ evidence/ # BI dashboards
β βββ package.json
β βββ evidence.config.yaml
β βββ sources/
β β βββ snowflake.yaml.example
β βββ pages/
β βββ index.md # Executive dashboard
β βββ patients.md # Demographics
β βββ encounters.md # Visit analytics
β βββ security-demo.md # Masking demonstration
β
βββ .github/workflows/ # CI/CD
β βββ terraform-plan.yml
β βββ terraform-apply.yml
β βββ dbt-run.yml
β
βββ docs/ # Documentation
βββ architecture.md
βββ security.md
βββ demo-script.md
| Role | Can Access | Cannot Access |
|---|---|---|
| LOADER_ROLE | Write to RAW_DB | Read STAGING, MARTS |
| TRANSFORMER_ROLE | Read RAW, Write STAGING/MARTS | N/A |
| ANALYST_ROLE | Read MARTS (masked) | Read RAW, STAGING |
| READER_ROLE | Read via Data Share | Direct database access |
Same query, different results based on role:
SELECT patient_id, ssn, first_name, last_name, date_of_birth
FROM marts_db.core.dim_patient
LIMIT 3;
As TRANSFORMER_ROLE:
| patient_id | ssn | first_name | last_name | date_of_birth |
|---|---|---|---|---|
| 1 | 999-12-3456 | John | Smith | 1985-03-15 |
| 2 | 888-34-5678 | Jane | Doe | 1990-07-22 |
As ANALYST_ROLE:
| patient_id | ssn | first_name | last_name | date_of_birth |
|---|---|---|---|---|
| 1 | *--3456 | J*** | S**** | 1985-01-01 |
| 2 | *--5678 | J*** | D** | 1990-01-01 |
The project includes GitHub Actions workflows for automated deployment.
Configure these secrets in your repository settings (Settings β Secrets and variables β Actions):
| Secret | Description | How to Get |
|---|---|---|
SNOWFLAKE_ACCOUNT | Snowflake account identifier | From your Snowflake URL (e.g., xy12345.us-east-1) |
SNOWFLAKE_USER | Snowflake username | Your Snowflake login username |
SNOWFLAKE_PRIVATE_KEY | RSA private key (full content) | Contents of ~/.snowflake/rsa_key.p8 |
# Copy the entire private key file content
cat ~/.snowflake/rsa_key.p8 | pbcopy # macOS
# Or manually copy the contents including BEGIN/END lines
Then paste as the SNOWFLAKE_PRIVATE_KEY secret value in GitHub.
| Workflow | Trigger | Purpose |
|---|---|---|
terraform-plan.yml | Pull Request | Preview infrastructure changes |
terraform-apply.yml | Push to main | Apply infrastructure changes |
dbt-run.yml | After terraform-apply | Run data transformations |
For production safety, configure an "environment" in GitHub:
productionA 5-7 minute video demonstration is available showing:
This is a portfolio project, but suggestions and feedback are welcome!
MIT License - See LICENSE for details.
Built as a demonstration of Snowflake architecture patterns for healthcare analytics.
Note: This project uses synthetic data generated by Synthea. No real patient information is included.
27 commits
Python
48.0%
HCL
40.5%
Shell
11.4%