# Guide: Policy Audit Trails — "Who Approved This?"

**Target Audience:** Compliance Officers, Security Auditors, Engineering Managers
**Prerequisite:** [Federating Truth](./federating-truth.md)

---

## The Problem: The Compliance Nightmare

It's audit season. The auditor asks:

> "Show me evidence that your TLS configuration was approved by someone with authority."

You dig through Slack, Jira, and Confluence. You find a thread from 2024 where someone said "LGTM." The auditor is not impressed.

What you need is:
1. **What** was approved (the exact policy)
2. **Who** approved it (cryptographic proof)
3. **When** it was approved (timestamp)
4. **Where** it's enforced (which projects)

Aphoria's policy source tracking gives you all four.

---

## How Policy Provenance Works

When you import a Trust Pack, Aphoria stores metadata for every assertion:

| Field | Description | Example |
|-------|-------------|---------|
| `pack_name` | Human-readable policy name | "Acme Security Standard" |
| `pack_version` | Semver version | "2.1.0" |
| `issuer_hex` | First 8 chars of signer's public key | "a1b2c3d4" |

This metadata appears in every conflict report, creating an unbroken chain from violation → policy → approver.

---

## Step 1: Establish Policy Authority

Your Security team creates the authoritative policy in a dedicated repo.

```bash
cd security-policies/

# Initialize persistent storage
aphoria init

# Define policies through bless commands
aphoria bless "code://*/tls/cert_verification" enabled true \
  --reason "SOC2 CC6.1: Encrypt data in transit"

aphoria bless "code://*/secrets/api_key" storage "vault" \
  --reason "SOC2 CC6.7: Secrets must use approved vault"

aphoria bless "code://*/logging/pii" masked true \
  --reason "GDPR Art.32: PII must not appear in logs"
```

## Step 2: Export with Versioning

Export the policy with a meaningful version that maps to your compliance cycle.

```bash
# Version matches your security policy document
aphoria export \
  --name "Acme SOC2 Controls v2.1" \
  --output acme-soc2-v2.1.pack
```

The `.pack` file contains:
- All assertions (the "what")
- Ed25519 signature (the "who" — cryptographic proof)
- Timestamp (the "when")

## Step 3: Distribute to Projects

Host the pack and configure projects to use it:

```toml
# Every project's aphoria.toml
policies = ["https://security.internal/policies/acme-soc2-v2.1.pack"]
```

## Step 4: The Audit Trail in Action

When a developer violates policy, the report shows full provenance:

```
┌─────────────────────────────────────────────────────────────────┐
│ BLOCK   code://go/payments/tls/cert_verification                │
├─────────────────────────────────────────────────────────────────┤
│ Location:   src/client.go:45                                    │
│ Your Code:  tls.InsecureSkipVerify = true                       │
│ Policy:     enabled = true                                      │
│                                                                 │
│ Source:     Acme SOC2 Controls v2.1 (a1b2c3d4)                 │
│ Reason:     SOC2 CC6.1: Encrypt data in transit                 │
└─────────────────────────────────────────────────────────────────┘
```

The auditor can now verify:
- **What:** TLS verification must be enabled
- **Who:** Key `a1b2c3d4` (maps to Security Team's signing key)
- **When:** Pack creation timestamp in the file
- **Where:** This specific project imported the policy

---

## Generating Compliance Reports

Export scan results as JSON for your compliance dashboard:

```bash
aphoria scan . --mode persistent --format json > compliance-scan.json
```

Extract policy sources for your audit evidence:

```bash
cat compliance-scan.json | jq '
  .findings[] |
  select(.verdict == "BLOCK" or .verdict == "FLAG") |
  {
    violation: .claim.concept_path,
    policy: .conflicting_sources[0].policy_source.pack_name,
    version: .conflicting_sources[0].policy_source.pack_version,
    approver: .conflicting_sources[0].policy_source.issuer_hex
  }
'
```

**Output:**
```json
{
  "violation": "code://go/payments/tls/cert_verification",
  "policy": "Acme SOC2 Controls v2.1",
  "version": "2.1.0",
  "approver": "a1b2c3d4"
}
```

---

## Mapping Issuer Keys to People

The `issuer_hex` is derived from an Ed25519 public key. Map these to real identities in your key registry:

```yaml
# key-registry.yaml (maintained by Security team)
keys:
  a1b2c3d4:
    owner: "security-team@acme.com"
    name: "Security Team Signing Key"
    created: "2025-01-15"

  e5f6g7h8:
    owner: "platform-team@acme.com"
    name: "Platform Team Signing Key"
    created: "2025-03-20"
```

Now the auditor sees:
> "Violation blocked by **Acme SOC2 Controls v2.1**, approved by **Security Team** (key a1b2c3d4)"

---

## Version History for Compliance

Keep old pack versions for historical audits:

```
policies/
├── acme-soc2-v1.0.pack    # 2024 Q1-Q2
├── acme-soc2-v1.1.pack    # 2024 Q3-Q4
├── acme-soc2-v2.0.pack    # 2025 Q1
└── acme-soc2-v2.1.pack    # Current
```

If an auditor asks "What policies were in effect on March 15, 2025?", you can point to the specific pack version and its contents.

---

## Summary

| Audit Question | Aphoria Answer |
|----------------|----------------|
| "Who approved this policy?" | `issuer_hex` → Key Registry → Owner |
| "When was it approved?" | Pack file timestamp |
| "What exactly was approved?" | Assertions in the pack |
| "Is it still enforced?" | Current `aphoria.toml` policies list |
| "Which projects comply?" | Scan results across repos |

**Next:** See how multiple teams can publish non-conflicting policies in [Multi-Team Policy Governance](./multi-team-policy-governance.md).
