# Azure Key Vault Architecture Reference
**Cold Bore Ballistics LLC — Confidential**
Last updated: 2026-06-06
Status: Active — `kv-cbb-shared-prod` applied 2026-06-06; `kv-scope-dope-prod` planned

> This document is the authoritative record of what Key Vault resources exist (or are planned) in the CBB Azure subscription. It is the single source of truth for vault names, access policies, and secret inventory. Secret **values** are never recorded here — only names, purposes, and rotation policies. Cross-reference `Azure_Architecture_Reference.md` for the broader Azure resource layout.

---

## Design Rationale

Secrets are managed in Azure Key Vault rather than passed as Terraform variables or stored in environment files. This eliminates plaintext secrets from `terraform.tfvars`, Terraform state, and CI/CD pipelines. Container Apps access secrets at runtime via managed identity — no credentials are embedded in application code or infrastructure configuration.

Two vaults are provisioned, one per scope:

| Vault | Scope | Rationale |
|---|---|---|
| `kv-cbb-shared-prod` | Corporate infrastructure secrets | Held in the `shared` Terraform service; accessed by Terraform automation only |
| `kv-scope-dope-prod` | ScopeDOPE application secrets | Held in the `scope-dope` Terraform service; accessed by the `feedback-service` Container App managed identity |

Keeping vaults separated by scope means a ScopeDOPE-specific acquisition can be packaged cleanly — the acquirer's team gets access to `kv-scope-dope-prod` without touching corporate infrastructure credentials.

---

## Vault Inventory

### `kv-cbb-shared-prod`

| Property | Value |
|---|---|
| **Resource group** | `rg-cbb-prod` |
| **Region** | northcentralus |
| **SKU** | Standard |
| **Soft delete** | Enabled, 90-day retention |
| **Purge protection** | Enabled |
| **Network access** | Firewall `Deny` + AzureServices bypass; allow-list: operator IP + Container App env static outbound IP (DocuSeal runtime) |
| **Terraform service** | `services/shared` |

#### Access — `kv-cbb-shared-prod`

| Principal | Type | Permissions | Purpose |
|---|---|---|---|
| Terraform operator (az login / OIDC) | User / Service Principal | Key, Secret, Certificate: Get, List, Set, Delete | Infrastructure management |

#### Secret Inventory — `kv-cbb-shared-prod`

Secrets are populated manually via `az keyvault secret set` after vault creation. Terraform creates the vault and grants RBAC; it does not write secret values.

| Secret name | Contains | Populated | Rotation policy |
|---|---|---|---|
| `vm-db-password` | PostgreSQL `feedback` user password on `vm-postgres-prod` | Pending | Rotate annually or on suspected compromise |
| `vm-ssh-public-key` | SSH public key authorized on `vm-postgres-prod` | Pending | Update when operator workstation changes |
| `namecheap-api-key` | Namecheap API key for account `coldboreballistics` — DNS automation via `cbb-utils/namecheap/` | 2026-06-06 | Rotate annually or on suspected compromise — regenerate in Namecheap → Profile → Tools → API Access |
| `twilio-cbb-auth-token` | Twilio CBB Corporate primary auth token (`AC26cc215c2e2f0425984bffbe7050a0e0`) | 2026-06-06 | Rotate only if compromised — rotation invalidates all CBB Corporate API keys |
| `sendgrid-claude-code-cli-secret` | SendGrid `claude-code-cli` API key secret (Full Access) | 2026-06-06 | Rotate annually or on suspected compromise |
| `twilio-cbb-claude-code-cli-secret` | Twilio CBB Corporate API key secret for the `claude-code-cli` key (`SK0974f8802be51c9c2e6fec7a4455b2cf`) | 2026-06-06 | Rotate annually or on suspected compromise; see Twilio Operating Runbook for key rotation procedure |
| `sendgrid-twilio-ivr-secret` | SendGrid `twilio-ivr` API key secret (Mail Send only) | 2026-06-06 | Rotate annually or on suspected compromise; update Twilio Function env var after rotation |
| `atlassian-claude-code-api-key` | Atlassian API key `claude-code-atlassian` for `admin@coldboreballisticsllc.com` — Claude Code MCP access to Jira and Confluence; expires 2027-06-01 | 2026-06-06 | Rotate before 2027-06-01 — create new token at id.atlassian.com → Security → API tokens, update Key Vault, revoke old token |

---

### `kv-scope-dope-prod`

| Property | Value |
|---|---|
| **Resource group** | `rg-cbb-prod` |
| **Region** | northcentralus |
| **SKU** | Standard |
| **Soft delete** | Enabled, 90-day retention |
| **Purge protection** | Enabled |
| **Network access** | Firewall `Deny` + AzureServices bypass; allow-list: operator IP (no live runtime consumer until the feedback service is rebuilt) |
| **Terraform service** | `services/scope-dope` (references vault via `terraform_remote_state` from shared) |

#### Access — `kv-scope-dope-prod`

| Principal | Type | Permissions | Purpose |
|---|---|---|---|
| Terraform operator | User / Service Principal | Key, Secret, Certificate: Get, List, Set, Delete | Infrastructure management |
| `feedback-service` Container App | System-assigned managed identity | Secret: Get, List | Runtime secret access |

#### Secret Inventory — `kv-scope-dope-prod`

Secrets are populated manually via `az keyvault secret set` after vault creation. Terraform creates the vault and grants RBAC; it does not write secret values.

| Secret name | Contains | Populated | Rotation policy |
|---|---|---|---|
| `database-url` | Full PostgreSQL connection string including password | Pending | Rotate with `vm-db-password` |
| `storage-connection-string` | Azure Blob Storage primary connection string for `stcbbprod` | Pending | Rotate annually or on key regeneration |
| `github-token` | GitHub PAT for feedback-service issue creation | Pending (deferred with feedback-service) | Rotate annually; immediately on token exposure |
| `flask-secret-key` | Flask session signing secret | Pending (deferred with feedback-service) | Rotate on suspected compromise |
| `twilio-scopedope-auth-token` | Twilio ScopeDOPE subaccount auth token (`AC7cc6b6571c9b0907b73b783a5422a2c4`) | 2026-06-06 | Rotate only if compromised — rotation invalidates all ScopeDOPE API keys |

> `acr-registry-password` was removed — the ACR admin user is disabled; the Container App pulls via managed identity (AcrPull).

---

## Terraform Structure

```
cbb-infra/
├── modules/
│   └── key_vault/          ← reusable module: creates one vault + RBAC assignments
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
├── services/
│   ├── shared/             ← creates kv-cbb-shared-prod; secrets populated via az CLI separately
│   └── scope-dope/         ← creates kv-scope-dope-prod; wires Container App to vault; secrets populated via az CLI separately
```

Container Apps reference Key Vault secrets via the `key_vault_secret_id` pattern using the Container App's system-assigned managed identity. No secret values pass through Terraform variables or state.

---

## Cost Tracking

| Resource | Monthly cost | Notes |
|---|---|---|
| `kv-cbb-shared-prod` | ~$0.00 | Standard SKU; ~$0.03/10k ops; low ops volume |
| `kv-scope-dope-prod` | ~$0.00 | Same; Container App reads secrets on startup only |
| **Total** | **~$0.00** | Rounds to zero at CBB scale |

---

## Architecture Decisions

| Decision | Choice | Rationale |
|---|---|---|
| SKU | Standard | HSM not required; software-backed keys sufficient for CBB secrets |
| Access model | RBAC (not legacy access policies) | RBAC is the current Azure recommended model; consistent with rest of Azure IAM |
| Purge protection | Enabled | Prevents accidental permanent deletion; required for compliance-grade environments |
| Vault per scope | Two vaults | Clean cost/access separation; acquisition packaging |
| Secret population | `az keyvault secret set` (CLI), never Terraform | Secret values never pass through Terraform variables or state; Terraform only creates vaults and grants RBAC |

---

## Document Control

| Field | Value |
|---|---|
| **Document owner** | `jschwefel@coldboreballisticsllc.com` |
| **Classification** | Confidential (03_-_Confidential/) |
| **Location** | `OneDrive/CBB_Corporate/03_-_Confidential/Infrastructure/Azure_Key_Vault/Azure_Key_Vault_Architecture_Reference.md` |
| **Cross-references** | `Azure_Key_Vault_Operating_Runbook.md`; `Azure_Key_Vault_Rebuild_Guide.md`; `Azure_Architecture_Reference.md` |
| **Created** | 2026-06-07 |
| **Last updated** | 2026-06-07 |
| **Next full review due** | 2027-06-07 |

---

## Revision Control Block

| Rev | Date | Changed By | Reviewed By | Approved By | Summary |
|-----|------|------------|-------------|-------------|---------|
| 0.9 | 2026-06-07 | jschwefel | — | — | Initial release |
