<!-- Cogny documentation. Canonical page: https://cogny.com/docs/security-privacy-best-practices -->

# Security and Privacy Best Practices

Comprehensive guide to security and privacy best practices when using Cogny, including data encryption, access controls, compliance, and secure integration patterns.

**Author:** Cogny Team  
**Published:** 2025-02-15  
**Updated:** 2026-10-05  
**Canonical:** https://cogny.com/docs/security-privacy-best-practices

## Overview

Cogny is built with security and privacy as foundational principles. This guide covers best practices for maintaining data security, ensuring privacy compliance, and implementing secure integration patterns.

## Data Security

### Encryption

**Data at Rest:**
- **Algorithm:** AES-256-GCM encryption
- **Key Management:** AWS KMS with automatic key rotation
- **Scope:** All stored data, including credentials, reports, and user data

**Data in Transit:**
- **Protocol:** TLS 1.3 (minimum TLS 1.2)
- **Certificates:** 256-bit SSL certificates
- **All connections:** API, web interface, and database connections

**Service Account Credentials:**
```python
# Example: Securely store BigQuery credentials
import json
from cryptography.fernet import Fernet

def encrypt_credentials(credentials_json, encryption_key):
    """Encrypt service account credentials"""
    f = Fernet(encryption_key)
    encrypted = f.encrypt(credentials_json.encode())
    return encrypted

def decrypt_credentials(encrypted_data, encryption_key):
    """Decrypt service account credentials"""
    f = Fernet(encryption_key)
    decrypted = f.decrypt(encrypted_data)
    return json.loads(decrypted)

# Never store plaintext credentials
# Always use encrypted storage or secret managers
```

### Access Control

**Principle of Least Privilege:**

BigQuery service account permissions:
```bash
# ✅ Good: Read-only access
roles/bigquery.dataViewer
roles/bigquery.jobUser
roles/bigquery.metadataViewer

# ❌ Bad: Excessive permissions
roles/bigquery.admin
roles/editor
```

Google Ads API permissions:
```bash
# ✅ Good: Read-only scope
https://www.googleapis.com/auth/adwords

# ❌ Bad: Excessive scope
https://www.googleapis.com/auth/cloud-platform
```

**Role-Based Access Control (RBAC):**

| Role | Permissions | Use Case |
|------|-------------|----------|
| **Viewer** | Read reports, view tickets | Stakeholders, executives |
| **Analyst** | Create reports, manage tickets | Growth team, analysts |
| **Admin** | All permissions + integrations | Technical leads |
| **Owner** | All permissions + billing | Account owners |

### API Security

**API Key Management:**

```bash
# Rotate API keys every 90 days
curl -X POST https://api.cogny.com/v1/api-keys/rotate \
  -H "Authorization: Bearer sk_live_abc123xyz789" \
  -H "Content-Type: application/json" \
  -d '{"key_id": "key_xyz123"}'
```

**IP Allowlisting (Enterprise):**

```bash
# Configure IP allowlist
curl -X POST https://api.cogny.com/v1/security/ip-allowlist \
  -H "Authorization: Bearer sk_live_abc123xyz789" \
  -H "Content-Type: application/json" \
  -d '{
    "allowed_ips": [
      "203.0.113.0/24",
      "198.51.100.42"
    ],
    "enabled": true
  }'
```

**Request Signing (Enterprise):**

```python
import hmac
import hashlib
import time

def sign_request(payload, api_secret):
    """Sign API request for additional security"""
    timestamp = str(int(time.time()))
    message = f"{timestamp}.{payload}"

    signature = hmac.new(
        api_secret.encode(),
        message.encode(),
        hashlib.sha256
    ).hexdigest()

    return {
        'X-Cogny-Signature': signature,
        'X-Cogny-Timestamp': timestamp
    }

# Include in API requests
headers = sign_request(json.dumps(payload), API_SECRET)
headers['Authorization'] = f'Bearer {API_KEY}'
```

### Audit Logging

All actions are logged for security auditing:

**Logged Events:**
- User authentication (login, logout, failed attempts)
- API key creation, rotation, deletion
- Data warehouse connections
- Report generation
- Configuration changes
- Data exports

**Access Audit Logs:**

```bash
# Via API
curl -X GET "https://api.cogny.com/v1/audit-logs?limit=100&event_type=authentication" \
  -H "Authorization: Bearer sk_live_abc123xyz789"
```

**Example Audit Log Entry:**

```json
{
  "id": "log_abc123",
  "timestamp": "2025-02-15T10:30:00Z",
  "event_type": "warehouse.connected",
  "user_id": "user_456",
  "user_email": "analyst@company.com",
  "ip_address": "203.0.113.42",
  "user_agent": "Mozilla/5.0...",
  "resource_type": "warehouse",
  "resource_id": "wh_123abc",
  "action": "create",
  "metadata": {
    "warehouse_type": "bigquery",
    "project_id": "company-analytics"
  }
}
```

## Privacy Compliance

### GDPR Compliance

**Data Subject Rights:**

1. **Right to Access:**
   ```bash
   # Export user data
   curl -X POST https://api.cogny.com/v1/privacy/data-export \
     -H "Authorization: Bearer sk_live_abc123xyz789" \
     -d '{"user_id": "user_456"}'
   ```

2. **Right to Erasure:**
   ```bash
   # Delete user data
   curl -X DELETE https://api.cogny.com/v1/privacy/user-data \
     -H "Authorization: Bearer sk_live_abc123xyz789" \
     -d '{"user_id": "user_456", "reason": "user_request"}'
   ```

3. **Right to Data Portability:**
   ```bash
   # Export in machine-readable format
   curl -X POST https://api.cogny.com/v1/privacy/data-export \
     -H "Authorization: Bearer sk_live_abc123xyz789" \
     -d '{"user_id": "user_456", "format": "json"}'
   ```

**Data Processing Agreement (DPA):**
- Available for Enterprise customers
- Defines data processing terms
- Outlines security measures
- Specifies data retention policies

### PII Protection

**Automatic PII Detection:**

Cogny automatically detects and handles PII:

```sql
-- PII detection in queries
SELECT
  REGEXP_CONTAINS(email, r'[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}') as is_email,
  REGEXP_CONTAINS(phone, r'\d{3}-\d{3}-\d{4}') as is_phone,
  -- Masked in reports unless explicitly enabled
FROM sensitive_table
```

**PII Masking:**

```python
# Configure PII masking
curl -X PATCH https://api.cogny.com/v1/warehouses/wh_123abc/settings \
  -H "Authorization: Bearer sk_live_abc123xyz789" \
  -d '{
    "pii_protection": {
      "enabled": true,
      "mask_emails": true,
      "mask_ip_addresses": true,
      "mask_phone_numbers": true,
      "mask_names": false
    }
  }'
```

**Anonymization:**

```sql
-- Anonymize user identifiers
SELECT
  TO_BASE64(SHA256(user_id)) as anonymized_user_id,
  DATE_TRUNC(signup_date, MONTH) as signup_month,  -- Date generalization
  CASE
    WHEN age < 25 THEN '18-24'
    WHEN age < 35 THEN '25-34'
    WHEN age < 45 THEN '35-44'
    ELSE '45+'
  END as age_bracket  -- Age binning
FROM users
```

### Cookie Consent

For GA4 data collection:

```javascript
// Example: Cookie consent integration
window.gtag('consent', 'default', {
  'analytics_storage': 'denied',
  'ad_storage': 'denied'
});

// After user consent
window.gtag('consent', 'update', {
  'analytics_storage': 'granted',
  'ad_storage': 'granted'
});
```

### Data Retention

**Configurable Retention Policies:**

```bash
# Set retention policy
curl -X PATCH https://api.cogny.com/v1/warehouses/wh_123abc/retention \
  -H "Authorization: Bearer sk_live_abc123xyz789" \
  -d '{
    "reports": "90_days",
    "audit_logs": "1_year",
    "raw_data": "do_not_store"
  }'
```

**Retention Options:**
- `30_days` - 30 days
- `90_days` - 90 days (default)
- `1_year` - 1 year
- `2_years` - 2 years
- `indefinite` - No automatic deletion
- `do_not_store` - Don't store raw data

**Automatic Deletion:**

```sql
-- Scheduled deletion of old data
DELETE FROM reports
WHERE created_at < TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)
  AND retention_policy = '90_days'
```

## Network Security

### VPC Integration (Enterprise)

Connect to BigQuery via private networking:

```bash
# Configure VPC peering
gcloud compute networks peerings create cogny-peer \
    --network=your-vpc-network \
    --peer-project=cogny-production \
    --peer-network=cogny-vpc
```

**Benefits:**
- Traffic doesn't traverse public internet
- Additional layer of security
- Meets compliance requirements
- Lower latency

### Private Service Connect

For advanced security:

```bash
# Create Private Service Connect endpoint
gcloud compute addresses create cogny-psc-endpoint \
    --global \
    --purpose=PRIVATE_SERVICE_CONNECT \
    --addresses=10.0.0.5 \
    --network=your-vpc-network

gcloud compute forwarding-rules create cogny-psc-rule \
    --global \
    --network=your-vpc-network \
    --address=cogny-psc-endpoint \
    --target-service-attachment=projects/cogny-production/serviceAttachments/cogny-api
```

### Firewall Rules

Restrict BigQuery access:

```bash
# Allow only Cogny IP ranges
gcloud compute firewall-rules create allow-cogny-bigquery \
    --direction=INGRESS \
    --priority=1000 \
    --network=your-vpc-network \
    --action=ALLOW \
    --rules=tcp:443 \
    --source-ranges=35.184.0.0/16,35.185.0.0/16 \
    --target-tags=bigquery
```

## Secure Integration Patterns

### Service Account Best Practices

**1. Dedicated Service Accounts:**

```bash
# Create separate service accounts per environment
gcloud iam service-accounts create cogny-production
gcloud iam service-accounts create cogny-staging
gcloud iam service-accounts create cogny-development
```

**2. Key Rotation:**

```bash
# Rotate keys every 90 days
# Create new key
gcloud iam service-accounts keys create new-key.json \
    --iam-account=cogny-production@project.iam.gserviceaccount.com

# Update in Cogny
# Delete old key
gcloud iam service-accounts keys delete KEY_ID \
    --iam-account=cogny-production@project.iam.gserviceaccount.com
```

**3. Key Lifecycle Management:**

```python
from datetime import datetime, timedelta
from google.cloud import iam

def check_key_age(service_account_email):
    """Check if service account keys need rotation"""
    client = iam.IAMCredentialsClient()

    keys = client.list_service_account_keys(
        name=f"projects/-/serviceAccounts/{service_account_email}"
    )

    for key in keys:
        age = datetime.now() - key.valid_after_time
        if age > timedelta(days=90):
            print(f"Key {key.name} is {age.days} days old. Rotation recommended.")
```

### OAuth Token Management

**Secure Token Storage:**

```python
import os
from google.oauth2.credentials import Credentials

# Store in environment variables or secret manager
refresh_token = os.environ.get('GOOGLE_ADS_REFRESH_TOKEN')

# Never hardcode tokens
# ❌ Bad
refresh_token = "1//abc123xyz..."

# ✅ Good
refresh_token = os.environ.get('GOOGLE_ADS_REFRESH_TOKEN')
```

**Token Refresh:**

```python
from google.auth.transport.requests import Request

def refresh_oauth_token(credentials):
    """Refresh expired OAuth token"""
    if credentials.expired:
        credentials.refresh(Request())
    return credentials
```

### Webhook Security

**Verify Webhook Signatures:**

```python
import hmac
import hashlib

def verify_webhook_signature(payload, signature, secret):
    """Verify webhook authenticity"""
    expected_signature = hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()

    # Use constant-time comparison
    return hmac.compare_digest(signature, expected_signature)

# In webhook handler
@app.route('/webhook/cogny', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Cogny-Signature')
    payload = request.data.decode()

    if not verify_webhook_signature(payload, signature, WEBHOOK_SECRET):
        return jsonify({'error': 'Invalid signature'}), 401

    # Process webhook
    data = json.loads(payload)
    # ...
```

**Webhook Endpoint Security:**

```python
# Use HTTPS only
# Implement rate limiting
from flask_limiter import Limiter

limiter = Limiter(
    app,
    default_limits=["100 per hour"]
)

@app.route('/webhook/cogny', methods=['POST'])
@limiter.limit("10 per minute")
def handle_webhook():
    # Handle webhook
    pass
```

## Compliance Frameworks

### SOC 2 Type II

Cogny is SOC 2 Type II compliant:
- Annual audits by independent auditors
- Continuous monitoring of security controls
- Report available upon request (Enterprise)

### ISO 27001

Security management system certified to ISO 27001:
- Information security policies
- Risk assessment procedures
- Incident response protocols

### GDPR

Full GDPR compliance:
- DPA available for customers
- Data processing records maintained
- Privacy by design principles
- Data subject rights support

### CCPA

California Consumer Privacy Act compliance:
- Consumer rights support
- Data deletion workflows
- Privacy policy transparency

## Incident Response

### Security Incident Reporting

Report security concerns:
- **Email:** security@cogny.com
- **Response Time:** Within 24 hours
- **PGP Key:** Available at cogny.com/security

### Incident Response Process

1. **Detection:** Automated monitoring and user reports
2. **Assessment:** Severity evaluation and impact analysis
3. **Containment:** Immediate actions to limit impact
4. **Remediation:** Fix vulnerabilities and restore service
5. **Notification:** Communicate with affected users (if required)
6. **Post-Mortem:** Root cause analysis and prevention measures

### Vulnerability Disclosure

Responsible disclosure program:
- Email: security@cogny.com
- Response SLA: 48 hours
- Recognition: Security hall of fame
- Bounty: Available for critical vulnerabilities

## Monitoring and Alerting

### Security Monitoring

Continuous monitoring for:
- Failed authentication attempts
- Unusual API activity
- Permission changes
- Data access patterns
- Query anomalies

### Alerting

Configure security alerts:

```bash
# API: Configure alerting
curl -X POST https://api.cogny.com/v1/security/alerts \
  -H "Authorization: Bearer sk_live_abc123xyz789" \
  -d '{
    "alert_type": "unusual_activity",
    "conditions": {
      "failed_logins_threshold": 5,
      "time_window_minutes": 15
    },
    "notification": {
      "email": ["security@company.com"],
      "slack_webhook": "https://hooks.slack.com/..."
    }
  }'
```

## Best Practices Checklist

### Initial Setup

- [ ] Use read-only BigQuery service account
- [ ] Enable 2FA for all Cogny user accounts
- [ ] Configure PII protection settings
- [ ] Set appropriate data retention policies
- [ ] Review and accept Data Processing Agreement
- [ ] Configure audit log retention

### Ongoing Maintenance

- [ ] Rotate API keys every 90 days
- [ ] Rotate service account keys every 90 days
- [ ] Review user permissions quarterly
- [ ] Monitor audit logs for unusual activity
- [ ] Keep OAuth credentials up to date
- [ ] Review and update IP allowlists

### Integration Security

- [ ] Never commit credentials to version control
- [ ] Use environment variables for secrets
- [ ] Implement webhook signature verification
- [ ] Use HTTPS for all API communications
- [ ] Implement request timeouts
- [ ] Handle errors securely (don't expose details)

## Support

### Security Questions
- **Email:** security@cogny.com
- **Documentation:** docs.cogny.com/security

### General Support
- **Email:** support@cogny.com
- **Response Time:** 24 hours (Standard), 4 hours (Enterprise)

## Next Steps

- [Connect Your Data Sources](/docs/connect-your-data-sources) - Your BigQuery warehouse, the GA4 and Search Console links, and Bring Your Own Data
- [Integration Catalog and Setup Guides](/docs/integration-catalog-and-setup-guides) - Every integration, how it connects, and the setup notes
- [API Authentication](/docs/api-overview-authentication) - API security best practices

## Resources

- **Security Portal:** [cogny.com/security](https://cogny.com/security)
- **Privacy Policy:** [cogny.com/privacy](https://cogny.com/privacy)
- **Terms of Service:** [cogny.com/terms](https://cogny.com/terms)
- **Status Page:** [status.cogny.com](https://status.cogny.com)

---

Source page: https://cogny.com/docs/security-privacy-best-practices  
All documentation: https://cogny.com/docs  
Cogny for agents: https://cogny.com/llms.txt
