Secrets Management - TVL Platform
Status: Active Operational Guide Tool: Doppler (Cloud-based secrets management) SOC 2: Type II Certified Last Updated: 2025-10-25
Overview
This document outlines how the TVL Platform manages sensitive configuration (secrets) across all environments using Doppler.
Secrets include:
- Database connection strings
- API keys (Stripe, Hostaway, Airbnb, etc.)
- OAuth client secrets
- Webhook signing secrets
- Service account credentials
Why Doppler?
| Requirement | Manual .env | Doppler | 
|---|---|---|
| Team Onboarding | 30 min (manual sharing) | 5 min (invite to workspace) | 
| Secret Rotation | 2 hours (update everywhere) | 10 min (update once, auto-sync) | 
| Audit Trail | ❌ None | ✅ Yes (who accessed what when) | 
| SOC 2 Compliance | ❌ Manual documentation | ✅ Built-in audit logs | 
| Cost (5 users) | $0 | $0 (free tier) | 
| Maintenance | Manual | Zero (fully managed) | 
Decision: Doppler provides enterprise-grade secrets management at zero cost for our team size.
Architecture
Environment Structure
tvl-platform/ (Doppler project)
├── development (local dev)
│   ├── DATABASE_ENVIRONMENT=local
│   ├── DATABASE_URL=postgresql://localhost:5432/tvl_dev
│   └── NODE_ENV=development
│
├── integration (Supabase dev)
│   ├── DATABASE_ENVIRONMENT=supabase-dev
│   ├── DATABASE_URL=postgresql://supabase-dev...
│   ├── SUPABASE_URL=https://[dev-ref].supabase.co
│   ├── SUPABASE_ANON_KEY=eyJh...
│   └── NODE_ENV=development
│
├── staging (Supabase staging)
│   ├── DATABASE_ENVIRONMENT=supabase-staging
│   ├── DATABASE_URL=postgresql://supabase-staging...
│   ├── SUPABASE_URL=https://[staging-ref].supabase.co
│   ├── STRIPE_SECRET_KEY=sk_test_... (test mode)
│   └── NODE_ENV=staging
│
└── production (Supabase production)
    ├── DATABASE_ENVIRONMENT=supabase-production
    ├── DATABASE_URL=postgresql://supabase-prod...
    ├── SUPABASE_URL=https://[prod-ref].supabase.co
    ├── STRIPE_SECRET_KEY=sk_live_... (live mode)
    └── NODE_ENV=production
Access Control
| Role | Development | Integration | Staging | Production | 
|---|---|---|---|---|
| Developer | Read/Write | Read/Write | Read | ❌ No Access | 
| Tech Lead | Read/Write | Read/Write | Read/Write | Read | 
| DevOps | Read/Write | Read/Write | Read/Write | Read/Write | 
| CI/CD (Service Token) | ❌ No Access | Read | Read | Read | 
Principle: Developers never have write access to production secrets.
Secrets Inventory
Database Credentials
| Secret | Environments | Rotation Frequency | Owner | 
|---|---|---|---|
| DATABASE_URL | All | Quarterly | DevOps | 
| DATABASE_TEST_URL | Development | Quarterly | DevOps | 
| POSTGRES_USER | Development | Quarterly | DevOps | 
| POSTGRES_PASSWORD | Development | Quarterly | DevOps | 
Supabase Credentials
| Secret | Environments | Rotation Frequency | Owner | 
|---|---|---|---|
| SUPABASE_URL | Integration, Staging, Production | Never (project URL) | DevOps | 
| SUPABASE_ANON_KEY | Integration, Staging, Production | Quarterly | DevOps | 
| SUPABASE_SERVICE_ROLE_KEY | Integration, Staging, Production | Quarterly | DevOps | 
Payment Processing (V1.0+)
| Secret | Environments | Rotation Frequency | Owner | 
|---|---|---|---|
| STRIPE_PUBLISHABLE_KEY | All | Rarely (public key) | Tech Lead | 
| STRIPE_SECRET_KEY | All | Quarterly | Tech Lead | 
| STRIPE_WEBHOOK_SECRET | All | When compromised | Tech Lead | 
Integration Partners
| Secret | Environments | Rotation Frequency | Owner | 
|---|---|---|---|
| HOSTAWAY_CLIENT_ID | All | Rarely | Tech Lead | 
| HOSTAWAY_CLIENT_SECRET | All | When team member leaves | Tech Lead | 
| AIRBNB_WEBHOOK_SECRET | All | When team member leaves | Tech Lead | 
| VRBO_API_KEY | All | Quarterly | Tech Lead | 
Development Tools
| Secret | Environments | Rotation Frequency | Owner | 
|---|---|---|---|
| LINEAR_API_KEY | Shared (all envs) | When team member leaves | Tech Lead | 
| GITHUB_TOKEN | CI/CD only | Annually | DevOps | 
Total: ~25 secrets across 4 environments = 100 secret values
Developer Workflows
Onboarding New Developer
Time: 5 minutes
# 1. Tech lead invites developer to Doppler
# https://dashboard.doppler.com/workplace/[workplace]/members
# Click "Invite Member" → Enter email → Assign to "Developer" role
# 2. Developer receives email, accepts invite
# 3. Developer installs Doppler CLI
brew install dopplerhq/cli/doppler
# 4. Developer authenticates
doppler login
# 5. Developer selects project
cd the-villa-life
doppler setup
# Choose: tvl-platform → development
# 6. Developer syncs secrets
doppler secrets download --no-file --format env > .env.local
# 7. Developer opens devcontainer
# F1 → Dev Containers: Reopen in Container
# ✅ Done! Developer has all secrets
Daily Development
No manual steps required.
Secrets automatically loaded from .env.local:
# 1. Open VS Code
code .
# 2. Reopen in Container
# F1 → Dev Containers: Reopen in Container
# 3. Start coding
# ✅ Secrets available in environment
Switching Environments
Example: Switch from local to Supabase dev integration
# 1. Select environment
doppler setup
# Choose: tvl-platform → integration
# 2. Download secrets
doppler secrets download --no-file --format env > .env.local
# 3. Rebuild container
# F1 → Dev Containers: Rebuild Container
# ✅ Now using Supabase dev environment
Operational Procedures
Quarterly Secret Rotation
Frequency: Every 3 months Owner: DevOps Time: 30 minutes
Checklist:
- 
Generate new credentials: - Supabase: Reset project service role key
- Stripe: Generate new secret key (test + live)
- Database: Change PostgreSQL role passwords
 
- 
Update Doppler (all environments): # Development
 doppler secrets set DATABASE_URL="postgresql://service_role:NEW_PASSWORD@..." --config development
 # Integration
 doppler secrets set SUPABASE_SERVICE_ROLE_KEY="NEW_KEY" --config integration
 # Staging
 doppler secrets set STRIPE_SECRET_KEY="sk_test_NEW_KEY" --config staging
 # Production
 doppler secrets set STRIPE_SECRET_KEY="sk_live_NEW_KEY" --config production
- 
Notify team (Slack #engineering): 🔐 Quarterly secret rotation completed.
 Action required: Update your local secrets
 1. Run: doppler secrets download > .env.local
 2. Rebuild container: F1 → Dev Containers: Rebuild
 If issues, see: docs/operations/secrets-management.md
- 
Update CI/CD service tokens (if needed): -  Regenerate GitHub Actions DOPPLER_TOKEN_STAGING
- Update GitHub repository secrets
 
-  Regenerate GitHub Actions 
- 
Audit access logs: - Review Doppler audit logs (last 90 days)
- Check for unauthorized access
- Document any anomalies
 
Team Member Offboarding
When: Developer leaves team Owner: Tech Lead Time: 20 minutes
Checklist:
- 
Revoke Doppler access: - Login to https://dashboard.doppler.com
- Navigate to Workplace → Members
- Find user → Click "..." → "Remove Member"
 
- 
Rotate sensitive secrets: -  LINEAR_API_KEY(shared across team)
-  HOSTAWAY_CLIENT_SECRET(integration access)
- Any secrets the developer had write access to
 
-  
- 
Update Doppler: doppler secrets set LINEAR_API_KEY="NEW_KEY" --config development
 doppler secrets set HOSTAWAY_CLIENT_SECRET="NEW_SECRET" --config production
- 
Notify team: 🔐 Secrets rotated due to team change.
 Run: doppler secrets download > .env.local && rebuild container
- 
Revoke other access: - GitHub organization membership
- Supabase dashboard access
- Linear workspace access
- AWS/GCP console (if applicable)
 
- 
Audit: - Review Doppler logs for departed member's last access
- Verify no API keys created by departed member
- Document in security log
 
Emergency: Compromised Secret
When: Secret suspected or confirmed leaked Owner: Tech Lead (escalate to DevOps if production) Time: 10 minutes
Example: STRIPE_SECRET_KEY accidentally committed to GitHub
Immediate Actions:
- 
Revoke compromised secret (< 2 minutes): # Stripe example:
 # 1. Login to Stripe dashboard
 # 2. Developers → API Keys → "..." → Revoke
 # 3. Generate new key
- 
Update Doppler (< 1 minute): doppler secrets set STRIPE_SECRET_KEY="sk_live_NEW_KEY" --config production
- 
Notify team (Slack #engineering-alerts): 🚨 SECURITY ALERT: Stripe secret key compromised
 Status: ✅ Revoked and rotated
 Impact: Production API calls may fail for ~5 minutes
 Action required (all devs):
 1. Run: doppler secrets download > .env.local
 2. Rebuild container
 Incident: INC-2025-001
- 
Force redeploy services (< 5 minutes): # Production backend (uses new key)
 kubectl rollout restart deployment/backend -n production
 # Production frontend (may need new publishable key)
 kubectl rollout restart deployment/frontend -n production
- 
Post-incident: - Review Stripe audit logs (identify unauthorized charges)
- Check Doppler logs (who accessed secret before compromise)
- Update GitHub to detect secrets in commits (git-secrets, pre-commit hooks)
- Document incident in security log
- Schedule post-mortem (if significant impact)
 
Audit & Compliance
Monthly Audit Review
Owner: Tech Lead Time: 30 minutes
Checklist:
- 
Review Doppler audit logs: - Login to https://dashboard.doppler.com
- Navigate to Workplace → Audit
- Filter last 30 days
-  Check for:
- ✅ Production secret access (should be rare)
- ✅ Unusual access times (after hours)
- ✅ Failed authentication attempts
- ✅ Bulk secret downloads
 
 
- 
Anomaly investigation: Example findings:
 - Developer A accessed production secrets at 2am
 → Action: Ask Developer A (legitimate? debugging prod issue?)
 - Unknown IP accessed staging
 → Action: Check if VPN IP, escalate to DevOps
 - Service token used from new region
 → Action: Verify CI/CD runner, check GitHub Actions logs
- 
Document findings: -  Create audit report in docs/operations/audit-logs/2025-10.md
- Note any action items
- Review with team in monthly security meeting
 
-  Create audit report in 
SOC 2 Compliance
Requirement: Demonstrate secure secrets management
Evidence provided by Doppler:
- 
Access Controls (CC6.1) - ✅ Role-based access (Developer, Tech Lead, DevOps)
- ✅ Production secrets restricted to Tech Lead + DevOps only
- ✅ Audit logs show who accessed what secret when
 
- 
Encryption (CC6.7) - ✅ Secrets encrypted at rest (AES-256)
- ✅ Secrets encrypted in transit (TLS 1.3)
- ✅ Doppler SOC 2 Type II report available
 
- 
Audit Logging (CC7.2) - ✅ All secret access logged
- ✅ 30-day retention (free tier), 1-year (team tier)
- ✅ Logs immutable (cannot be deleted)
 
- 
Incident Response (CC7.3) - ✅ Documented procedure (this doc: Emergency section)
- ✅ Fast rotation capability (10 minutes)
- ✅ Notification workflow (Slack alerts)
 
For SOC 2 audit:
- Provide Doppler SOC 2 Type II report
- Demonstrate quarterly rotation schedule
- Show audit log review process (monthly)
- Document offboarding procedure (this doc)
Backup & Disaster Recovery
Doppler Outage (Unlikely)
Doppler SLA: 99.9% uptime (Team tier)
Mitigation:
- 
Local cache (automatic): # Doppler CLI caches secrets locally
 ls ~/.doppler/cache/
 # Even if Doppler is down, cached secrets work
- 
Emergency fallback (.env.local): # .env.local already contains latest secrets
 # Container works normally during Doppler outage
 # ✅ No action needed
- 
If .env.local deleted: # 1. Use Doppler cache (if available)
 doppler secrets --fallback-readonly
 # 2. Contact team member for .env.local copy
 # 3. Or wait for Doppler to restore (typically < 1 hour)
Secrets Backup
Frequency: Weekly (automated) Owner: DevOps Storage: 1Password (encrypted team vault)
Process:
# Export all environments (weekly cron job)
doppler secrets download --no-file --format env --config development > backup-development.env
doppler secrets download --no-file --format env --config integration > backup-integration.env
doppler secrets download --no-file --format env --config staging > backup-staging.env
doppler secrets download --no-file --format env --config production > backup-production.env
# Encrypt backups
gpg --encrypt --recipient devops@thevillalife.com backup-*.env
# Upload to 1Password team vault
# Folder: "Doppler Backups" → Item: "2025-10-25"
# Delete local copies
rm backup-*.env backup-*.env.gpg
Restore process (if Doppler data loss):
- Download encrypted backup from 1Password
- Decrypt: gpg --decrypt backup-production.env.gpg > production.env
- Re-import to Doppler: doppler secrets upload production.env --config production
Cost Management
Current State (Free Tier)
| Metric | Limit | Usage | Status | 
|---|---|---|---|
| Users | 5 | 3 | ✅ Under limit | 
| Secrets | Unlimited | ~100 | ✅ OK | 
| Environments | Unlimited | 4 | ✅ OK | 
| Projects | Unlimited | 1 | ✅ OK | 
Cost: $0/month
Future (Team Tier)
When: Team grows past 5 users
| Metric | Cost | Notes | 
|---|---|---|
| Base | $12/user/month | Unlimited everything | 
| 10 users | $120/month | = $1,440/year | 
| 20 users | $240/month | = $2,880/year | 
ROI Analysis:
| Cost Type | Manual | Doppler Team (10 users) | 
|---|---|---|
| Time savings | $1,500/year | Saved (automated) | 
| Doppler subscription | $0 | $1,440/year | 
| Net Cost | $1,500/year | $1,440/year | 
Breakeven: Doppler pays for itself via time savings, even at Team tier.
Migration Plan (If Needed)
Scenario: Migrating to Infisical (Self-Hosted)
When: Team > 15 users, Doppler cost > self-hosted cost
Timeline: 1 week
Steps:
- 
Export from Doppler: doppler secrets download --no-file --format json > secrets-export.json
- 
Deploy Infisical: - Deploy Docker Compose/Kubernetes
- Configure backups
- Setup SSL/TLS
 
- 
Import to Infisical: infisical import secrets-export.json
- 
Update team: - Install Infisical CLI
- Re-authenticate
- Test sync
 
- 
Cutover: - Switch CI/CD to Infisical tokens
- Archive Doppler account (keep for 1 month)
 
Estimated cost: 40 hours DevOps time = $4,000 one-time
Summary
Current Setup:
- ✅ Doppler (free tier) for all secrets
- ✅ 4 environments (development, integration, staging, production)
- ✅ ~100 secret values managed
- ✅ SOC 2 Type II certified (helps achieve compliance)
Key Workflows:
- Onboarding: 5 minutes (vs 30 minutes manual)
- Rotation: 10 minutes (vs 2 hours manual)
- Offboarding: 20 minutes (revoke + rotate)
- Emergency: 10 minutes (revoke + redeploy)
Compliance:
- ✅ Quarterly rotation schedule
- ✅ Monthly audit log review
- ✅ Offboarding procedure documented
- ✅ Emergency response plan
Next Steps:
- ✅ Setup Doppler account (Tech Lead)
- ✅ Add all secrets to Doppler
- ✅ Invite team members
- ✅ Test rotation workflow
- ✅ Schedule quarterly rotation reminder
Last Updated: 2025-10-25 Owner: Tech Lead Review Frequency: Quarterly (or when significant changes)