- Add PolicySourceStore for tracking where policies come from - Implement claim extraction skill and API endpoints - Add community UI text selection extractor component - Create Go SDK aphoria client for policy operations - Document patent specifications and legal disclosures - Add guides: golden path loop, policy audit trails, pre-flight checks - Expand Unreal Engine config extractor with source tracking - Add UAT reports for policy source tracking validation - Refactor tests.rs into modular test files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
196 lines
6.0 KiB
Markdown
196 lines
6.0 KiB
Markdown
# 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).
|