Skip to main content

TVL Platform - API Key & Token Rotation Runbook

Summary

This runbook provides comprehensive procedures for rotating API keys, tokens, and credentials for all external services integrated with the TVL platform. Includes rotation schedules, step-by-step procedures, emergency rotation, and validation steps.

Table of Contents


Rotation Schedule

Regular Rotation Schedule

ServiceRotation FrequencyLast RotationNext RotationOwner
Stripe API KeysEvery 90 days2025-07-242025-10-24Platform Team
Hostaway API KeysEvery 90 days2025-08-152025-11-15Integrations Team
Google OAuth Client SecretEvery 180 days2025-04-012025-10-01Platform Team
SendGrid API KeysEvery 90 days2025-08-012025-11-01Platform Team
AWS S3 Access KeysEvery 90 days2025-07-102025-10-10Platform Team
Supabase Service KeysEvery 180 days2025-05-012025-11-01Platform Team
Redis PasswordsEvery 180 days2025-06-012025-12-01Platform Team
JWT Signing KeysEvery 365 days2025-01-012026-01-01Security Team

Rotation Triggers

Scheduled Rotation:

  • 30 days before expiration: Create rotation ticket
  • 7 days before expiration: Send reminder notification
  • Day of expiration: Execute rotation
  • 1 day after rotation: Verify and monitor

Emergency Rotation (within 4 hours):

  • Key exposure detected (leaked in logs, GitHub, etc.)
  • Unauthorized access detected
  • Service compromise suspected
  • Compliance audit requirement
  • Employee offboarding with key access

Pre-Rotation Checklist

Planning

  • Rotation ticket created in Linear
  • Rotation scheduled during low-traffic window (10am-2pm EST weekday)
  • On-call engineer notified and available
  • Deployment freeze confirmed (no other deployments scheduled)
  • Backup of current secrets documented

Preparation

  • New key/credential generated (where applicable)
  • Access to secret management systems confirmed:
    • Railway/Fly dashboard
    • Vercel dashboard
    • AWS Secrets Manager (if used)
    • 1Password/HashiCorp Vault (if used)
  • Rollback plan documented
  • Communication plan ready (#engineering-ops channel)

Validation

  • Current services operational (no ongoing incidents)
  • Monitoring dashboards green
  • Recent backups confirmed
  • Test environment rotation completed successfully

Service Rotation Procedures

Stripe API Keys

Service: Payment processing Key Type: Secret API keys (sk_live_xxx) Rotation Frequency: Every 90 days Downtime Risk: High (payments will fail if misconfigured)

Procedure

Step 1: Generate New API Key

# 1. Login to Stripe Dashboard
# https://dashboard.stripe.com/test/apikeys (staging)
# https://dashboard.stripe.com/apikeys (production)

# 2. Click "Create secret key"
# Name: "TVL API Key - 2025-10-24"
# Description: "Backend API server key, rotated 2025-10-24"

# 3. Copy new key (shown only once)
NEW_STRIPE_KEY="sk_live_xxxxxxxxxxxxx"

# 4. Store in secure location temporarily
echo $NEW_STRIPE_KEY > /tmp/stripe_key_new.txt
chmod 600 /tmp/stripe_key_new.txt

Step 2: Update Staging Environment

# Update Railway/Fly staging environment
railway variables set STRIPE_SECRET_KEY=$NEW_STRIPE_KEY --environment staging

# Verify staging
curl -X POST https://api.staging.tvl.app/api/v1/payment-intents \
-H "Authorization: Bearer <test-token>" \
-H "Content-Type: application/json" \
-d '{
"amount": 100,
"currency": "usd",
"booking_id": "<test-booking-id>"
}'

# Expected: Payment intent created successfully

Step 3: Update Production Environment

# Backup current key
OLD_STRIPE_KEY=$(railway variables get STRIPE_SECRET_KEY --environment production)
echo $OLD_STRIPE_KEY > /tmp/stripe_key_old.txt

# Update production
railway variables set STRIPE_SECRET_KEY=$NEW_STRIPE_KEY --environment production

# Restart services (automatic in most cases)
railway restart --environment production

Step 4: Verify Production

# Wait 30 seconds for services to restart
sleep 30

# Health check
curl https://api.tvl.com/health | jq '.checks.stripe'
# Expected: "healthy"

# Test payment intent creation (use test booking)
# (Run smoke test script)
./scripts/smoke-test-payments.sh

Step 5: Monitor and Cleanup

# Monitor for 30 minutes
# - Check Sentry for payment errors
# - Check Grafana for payment success rate
# - Check Stripe webhook delivery

# If all successful, revoke old key
# Stripe Dashboard → API Keys → Reveal old key → Delete

# Clean up temporary files
rm /tmp/stripe_key_new.txt /tmp/stripe_key_old.txt

# Update rotation tracking
# Linear: Mark ticket complete
# Update rotation schedule spreadsheet

Rollback Procedure:

# If issues detected within 30 minutes
railway variables set STRIPE_SECRET_KEY=$OLD_STRIPE_KEY --environment production
railway restart --environment production

# Verify rollback
curl https://api.tvl.com/health | jq '.checks.stripe'

Hostaway API Keys

Service: PMS connector (property sync) Key Type: API Key + Account ID Rotation Frequency: Every 90 days Downtime Risk: Medium (sync delays, no immediate customer impact)

Procedure

Step 1: Generate New API Key

# 1. Login to Hostaway Dashboard
# https://dashboard.hostaway.com/api-keys

# 2. Create new API key
# Name: "TVL Integration - 2025-10-24"
# Permissions: Read/Write for Properties, Bookings, Calendars

# 3. Copy new key
NEW_HOSTAWAY_KEY="ha_xxxxxxxxxxxxx"
HOSTAWAY_ACCOUNT_ID="12345"

# 4. Store securely
echo $NEW_HOSTAWAY_KEY > /tmp/hostaway_key_new.txt
chmod 600 /tmp/hostaway_key_new.txt

Step 2: Update Staging

# Update environment variables
railway variables set HOSTAWAY_API_KEY=$NEW_HOSTAWAY_KEY --environment staging
railway variables set HOSTAWAY_ACCOUNT_ID=$HOSTAWAY_ACCOUNT_ID --environment staging

# Test connection
curl -X GET "https://api.hostaway.com/v1/properties" \
-H "Authorization: Bearer $NEW_HOSTAWAY_KEY" \
-H "X-Account-Id: $HOSTAWAY_ACCOUNT_ID"

# Expected: 200 OK with properties list

Step 3: Update Production

# Backup old key
OLD_HOSTAWAY_KEY=$(railway variables get HOSTAWAY_API_KEY --environment production)

# Update production
railway variables set HOSTAWAY_API_KEY=$NEW_HOSTAWAY_KEY --environment production

# Restart workers (sync workers use this key)
railway restart sync-worker --environment production

Step 4: Verify Sync Jobs

# Check sync worker logs
railway logs sync-worker --follow --environment production

# Verify sync jobs processing
redis-cli -u $REDIS_URL
> LLEN bull:sync-availability-job:active
> LLEN bull:sync-availability-job:failed

# Expected: Active jobs > 0, failed = 0

# Test manual sync
curl -X POST https://api.tvl.com/api/v1/connectors/hostaway/sync \
-H "Authorization: Bearer <admin-token>" \
-d '{"property_id": "<test-property-id>"}'

Step 5: Revoke Old Key

# After 1 hour of successful operation
# Hostaway Dashboard → API Keys → Delete old key

# Clean up
rm /tmp/hostaway_key_new.txt

# Update documentation
# Update connector configuration documentation

Google OAuth Credentials

Service: User authentication (Google OIDC) Key Type: Client ID + Client Secret Rotation Frequency: Every 180 days Downtime Risk: Critical (all user logins will fail)

Procedure

Step 1: Generate New OAuth Client

# 1. Go to Google Cloud Console
# https://console.cloud.google.com/apis/credentials

# 2. Select TVL Production project

# 3. Create new OAuth 2.0 Client ID
# Application type: Web application
# Name: "TVL Platform - 2025-10-24"
# Authorized redirect URIs:
# - https://app.tvl.com/auth/callback
# - https://api.tvl.com/auth/google/callback

# 4. Copy credentials
NEW_GOOGLE_CLIENT_ID="xxxxx.apps.googleusercontent.com"
NEW_GOOGLE_CLIENT_SECRET="GOCSPX-xxxxxxxxxxxxx"

# 5. Store securely
echo "CLIENT_ID=$NEW_GOOGLE_CLIENT_ID" > /tmp/google_oauth_new.txt
echo "CLIENT_SECRET=$NEW_GOOGLE_CLIENT_SECRET" >> /tmp/google_oauth_new.txt
chmod 600 /tmp/google_oauth_new.txt

Step 2: Update Supabase Auth Configuration

# 1. Login to Supabase Dashboard
# https://app.supabase.com/project/<project-id>/auth/providers

# 2. Navigate to: Authentication → Providers → Google

# 3. Update credentials:
# - Client ID: <NEW_GOOGLE_CLIENT_ID>
# - Client Secret: <NEW_GOOGLE_CLIENT_SECRET>

# 4. Click "Save"

# IMPORTANT: Keep old credentials active temporarily
# Google allows multiple OAuth clients simultaneously

Step 3: Update Frontend Environment Variables

# Update Vercel environment variables
vercel env add VITE_GOOGLE_CLIENT_ID production
# Paste: <NEW_GOOGLE_CLIENT_ID>

# Trigger redeployment
vercel --prod

# Wait for deployment
vercel inspect <deployment-url>

Step 4: Test Authentication

# Test login flow (manual testing required)
# 1. Open incognito browser window
# 2. Navigate to https://app.tvl.com
# 3. Click "Sign in with Google"
# 4. Complete OAuth flow
# 5. Verify successful login

# Check Supabase logs
# Supabase Dashboard → Logs → Auth logs
# Verify successful authentication events

Step 5: Revoke Old OAuth Client

# After 24 hours of successful operation
# Google Cloud Console → Credentials → Delete old OAuth client

# Clean up
rm /tmp/google_oauth_new.txt

# Update documentation

Rollback Procedure:

# If authentication fails:
# 1. Revert Supabase provider configuration to old credentials
# 2. Revert Vercel environment variable
# 3. Trigger frontend redeployment
# 4. Verify login works with old credentials

SendGrid API Keys

Service: Transactional email delivery Key Type: API Key Rotation Frequency: Every 90 days Downtime Risk: Medium (emails will fail to send)

Procedure

Step 1: Generate New API Key

# 1. Login to SendGrid Dashboard
# https://app.sendgrid.com/settings/api_keys

# 2. Create API Key
# Name: "TVL Platform - 2025-10-24"
# Permissions: Full Access (Mail Send)

# 3. Copy key (shown only once)
NEW_SENDGRID_KEY="SG.xxxxxxxxxxxxx"

echo $NEW_SENDGRID_KEY > /tmp/sendgrid_key_new.txt
chmod 600 /tmp/sendgrid_key_new.txt

Step 2: Update Environment Variables

# Update staging
railway variables set SENDGRID_API_KEY=$NEW_SENDGRID_KEY --environment staging

# Test email sending
curl -X POST https://api.staging.tvl.app/api/v1/test/send-email \
-H "Authorization: Bearer <admin-token>" \
-d '{
"to": "test@tvl.com",
"subject": "Test email - rotation validation",
"body": "If you receive this, SendGrid rotation successful"
}'

# Check email received
# Check SendGrid activity logs

# Update production
OLD_SENDGRID_KEY=$(railway variables get SENDGRID_API_KEY --environment production)
railway variables set SENDGRID_API_KEY=$NEW_SENDGRID_KEY --environment production

# Restart notification worker
railway restart notification-worker --environment production

Step 3: Verify Email Delivery

# Monitor notification worker logs
railway logs notification-worker --follow --environment production

# Send test email via production
# (Use admin panel to trigger test notification)

# Verify in SendGrid Dashboard
# Activity → Email Activity
# Check for successful deliveries with new API key

Step 4: Revoke Old Key

# After 1 hour of successful operation
# SendGrid Dashboard → API Keys → Delete old key

rm /tmp/sendgrid_key_new.txt

AWS S3 Access Keys

Service: Media storage (property images, documents) Key Type: Access Key ID + Secret Access Key Rotation Frequency: Every 90 days Downtime Risk: Medium (media uploads/downloads will fail)

Procedure

Step 1: Generate New Access Key

# 1. Login to AWS Console
# https://console.aws.amazon.com/iam/home#/users/tvl-platform-user

# 2. Select user: tvl-platform-user

# 3. Security credentials tab → Access keys → Create access key

# 4. Copy credentials
NEW_AWS_ACCESS_KEY_ID="AKIA..."
NEW_AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxx"

echo "AWS_ACCESS_KEY_ID=$NEW_AWS_ACCESS_KEY_ID" > /tmp/aws_keys_new.txt
echo "AWS_SECRET_ACCESS_KEY=$NEW_AWS_SECRET_ACCESS_KEY" >> /tmp/aws_keys_new.txt
chmod 600 /tmp/aws_keys_new.txt

Step 2: Update Environment Variables

# Update staging
railway variables set AWS_ACCESS_KEY_ID=$NEW_AWS_ACCESS_KEY_ID --environment staging
railway variables set AWS_SECRET_ACCESS_KEY=$NEW_AWS_SECRET_ACCESS_KEY --environment staging

# Test S3 access
aws s3 ls s3://tvl-staging-media --region us-east-1

# Update production
railway variables set AWS_ACCESS_KEY_ID=$NEW_AWS_ACCESS_KEY_ID --environment production
railway variables set AWS_SECRET_ACCESS_KEY=$NEW_AWS_SECRET_ACCESS_KEY --environment production

railway restart --environment production

Step 3: Verify S3 Operations

# Test upload
curl -X POST https://api.tvl.com/api/v1/properties/<property-id>/media \
-H "Authorization: Bearer <test-token>" \
-F "file=@test-image.jpg"

# Expected: 200 OK with media URL

# Test download
curl -I <returned-media-url>
# Expected: 200 OK

Step 4: Deactivate Old Key

# After 1 hour of successful operation
# AWS Console → IAM → Users → tvl-platform-user → Security credentials
# → Deactivate old access key
# (Keep deactivated for 24 hours before deleting)

# After 24 hours: Delete old access key

rm /tmp/aws_keys_new.txt

Supabase Service Keys

Service: Database access, admin operations Key Type: Service Role Key (JWT) Rotation Frequency: Every 180 days Downtime Risk: Critical (database operations will fail)

Procedure

Step 1: Generate New Service Key

# 1. Login to Supabase Dashboard
# https://app.supabase.com/project/<project-id>/settings/api

# 2. Navigate to: Settings → API

# 3. Click "Reset service_role key"
# WARNING: This invalidates the old key immediately

# 4. Copy new service_role key
NEW_SUPABASE_SERVICE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

echo $NEW_SUPABASE_SERVICE_KEY > /tmp/supabase_key_new.txt
chmod 600 /tmp/supabase_key_new.txt

Step 2: Update Environment Variables Immediately

# CRITICAL: Must update immediately as old key is now invalid

# Update staging
railway variables set SUPABASE_SERVICE_KEY=$NEW_SUPABASE_SERVICE_KEY --environment staging
railway restart --environment staging

# Verify staging works
curl https://api.staging.tvl.app/health | jq '.checks.database'
# Expected: "healthy"

# Update production
OLD_SUPABASE_KEY=$(railway variables get SUPABASE_SERVICE_KEY --environment production)
railway variables set SUPABASE_SERVICE_KEY=$NEW_SUPABASE_SERVICE_KEY --environment production
railway restart --environment production

Step 3: Verify Database Operations

# Health check
curl https://api.tvl.com/health | jq '.checks.database'

# Test database query
curl -X GET https://api.tvl.com/api/v1/properties \
-H "Authorization: Bearer <test-token>"

# Check Supabase logs
# Supabase Dashboard → Logs → Postgres logs
# Verify no authentication errors

Step 4: Update Backup Scripts

# Update any scripts using service key
# Example: backup scripts, migration scripts, admin tools

# Update .env.production file
sed -i "s/SUPABASE_SERVICE_KEY=.*/SUPABASE_SERVICE_KEY=$NEW_SUPABASE_SERVICE_KEY/" .env.production

# Commit changes (encrypted)
git add .env.production.encrypted
git commit -m "chore: Rotate Supabase service key"
git push

Note: Supabase service key rotation is immediate and cannot be rolled back. Plan accordingly.


Redis Passwords

Service: Cache, job queue, session storage Key Type: Redis password Rotation Frequency: Every 180 days Downtime Risk: Critical (all caching and jobs will fail)

Procedure

Step 1: Generate New Password in Upstash

# 1. Login to Upstash Console
# https://console.upstash.com/redis/<database-id>

# 2. Navigate to: Details → Security

# 3. Click "Reset Password"
# Upstash will provide new connection string

# 4. Copy new Redis URL
NEW_REDIS_URL="rediss://default:xxxxxxxxxxxxx@us1-example.upstash.io:6379"

echo $NEW_REDIS_URL > /tmp/redis_url_new.txt
chmod 600 /tmp/redis_url_new.txt

Step 2: Update Staging

# Update staging environment
railway variables set REDIS_URL=$NEW_REDIS_URL --environment staging
railway restart --environment staging

# Wait for services to reconnect
sleep 30

# Test Redis connection
redis-cli -u $NEW_REDIS_URL ping
# Expected: PONG

# Test cache operations
curl https://api.staging.tvl.app/health | jq '.checks.redis'
# Expected: "healthy"

Step 3: Update Production (Zero-Downtime)

# Upstash supports both old and new passwords for a grace period
# Update production environment
OLD_REDIS_URL=$(railway variables get REDIS_URL --environment production)
railway variables set REDIS_URL=$NEW_REDIS_URL --environment production

# Restart services one by one (rolling restart)
railway restart web --environment production
sleep 30
railway restart sync-worker --environment production
sleep 30
railway restart payment-worker --environment production
sleep 30
railway restart notification-worker --environment production

Step 4: Verify All Services

# Health check
curl https://api.tvl.com/health | jq '.checks.redis'

# Check job processing
redis-cli -u $NEW_REDIS_URL
> INFO stats
> LLEN bull:sync-worker:active
> LLEN bull:sync-worker:failed

# Monitor for 30 minutes
# - Check Grafana for Redis connection errors
# - Check Sentry for cache errors
# - Verify job processing rates normal

Step 5: Finalize Rotation

# After 1 hour, old password is automatically invalidated by Upstash

rm /tmp/redis_url_new.txt

# Update documentation

Emergency Rotation

Immediate Response (Key Compromise)

Timeline: Complete rotation within 4 hours

Step 1: Assess Impact (0-15 minutes)

# Identify compromised key
COMPROMISED_SERVICE="<service-name>" # e.g., "stripe", "hostaway"

# Check for unauthorized usage
# - Review service logs (Stripe dashboard, AWS CloudTrail, etc.)
# - Check for unusual API calls
# - Verify data access patterns

# Create incident ticket
gh issue create \
--title "[SECURITY] Emergency key rotation - $COMPROMISED_SERVICE" \
--label "security,incident,p0" \
--body "Key compromise detected. Initiating emergency rotation."

Step 2: Disable Compromised Key (15-30 minutes)

# Immediately disable/revoke old key in service provider dashboard
# (Service-specific, see procedures above)

# Examples:
# - Stripe: Dashboard → API Keys → Delete key
# - AWS: IAM → Users → Deactivate access key
# - Google OAuth: Cloud Console → Credentials → Delete OAuth client

# Verify key revoked
# Test old key returns 401 Unauthorized

Step 3: Generate and Deploy New Key (30-90 minutes)

# Follow standard rotation procedure for service (see above)
# Accelerate timeline:
# - Skip staging testing (deploy directly to production)
# - Monitor closely during and after deployment

# Immediate deployment
railway variables set ${SERVICE}_KEY=$NEW_KEY --environment production
railway restart --environment production

# Verify immediately
./scripts/verify-deployment.sh

Step 4: Investigate and Contain (90-240 minutes)

# Identify compromise source
# - Check git history for leaked keys
# - Review log files for exposed credentials
# - Scan codebase for hardcoded secrets
# - Review recent deployments

# Remediation actions
# - Remove leaked secrets from Git history (git filter-branch or BFG)
# - Rotate all related credentials
# - Update security policies
# - Add secret scanning to CI/CD

# Example: Remove secrets from Git
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch .env" \
--prune-empty --tag-name-filter cat -- --all

git push --force --all

Step 5: Post-Incident (After 4 hours)

# Create post-mortem
# - Root cause analysis
# - Timeline of events
# - Remediation actions taken
# - Preventive measures

# Update runbooks and procedures
# Conduct security training
# Implement automated secret detection (e.g., GitGuardian, TruffleHog)

Post-Rotation Verification

Verification Checklist

Immediate (within 15 minutes):

  • Health check endpoint returns healthy status
  • Service-specific functionality tested
  • No errors in Sentry
  • No failed jobs in queue
  • External service connectivity verified

Short-term (within 1 hour):

  • Monitor error rates (should be < 1%)
  • Check Grafana for anomalies
  • Verify scheduled jobs running
  • Test end-to-end user flows
  • Check customer support channels

Long-term (within 24 hours):

  • Review error trends
  • Verify data consistency
  • Update rotation tracking spreadsheet
  • Document any issues encountered
  • Update runbook with improvements

Automated Verification Script

#!/bin/bash
# scripts/verify-key-rotation.sh

SERVICE=$1 # e.g., "stripe", "hostaway", "sendgrid"
API_URL="https://api.tvl.com"

echo "=== Verifying $SERVICE Key Rotation ==="

case $SERVICE in
stripe)
echo "Testing Stripe connectivity..."
RESPONSE=$(curl -s $API_URL/health | jq -r '.checks.stripe')
if [ "$RESPONSE" = "healthy" ]; then
echo "✓ Stripe: OK"
else
echo "✗ Stripe: FAILED"
exit 1
fi
;;

hostaway)
echo "Testing Hostaway connectivity..."
RESPONSE=$(curl -s $API_URL/health | jq -r '.checks.hostaway')
if [ "$RESPONSE" = "healthy" ]; then
echo "✓ Hostaway: OK"
else
echo "✗ Hostaway: FAILED"
exit 1
fi
;;

sendgrid)
echo "Testing SendGrid connectivity..."
# Send test email
curl -X POST $API_URL/api/v1/test/send-email \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{
"to": "ops@tvl.com",
"subject": "SendGrid rotation test",
"body": "Key rotation successful"
}'
echo "✓ SendGrid: Test email sent"
;;

*)
echo "Unknown service: $SERVICE"
exit 1
;;
esac

echo ""
echo "✓ Rotation verification complete"

Incident Response

Key Exposure Scenarios

Scenario 1: Key Leaked in Git Repository

# 1. Revoke key immediately (see Emergency Rotation)

# 2. Remove from Git history
bfg --replace-text secrets.txt # Create secrets.txt with exposed key
git reflog expire --expire=now --all
git gc --prune=now --aggressive

# 3. Force push (coordinate with team)
git push --force --all

# 4. Rotate key
# (Follow standard rotation procedure)

Scenario 2: Key Exposed in Logs

# 1. Identify exposure scope
# - Which log files?
# - Which time range?
# - Who has access to logs?

# 2. Revoke key immediately

# 3. Redact from logs
# Railway: Cannot delete logs, rotate immediately
# CloudWatch: Delete log streams (if applicable)

# 4. Update logging configuration to mask secrets
# Example: Add secret masking to logger

Scenario 3: Unauthorized API Usage Detected

# 1. Review service audit logs
# Stripe: Dashboard → Logs → API logs
# AWS: CloudTrail → Event history

# 2. Identify unauthorized calls
# - Source IP addresses
# - API endpoints called
# - Time range

# 3. Revoke key immediately

# 4. Implement IP allowlisting (if supported)
# AWS: Add IP restrictions to IAM policy
# Stripe: Use IP allowlists for restricted keys

# 5. Alert security team

Escalation

SeverityResponse TimeEscalation Path
P0 - Key actively exploitedImmediateSecurity Team → CTO → Legal
P1 - Key exposed but no exploitation4 hoursPlatform Team → Security Team
P2 - Scheduled rotation overdue24 hoursPlatform Team

Communication Templates

Key Exposure Notification:

Subject: [SECURITY] API Key Rotation Required - <Service>

Team,

We have detected potential exposure of our <Service> API key.

Impact: <brief description>
Timeline: Rotation in progress, completion ETA <time>
Action Required: None (ops team handling)

Status updates will be posted to #incidents.

On-call: <name>

Sources

  • /mnt/c/GitHub/claude-test/docs/01-architecture/deployment-views.md
  • /mnt/c/GitHub/claude-test/docs/00-overview/platform-overview.md
  • Security best practices (OWASP, NIST)