# Credentials & Security Schema

**MSP Mode Database Schema - Security Tables**

**Status:** Designed 2026-01-15
**Database:** msp_tracking (MariaDB on Jupiter)

---

## Overview

The Credentials & Security subsystem provides encrypted credential storage, comprehensive audit logging, security incident tracking, and granular access control for MSP work. All sensitive data is encrypted at rest using AES-256-GCM.

**Related Documentation:**
- [MSP-MODE-SPEC.md](../MSP-MODE-SPEC.md) - Full system specification
- [ARCHITECTURE_OVERVIEW.md](ARCHITECTURE_OVERVIEW.md) - System architecture
- [API_SPEC.md](API_SPEC.md) - API endpoints for credential access
- [SCHEMA_CONTEXT.md](SCHEMA_CONTEXT.md) - Learning and context tables

---

## Tables Summary

| Table | Purpose | Encryption |
|-------|---------|------------|
| `credentials` | Encrypted credential storage | AES-256-GCM |
| `credential_audit_log` | Comprehensive access audit trail | No (metadata only) |
| `security_incidents` | Security event tracking | No |
| `credential_permissions` | Granular access control (future multi-user) | No |

**Total:** 4 tables

---

## Table Schemas

### `credentials`

Encrypted credential storage for client infrastructure, services, and integrations. All sensitive fields encrypted at rest with AES-256-GCM.

```sql
CREATE TABLE credentials (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    client_id UUID REFERENCES clients(id) ON DELETE CASCADE,
    service_id UUID REFERENCES services(id) ON DELETE CASCADE,
    infrastructure_id UUID REFERENCES infrastructure(id) ON DELETE CASCADE,

    -- Credential type and metadata
    credential_type VARCHAR(50) NOT NULL CHECK(credential_type IN (
        'password', 'api_key', 'oauth', 'ssh_key',
        'shared_secret', 'jwt', 'connection_string', 'certificate'
    )),
    service_name VARCHAR(255) NOT NULL, -- "Gitea Admin", "AD2 sysadmin"
    username VARCHAR(255),

    -- Encrypted sensitive data (AES-256-GCM)
    password_encrypted BYTEA,
    api_key_encrypted BYTEA,
    client_secret_encrypted BYTEA,
    token_encrypted BYTEA,
    connection_string_encrypted BYTEA,

    -- OAuth-specific fields
    client_id_oauth VARCHAR(255),
    tenant_id_oauth VARCHAR(255),

    -- SSH key storage
    public_key TEXT,

    -- Service-specific
    integration_code VARCHAR(255), -- for services like Autotask

    -- Access metadata
    external_url VARCHAR(500),
    internal_url VARCHAR(500),
    custom_port INTEGER,
    role_description VARCHAR(500),
    requires_vpn BOOLEAN DEFAULT false,
    requires_2fa BOOLEAN DEFAULT false,
    ssh_key_auth_enabled BOOLEAN DEFAULT false,
    access_level VARCHAR(100),

    -- Lifecycle management
    expires_at TIMESTAMP,
    last_rotated_at TIMESTAMP,
    is_active BOOLEAN DEFAULT true,

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_credentials_client (client_id),
    INDEX idx_credentials_service (service_id),
    INDEX idx_credentials_type (credential_type),
    INDEX idx_credentials_active (is_active)
);
```

**Security Features:**
- All sensitive fields encrypted with AES-256-GCM
- Encryption key stored separately (environment variable or vault)
- Master password unlock mechanism
- Automatic expiration tracking
- Rotation reminders
- VPN requirement flags

**Example Records:**

**Password Credential (AD2 sysadmin):**
```json
{
  "service_name": "AD2\\sysadmin",
  "credential_type": "password",
  "username": "sysadmin",
  "password_encrypted": "<encrypted_bytes>",
  "internal_url": "192.168.0.6",
  "requires_vpn": true,
  "access_level": "Domain Admin",
  "infrastructure_id": "ad2-server-uuid",
  "client_id": "dataforth-uuid"
}
```

**API Key (SyncroMSP):**
```json
{
  "service_name": "SyncroMSP API",
  "credential_type": "api_key",
  "api_key_encrypted": "<encrypted_bytes>",
  "external_url": "https://azcomputerguru.syncromsp.com/api/v1",
  "integration_code": "syncro_psa",
  "expires_at": "2027-01-15T00:00:00Z"
}
```

**OAuth Credential (Microsoft 365):**
```json
{
  "service_name": "Dataforth M365 Admin",
  "credential_type": "oauth",
  "client_id_oauth": "app-client-id",
  "client_secret_encrypted": "<encrypted_bytes>",
  "tenant_id_oauth": "tenant-uuid",
  "token_encrypted": "<encrypted_access_token>",
  "requires_2fa": true,
  "client_id": "dataforth-uuid"
}
```

**SSH Key (D2TESTNAS root):**
```json
{
  "service_name": "D2TESTNAS root",
  "credential_type": "ssh_key",
  "username": "root",
  "public_key": "ssh-rsa AAAAB3Nza...",
  "internal_url": "192.168.0.9",
  "requires_vpn": true,
  "ssh_key_auth_enabled": true,
  "infrastructure_id": "d2testnas-uuid"
}
```

---

### `credential_audit_log`

Comprehensive audit trail for all credential access operations. Tracks who accessed what credential, when, from where, and why.

```sql
CREATE TABLE credential_audit_log (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    credential_id UUID NOT NULL REFERENCES credentials(id) ON DELETE CASCADE,

    -- Action tracking
    action VARCHAR(50) NOT NULL CHECK(action IN (
        'view', 'create', 'update', 'delete', 'rotate', 'decrypt'
    )),

    -- User context
    user_id VARCHAR(255) NOT NULL, -- JWT sub claim
    ip_address VARCHAR(45),
    user_agent TEXT,

    -- Session context
    session_id UUID, -- if accessed during MSP session
    work_item_id UUID, -- if accessed for specific work item

    -- Audit details
    details TEXT, -- JSON: what changed, why accessed, etc.

    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_cred_audit_credential (credential_id),
    INDEX idx_cred_audit_user (user_id),
    INDEX idx_cred_audit_timestamp (timestamp),
    INDEX idx_cred_audit_action (action)
);
```

**Logged Actions:**
- **view** - Credential viewed in UI/API
- **create** - New credential stored
- **update** - Credential modified
- **delete** - Credential removed
- **rotate** - Password/key rotated
- **decrypt** - Credential decrypted for use

**Example Audit Entries:**

**Credential Access During Session:**
```json
{
  "credential_id": "ad2-sysadmin-uuid",
  "action": "decrypt",
  "user_id": "mike@azcomputerguru.com",
  "ip_address": "172.16.3.101",
  "session_id": "current-session-uuid",
  "work_item_id": "fix-user-account-uuid",
  "details": {
    "reason": "Access AD2 to reset user account",
    "service_name": "AD2\\sysadmin"
  },
  "timestamp": "2026-01-15T14:32:10Z"
}
```

**Credential Rotation:**
```json
{
  "credential_id": "nas-root-uuid",
  "action": "rotate",
  "user_id": "mike@azcomputerguru.com",
  "details": {
    "reason": "Scheduled 90-day rotation",
    "old_password_hash": "sha256:abc123...",
    "new_password_hash": "sha256:def456..."
  },
  "timestamp": "2026-01-15T09:00:00Z"
}
```

**Failed Access Attempt:**
```json
{
  "credential_id": "client-api-uuid",
  "action": "view",
  "user_id": "unknown@external.com",
  "ip_address": "203.0.113.45",
  "details": {
    "error": "Unauthorized - invalid JWT token",
    "blocked": true
  },
  "timestamp": "2026-01-15T03:22:05Z"
}
```

**Audit Queries:**
```sql
-- Who accessed this credential in last 30 days?
SELECT user_id, action, timestamp, details
FROM credential_audit_log
WHERE credential_id = 'target-uuid'
  AND timestamp >= NOW() - INTERVAL 30 DAY
ORDER BY timestamp DESC;

-- All credential access by user
SELECT c.service_name, cal.action, cal.timestamp
FROM credential_audit_log cal
JOIN credentials c ON cal.credential_id = c.id
WHERE cal.user_id = 'mike@azcomputerguru.com'
ORDER BY cal.timestamp DESC
LIMIT 50;

-- Recent decryption events (actual credential usage)
SELECT c.service_name, cal.user_id, cal.timestamp, cal.session_id
FROM credential_audit_log cal
JOIN credentials c ON cal.credential_id = c.id
WHERE cal.action = 'decrypt'
  AND cal.timestamp >= NOW() - INTERVAL 7 DAY
ORDER BY cal.timestamp DESC;
```

---

### `security_incidents`

Security event and incident tracking for MSP clients. Documents incidents, investigations, remediation, and resolution.

```sql
CREATE TABLE security_incidents (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    client_id UUID REFERENCES clients(id) ON DELETE CASCADE,
    service_id UUID REFERENCES services(id) ON DELETE SET NULL,
    infrastructure_id UUID REFERENCES infrastructure(id) ON DELETE SET NULL,

    -- Incident classification
    incident_type VARCHAR(100) CHECK(incident_type IN (
        'bec', 'backdoor', 'malware', 'unauthorized_access',
        'data_breach', 'phishing', 'ransomware', 'brute_force',
        'credential_compromise', 'ddos', 'injection_attack'
    )),
    incident_date TIMESTAMP NOT NULL,
    severity VARCHAR(50) CHECK(severity IN ('critical', 'high', 'medium', 'low')),

    -- Incident details
    description TEXT NOT NULL,
    affected_users TEXT, -- JSON array of affected users
    affected_systems TEXT, -- JSON array of affected systems

    -- Investigation
    findings TEXT, -- investigation results
    root_cause TEXT,
    indicators_of_compromise TEXT, -- JSON array: IPs, file hashes, domains

    -- Remediation
    remediation_steps TEXT,
    remediation_verified BOOLEAN DEFAULT false,

    -- Status tracking
    status VARCHAR(50) DEFAULT 'investigating' CHECK(status IN (
        'investigating', 'contained', 'resolved', 'monitoring'
    )),
    detected_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    contained_at TIMESTAMP,
    resolved_at TIMESTAMP,

    -- Follow-up
    lessons_learned TEXT,
    prevention_measures TEXT, -- what was implemented to prevent recurrence
    external_reporting_required BOOLEAN DEFAULT false, -- regulatory/client reporting
    external_report_details TEXT,

    notes TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_incidents_client (client_id),
    INDEX idx_incidents_type (incident_type),
    INDEX idx_incidents_severity (severity),
    INDEX idx_incidents_status (status),
    INDEX idx_incidents_date (incident_date)
);
```

**Real-World Examples from Session Logs:**

**BEC (Business Email Compromise) - BG Builders:**
```json
{
  "incident_type": "bec",
  "client_id": "bg-builders-uuid",
  "incident_date": "2025-12-XX",
  "severity": "critical",
  "description": "OAuth backdoor application discovered in M365 tenant allowing unauthorized email access",
  "affected_users": ["admin@bgbuilders.com", "accounting@bgbuilders.com"],
  "findings": "Malicious OAuth app registered with Mail.ReadWrite permissions. App created via phishing attack.",
  "root_cause": "User clicked phishing link and authorized malicious OAuth application",
  "remediation_steps": "1. Revoked OAuth app consent\n2. Forced password reset for affected users\n3. Enabled MFA for all users\n4. Reviewed audit logs for data exfiltration\n5. Configured conditional access policies",
  "remediation_verified": true,
  "status": "resolved",
  "prevention_measures": "Implemented OAuth app approval workflow, security awareness training, conditional access policies",
  "external_reporting_required": true,
  "external_report_details": "Notified client management, documented for cyber insurance"
}
```

**BEC - CW Concrete:**
```json
{
  "incident_type": "bec",
  "client_id": "cw-concrete-uuid",
  "incident_date": "2025-11-XX",
  "severity": "high",
  "description": "Business email compromise detected - unauthorized access to executive mailbox",
  "affected_users": ["ceo@cwconcrete.com"],
  "findings": "Attacker used compromised credentials to access mailbox and send fraudulent wire transfer requests",
  "root_cause": "Credential phishing via fake Office 365 login page",
  "remediation_steps": "1. Reset compromised credentials\n2. Enabled MFA\n3. Blocked sender domains\n4. Reviewed sent items for fraudulent emails\n5. Notified financial institutions",
  "status": "resolved",
  "lessons_learned": "MFA should be mandatory for all executive accounts. Email authentication (DMARC/DKIM/SPF) critical."
}
```

**Malware - General Pattern:**
```json
{
  "incident_type": "malware",
  "severity": "high",
  "description": "Ransomware infection detected on workstation",
  "affected_systems": ["WS-ACCT-01"],
  "findings": "CryptoLocker variant. Files encrypted with .encrypted extension. Ransom note left in directories.",
  "root_cause": "User opened malicious email attachment",
  "remediation_steps": "1. Isolated infected system\n2. Verified backups available\n3. Wiped and restored from backup\n4. Updated endpoint protection\n5. Implemented email attachment filtering",
  "status": "resolved",
  "prevention_measures": "Enhanced email filtering, user training, backup verification schedule"
}
```

**Queries:**
```sql
-- Critical unresolved incidents
SELECT client_id, incident_type, description, incident_date
FROM security_incidents
WHERE severity = 'critical'
  AND status != 'resolved'
ORDER BY incident_date DESC;

-- Incident history for client
SELECT incident_type, severity, incident_date, status
FROM security_incidents
WHERE client_id = 'target-client-uuid'
ORDER BY incident_date DESC;

-- BEC incidents requiring reporting
SELECT client_id, description, incident_date, external_report_details
FROM security_incidents
WHERE incident_type = 'bec'
  AND external_reporting_required = true;
```

---

### `credential_permissions`

Granular access control for credentials. Supports future multi-user MSP team expansion by defining who can access which credentials.

```sql
CREATE TABLE credential_permissions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    credential_id UUID NOT NULL REFERENCES credentials(id) ON DELETE CASCADE,
    user_id VARCHAR(255) NOT NULL, -- or role_id for role-based access

    -- Permission levels
    permission_level VARCHAR(50) CHECK(permission_level IN ('read', 'write', 'admin')),

    -- Constraints
    requires_2fa BOOLEAN DEFAULT false, -- force 2FA for this credential
    ip_whitelist TEXT, -- JSON array of allowed IPs
    time_restrictions TEXT, -- JSON: business hours only, etc.

    -- Audit
    granted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    granted_by VARCHAR(255),
    expires_at TIMESTAMP, -- temporary access

    UNIQUE(credential_id, user_id),
    INDEX idx_cred_perm_credential (credential_id),
    INDEX idx_cred_perm_user (user_id)
);
```

**Permission Levels:**
- **read** - Can view/decrypt credential
- **write** - Can update credential
- **admin** - Can grant/revoke permissions, delete credential

**Example Permissions:**

**Standard Technician Access:**
```json
{
  "credential_id": "client-rdp-uuid",
  "user_id": "tech1@azcomputerguru.com",
  "permission_level": "read",
  "requires_2fa": false,
  "granted_by": "mike@azcomputerguru.com"
}
```

**Sensitive Credential (Admin Only):**
```json
{
  "credential_id": "domain-admin-uuid",
  "user_id": "mike@azcomputerguru.com",
  "permission_level": "admin",
  "requires_2fa": true,
  "ip_whitelist": ["172.16.3.0/24", "192.168.1.0/24"],
  "granted_by": "system"
}
```

**Temporary Access (Contractor):**
```json
{
  "credential_id": "temp-vpn-uuid",
  "user_id": "contractor@external.com",
  "permission_level": "read",
  "requires_2fa": true,
  "expires_at": "2026-02-01T00:00:00Z",
  "granted_by": "mike@azcomputerguru.com"
}
```

**Time-Restricted Access:**
```json
{
  "credential_id": "backup-system-uuid",
  "user_id": "nightshift@azcomputerguru.com",
  "permission_level": "read",
  "time_restrictions": {
    "allowed_hours": "18:00-06:00",
    "timezone": "America/Phoenix",
    "days": ["mon", "tue", "wed", "thu", "fri"]
  }
}
```

---

## Credential Workflows

### Credential Storage Workflow (Agent-Based)

**When new credential discovered during MSP session:**

1. **User mentions credential:**
   - "SSH to AD2 as sysadmin" → Claude detects credential reference

2. **Check if credential exists:**
   - Query: `GET /api/v1/credentials?service=AD2&username=sysadmin`

3. **If not found, prompt user:**
   - "Store credential for AD2\\sysadmin? (y/n)"

4. **Launch Credential Storage Agent:**
   - Receives: credential data, client context, service info
   - Encrypts credential with AES-256-GCM
   - Links to client_id, service_id, infrastructure_id
   - Stores via API: `POST /api/v1/credentials`
   - Creates audit log entry (action: 'create')
   - Returns: credential_id

5. **Main Claude confirms:**
   - "Stored AD2\\sysadmin credential (ID: abc123)"

### Credential Retrieval Workflow (Agent-Based)

**When credential needed for work:**

1. **Launch Credential Retrieval Agent:**
   - Task: "Retrieve credential for AD2\\sysadmin"

2. **Agent performs:**
   - Query API: `GET /api/v1/credentials?service=AD2&username=sysadmin`
   - Decrypt credential (API handles this with master key)
   - Log access to credential_audit_log:
     - action: 'decrypt'
     - user_id: from JWT
     - session_id: current MSP session
     - work_item_id: current work context
   - Return only credential value

3. **Agent returns:**
   - "Paper123!@#" (actual credential)

4. **Main Claude uses credential:**
   - Displays in context: "Using AD2\\sysadmin password from vault"
   - Never logs actual password value in session logs

5. **Audit trail created automatically**

### Credential Rotation Workflow

**Scheduled or on-demand rotation:**

1. **Identify credentials needing rotation:**
   ```sql
   SELECT * FROM credentials
   WHERE expires_at <= NOW() + INTERVAL 7 DAY
      OR last_rotated_at <= NOW() - INTERVAL 90 DAY;
   ```

2. **For each credential:**
   - Generate new password/key
   - Update service/infrastructure with new credential
   - Encrypt new credential
   - Update credentials table
   - Set last_rotated_at = NOW()
   - Log rotation in credential_audit_log

3. **Verify new credential works:**
   - Test authentication
   - Update verification status

4. **Notify user:**
   - "Rotated 3 credentials: AD2\\sysadmin, NAS root, Gitea admin"

---

## Security Considerations

### Encryption at Rest

**AES-256-GCM Encryption:**
- All `*_encrypted` fields use AES-256-GCM
- Provides both confidentiality and authenticity
- Per-credential random IV (initialization vector)
- Master key stored separately from database

**Master Key Management:**
```python
# Example key storage (production)
# Option 1: Environment variable (Docker secret)
MASTER_KEY = os.environ['MSP_CREDENTIAL_MASTER_KEY']

# Option 2: HashiCorp Vault
# vault = hvac.Client(url='https://vault.internal')
# MASTER_KEY = vault.secrets.kv.v2.read_secret_version(path='msp/credential-key')

# Option 3: AWS KMS / Azure Key Vault
# MASTER_KEY = kms_client.decrypt(encrypted_key_blob)
```

**Encryption Process:**
```python
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

def encrypt_credential(plaintext: str, master_key: bytes) -> bytes:
    """Encrypt credential with AES-256-GCM"""
    aesgcm = AESGCM(master_key)  # 32-byte key
    nonce = os.urandom(12)  # 96-bit random nonce
    ciphertext = aesgcm.encrypt(nonce, plaintext.encode(), None)
    return nonce + ciphertext  # prepend nonce to ciphertext

def decrypt_credential(encrypted: bytes, master_key: bytes) -> str:
    """Decrypt credential"""
    aesgcm = AESGCM(master_key)
    nonce = encrypted[:12]
    ciphertext = encrypted[12:]
    plaintext = aesgcm.decrypt(nonce, ciphertext, None)
    return plaintext.decode()
```

### Access Control

**JWT-Based Authentication:**
- All API requests require valid JWT token
- Token includes user_id (sub claim)
- Token expires after 1 hour (refresh pattern)

**Permission Checks:**
```python
# Before decrypting credential
def check_credential_access(credential_id: str, user_id: str) -> bool:
    # Check credential_permissions table
    perm = db.query(CredentialPermission).filter(
        CredentialPermission.credential_id == credential_id,
        CredentialPermission.user_id == user_id
    ).first()

    if not perm:
        # No explicit permission - deny by default
        return False

    if perm.expires_at and perm.expires_at < datetime.now():
        # Permission expired
        return False

    if perm.requires_2fa:
        # Check if user has valid 2FA session
        if not check_2fa_session(user_id):
            return False

    return True
```

**Audit Logging:**
- Every credential access logged automatically
- Failed access attempts logged with details
- Queryable for security investigations
- Retention: 7 years (compliance)

### Key Rotation Strategy

**Master Key Rotation (Annual or on-demand):**

1. Generate new master key
2. Re-encrypt all credentials with new key
3. Update key in secure storage
4. Audit log: key rotation event
5. Verify all credentials decrypt successfully
6. Archive old key (encrypted, for disaster recovery)

**Credential Rotation (Per-credential schedule):**

- **Critical credentials:** 90 days
- **Standard credentials:** 180 days
- **Service accounts:** 365 days
- **API keys:** 365 days or vendor recommendation

### Compliance Considerations

**Data Retention:**
- Credentials: Retained while active
- Audit logs: 7 years minimum
- Security incidents: Permanent (unless client requests deletion)

**Access Logging:**
- Who accessed what credential
- When and from where (IP)
- Why (session/work item context)
- Result (success/failure)

**Encryption Standards:**
- AES-256-GCM (FIPS 140-2 compliant)
- TLS 1.3 for API transit encryption
- Key length: 256 bits minimum

---

## Integration with Other Schemas

**Links to:**
- `clients` - Credentials belong to clients
- `infrastructure` - Credentials access infrastructure
- `services` - Credentials authenticate to services
- `sessions` - Credential access logged per session
- `work_items` - Credentials used for specific work

**Used by:**
- MSP Mode sessions (credential retrieval)
- Security incident investigations (affected credentials)
- Audit queries (compliance reporting)
- Integration workflows (external system authentication)

---

## Example Queries

### Find all credentials for a client
```sql
SELECT c.service_name, c.username, c.credential_type, c.requires_vpn
FROM credentials c
WHERE c.client_id = 'dataforth-uuid'
  AND c.is_active = true
ORDER BY c.service_name;
```

### Check credential expiration
```sql
SELECT c.service_name, c.expires_at, c.last_rotated_at
FROM credentials c
WHERE c.expires_at <= NOW() + INTERVAL 30 DAY
   OR c.last_rotated_at <= NOW() - INTERVAL 90 DAY
ORDER BY c.expires_at ASC;
```

### Audit: Who accessed credential?
```sql
SELECT cal.user_id, cal.action, cal.timestamp, cal.ip_address
FROM credential_audit_log cal
WHERE cal.credential_id = 'target-credential-uuid'
ORDER BY cal.timestamp DESC
LIMIT 20;
```

### Find credentials accessed in session
```sql
SELECT c.service_name, cal.action, cal.timestamp
FROM credential_audit_log cal
JOIN credentials c ON cal.credential_id = c.id
WHERE cal.session_id = 'session-uuid'
ORDER BY cal.timestamp;
```

### Security incidents requiring follow-up
```sql
SELECT si.client_id, si.incident_type, si.description, si.status
FROM security_incidents si
WHERE si.status IN ('investigating', 'contained')
  AND si.severity IN ('critical', 'high')
ORDER BY si.incident_date DESC;
```

---

## Future Enhancements

**Planned:**
1. Hardware security module (HSM) integration
2. Multi-factor authentication for high-privilege credentials
3. Automatic credential rotation scheduling
4. Integration with password managers (1Password, Bitwarden)
5. Credential strength analysis and weak password detection
6. Breach detection integration (Have I Been Pwned API)
7. Role-based access control (RBAC) for team expansion
8. Credential sharing workflows with approval process

**Under Consideration:**
- Biometric authentication for critical credentials
- Time-based one-time password (TOTP) storage
- Certificate management and renewal automation
- Secrets scanning in code repositories
- Automated credential discovery (scan infrastructure)

---

**Document Version:** 1.0
**Last Updated:** 2026-01-15
**Author:** MSP Mode Schema Design Team
