docs: fix Aphoria pitch materials based on skeptical buyer review
Demo script & slides: - Update speed claims from "0.25s" to "<100ms staged, <1s full" - Fix CLI output mockups to match actual Aphoria table.rs format - Remove fake --approver and --expires flags from ack examples - Remove non-existent "Contact: #security-policy" field - Update ACK output to describe summary table behavior accurately Roadmap additions (Phase 10): - 10.1 Acknowledgment Expiry: --expires flag with duration/ISO date - 10.2 Human-Readable Signer Names: signer_name + contact in PackHeader - 10.3 Speed Benchmarks: aphoria scan --benchmark self-test Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c02b0370d7
commit
9698e63702
359
applications/aphoria-pitch/README.md
Normal file
359
applications/aphoria-pitch/README.md
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
# Aphoria Demo Script
|
||||||
|
|
||||||
|
> **Duration:** 15-20 minutes + Q&A
|
||||||
|
> **Target Buyer:** Marcus Thompson (VP Platform Engineering, Series C fintech, 400 engineers)
|
||||||
|
> **URLs:** Slides at `localhost:3001`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pre-Demo Checklist
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Terminal 1: Build Aphoria
|
||||||
|
cd applications/aphoria && cargo build --release
|
||||||
|
|
||||||
|
# Terminal 2: Create demo project with intentional violations
|
||||||
|
mkdir /tmp/aphoria-demo && cd /tmp/aphoria-demo
|
||||||
|
|
||||||
|
# Create a Go file with TLS skip violation
|
||||||
|
cat > main.go << 'EOF'
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
client := &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true, // VIOLATION: Disables cert verification
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_ = client
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create a config with weak TLS version
|
||||||
|
cat > config.yaml << 'EOF'
|
||||||
|
server:
|
||||||
|
tls:
|
||||||
|
min_version: "1.2" # VIOLATION: Should be 1.3
|
||||||
|
ciphers:
|
||||||
|
- TLS_RSA_WITH_AES_128_CBC_SHA # VIOLATION: Weak cipher
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create a JWT config with weak algorithm
|
||||||
|
cat > auth.go << 'EOF'
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import "github.com/golang-jwt/jwt/v5"
|
||||||
|
|
||||||
|
func CreateToken() {
|
||||||
|
// VIOLATION: Using HS256 instead of RS256
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||||
|
"user": "admin",
|
||||||
|
})
|
||||||
|
_ = token
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Terminal 3: Start slides
|
||||||
|
cd applications/aphoria-pitch && npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verify before presenting:**
|
||||||
|
- [ ] `aphoria scan` runs without error on demo project
|
||||||
|
- [ ] Violations are detected (BLOCK for TLS skip, WARN for weak cipher)
|
||||||
|
- [ ] Slides load at `localhost:3001`
|
||||||
|
- [ ] Press `S` to verify speaker notes appear
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Part 1: Slides (localhost:3001)
|
||||||
|
|
||||||
|
### Slide 1: The Hook
|
||||||
|
**On screen:** "SOC 2 audit prep takes **180 hours**. 60% is proving 'who approved what.'"
|
||||||
|
|
||||||
|
**Say:**
|
||||||
|
> "How long did your last SOC 2 audit take? For most Series C companies, it's about 180 hours of engineering time. And 60 percent of that time is spent on 'audit archaeology' - reconstructing who approved what, when."
|
||||||
|
>
|
||||||
|
> "63 percent of security incidents trace to config drift from a known-good state. Not new vulnerabilities. Drift from what you already knew was correct."
|
||||||
|
|
||||||
|
**Then:** Press -> to reveal "The problem isn't missing policies. It's proving you enforced them."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Slide 2: Why This Keeps Happening
|
||||||
|
**On screen:** Three pain points
|
||||||
|
|
||||||
|
**Say (reveal each with ->):**
|
||||||
|
> "AI generates code that looks correct. Copilot will happily write `InsecureSkipVerify = true` if you ask for a quick HTTP client. Does your PR review catch it? Every time?"
|
||||||
|
>
|
||||||
|
> "Your staff engineer wrote a best practices wiki. New hires don't read it. Contractors don't know it exists."
|
||||||
|
>
|
||||||
|
> "An auditor asks 'who approved this exception?' You spend 3 hours digging through Slack threads from 2023."
|
||||||
|
|
||||||
|
**Key point:** "Your security team writes policies. Nobody can prove they're followed. That's the gap."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Slide 3: Introducing Aphoria
|
||||||
|
**On screen:** Aphoria logo + tagline
|
||||||
|
|
||||||
|
**Say:**
|
||||||
|
> "Aphoria is a code-level truth linter. We don't pattern-match like Semgrep. We validate your code against authoritative sources - RFCs, OWASP guidelines, your internal policies - with cryptographic provenance."
|
||||||
|
|
||||||
|
**Don't linger** - next slide explains the approach.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Slide 4: Every Policy Has a Source
|
||||||
|
**On screen:** Three benefits
|
||||||
|
|
||||||
|
**Say (reveal each with ->):**
|
||||||
|
> "Cryptographic attribution. Every policy is signed by an approver. Not 'the linter said so.' It's 'signed by @security-team, Acme Security Standard version 3.2.'"
|
||||||
|
>
|
||||||
|
> "Sub-second scanning. Under 100 milliseconds for staged files, under 1 second for full scans. Fast enough for pre-commit hooks. Your developers won't disable it."
|
||||||
|
>
|
||||||
|
> "AI guardrails. Copilot generates insecure code. This catches it instantly, before the PR."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Slide 5: What This Enables
|
||||||
|
**On screen:** Three capability cards
|
||||||
|
|
||||||
|
**Say:**
|
||||||
|
> "Policy governance - your security team publishes once, 400 engineers inherit instantly. No more 'update 50 repos.'"
|
||||||
|
>
|
||||||
|
> "Drift detection - 'TLS config changed from 1.3 to 1.2' - caught before production, not during the incident."
|
||||||
|
>
|
||||||
|
> "Compliance export - SOC 2 evidence in 15 minutes, not 3 days. Full JSON with provenance."
|
||||||
|
|
||||||
|
**Reveal:** "Every exception tracked with reason and timestamp."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Slide 6: Demo Preview
|
||||||
|
**On screen:** CLI output preview
|
||||||
|
|
||||||
|
**Say:**
|
||||||
|
> "This is what you're about to see. A blocked violation with the exact policy it violates, who signed that policy, and how to get help."
|
||||||
|
>
|
||||||
|
> "I'm going to run this exact command live..."
|
||||||
|
|
||||||
|
**Then:** Switch to Terminal for live demo
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Part 2: Live Demo (Terminal)
|
||||||
|
|
||||||
|
### Demo Step 1: Speed
|
||||||
|
**Command:**
|
||||||
|
```bash
|
||||||
|
cd /tmp/aphoria-demo
|
||||||
|
time aphoria scan
|
||||||
|
```
|
||||||
|
|
||||||
|
**What they see:**
|
||||||
|
- Scan completes in under 1 second (typically ~650ms for full scan)
|
||||||
|
- 3 violations detected
|
||||||
|
|
||||||
|
**Say:**
|
||||||
|
> "Under a second for a full scan. Under 100 milliseconds for staged files only. That's fast enough for a pre-commit hook. Your developers won't disable it because they don't notice it."
|
||||||
|
|
||||||
|
**AMAZE MOMENT:** "This is pre-commit ready. No waiting. No 'I'll run it later.'"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Demo Step 2: Attribution
|
||||||
|
**What they see in the output:**
|
||||||
|
```
|
||||||
|
BLOCK code://go/aphoria-demo/main/tls/cert_verification
|
||||||
|
Your code: TLS certificate verification is disabled (main.go:12)
|
||||||
|
Regulatory: Boolean(true) (Tier 0)
|
||||||
|
Action: Fix or acknowledge with: aphoria ack <path> --reason "..."
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** After importing a Trust Pack with `aphoria policy import`, output includes:
|
||||||
|
```
|
||||||
|
Source: Acme Security Standard v1.0 (5a3c7b...)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Say:**
|
||||||
|
> "Look at the output. This isn't 'rule 47 failed.' It shows the exact file and line, what the regulatory standard requires, and how to handle exceptions."
|
||||||
|
>
|
||||||
|
> "When you import your org's Trust Pack, every violation traces to a signed policy source. When an auditor asks 'what's your policy on TLS verification?' - this is your answer. Not a wiki page. A cryptographically signed assertion."
|
||||||
|
|
||||||
|
**AMAZE MOMENT:** "The audit trail is built into every violation."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Demo Step 3: Acknowledgments
|
||||||
|
**Command:**
|
||||||
|
```bash
|
||||||
|
aphoria ack code://go/aphoria-demo/main/tls/cert_verification \
|
||||||
|
--reason "Integration test environment - legacy system migration"
|
||||||
|
```
|
||||||
|
|
||||||
|
**What they see:**
|
||||||
|
```
|
||||||
|
Conflict acknowledged.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Re-scan shows the conflict now marked as ACK in the summary table:**
|
||||||
|
|
||||||
|
The violation appears with an `ACK` verdict instead of `BLOCK`, indicating it has been acknowledged. The acknowledgment reason and timestamp are stored in the audit trail.
|
||||||
|
|
||||||
|
**Say:**
|
||||||
|
> "Sometimes you need an exception. Not every violation is a real problem. Integration test environments, legacy migrations, third-party constraints."
|
||||||
|
>
|
||||||
|
> "This isn't `.sonar-ignore`. It's a tracked acknowledgment with a reason and timestamp, stored in the audit trail. When you re-scan, it shows as ACK instead of BLOCK."
|
||||||
|
|
||||||
|
**AMAZE MOMENT:** "Exceptions are tracked, not hidden."
|
||||||
|
|
||||||
|
**Coming Soon:** Acknowledgment expiry (`--expires`) to auto-resurface after a TTL.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Demo Step 4: Drift Detection
|
||||||
|
**Command:**
|
||||||
|
```bash
|
||||||
|
# First scan with persistence
|
||||||
|
aphoria scan --persist
|
||||||
|
|
||||||
|
# Modify the config to introduce drift
|
||||||
|
sed -i '' 's/min_version: "1.2"/min_version: "1.1"/' config.yaml
|
||||||
|
|
||||||
|
# Second scan
|
||||||
|
aphoria scan --persist
|
||||||
|
```
|
||||||
|
|
||||||
|
**What they see:**
|
||||||
|
```
|
||||||
|
DRIFT code://config/tls/min_version
|
||||||
|
Previous: 1.2
|
||||||
|
Current: 1.1
|
||||||
|
Changed: 2024-02-06T14:32:00Z
|
||||||
|
```
|
||||||
|
|
||||||
|
**Say:**
|
||||||
|
> "Drift detection. Someone changed the TLS version from 1.2 to 1.1. Maybe it was intentional. Maybe it was a merge conflict gone wrong."
|
||||||
|
>
|
||||||
|
> "Either way, you know. Before production. Not during the incident."
|
||||||
|
|
||||||
|
**AMAZE MOMENT:** "63% of security incidents are config drift. This catches them."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Demo Step 5: Compliance Export
|
||||||
|
**Command:**
|
||||||
|
```bash
|
||||||
|
aphoria scan --format json | jq '.violations | length'
|
||||||
|
aphoria scan --format json | jq '.acknowledgments'
|
||||||
|
aphoria scan --format json > soc2-evidence.json
|
||||||
|
```
|
||||||
|
|
||||||
|
**What they see:**
|
||||||
|
- Full JSON output with provenance
|
||||||
|
- Acknowledgments with reasons and timestamps
|
||||||
|
- Export-ready for SOC 2
|
||||||
|
|
||||||
|
**Say:**
|
||||||
|
> "15 minutes, not 3 days. Your SOC 2 auditor asks for evidence of policy enforcement. You give them this JSON file."
|
||||||
|
>
|
||||||
|
> "Every violation. Every acknowledgment. Full audit trail. Machine-readable. Auditor-friendly."
|
||||||
|
|
||||||
|
**AMAZE MOMENT:** "SOC 2 evidence generation goes from days to minutes."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Part 3: Return to Slides
|
||||||
|
|
||||||
|
### Slide 7: Questions
|
||||||
|
**Page:** Back to localhost:3001, press -> to reach Q&A slide
|
||||||
|
|
||||||
|
**What they see:** Recap of what they just saw
|
||||||
|
|
||||||
|
**Be ready for:**
|
||||||
|
|
||||||
|
| Question | Answer |
|
||||||
|
|----------|--------|
|
||||||
|
| "Why not just write better Semgrep rules?" | "Semgrep rules don't track who approved exceptions. Aphoria has cryptographic provenance. Every policy traces to a signer." |
|
||||||
|
| "What's the false positive rate?" | "We check against authoritative sources, not pattern matching. False positives are policy disagreements, not tool bugs. And those surface as conversations, not ignored warnings." |
|
||||||
|
| "I already have pre-commit hooks." | "Hooks catch violations. Aphoria proves who approved the policy and when. That's the difference between 'we have policies' and 'we can prove enforcement.'" |
|
||||||
|
| "SOC 2 certified?" | "We help you generate evidence. The JSON export with policy provenance and acknowledgment trails is what your auditor needs. We're working on control mapping documentation." |
|
||||||
|
| "Why not Postgres?" | "You could build this. 6-9 months, 2-3 engineers. We've done the hard work. And we've solved problems you haven't hit yet - provenance, drift detection, exception tracking." |
|
||||||
|
| "How does this work with existing CI?" | "Pre-commit hook or CI step. Same `aphoria scan` command. JSON output for automation, human-readable for developers." |
|
||||||
|
| "What about secrets/credentials detection?" | "Aphoria focuses on configuration policy validation, not secrets scanning. Use Gitleaks for secrets. Use Aphoria for 'is this config compliant with our policies.'" |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The Five Aha Moments (Summary)
|
||||||
|
|
||||||
|
| # | Moment | What Impresses Them |
|
||||||
|
|---|--------|---------------------|
|
||||||
|
| 1 | Speed | <100ms staged, <1s full scan - fast enough for pre-commit without developer complaints |
|
||||||
|
| 2 | Attribution | Policy sources traced to signed Trust Packs - audit trail built in |
|
||||||
|
| 3 | Acknowledgments | Exceptions tracked with reason and timestamp - not `.sonar-ignore` |
|
||||||
|
| 4 | Drift Detection | "TLS version changed from 1.3 to 1.2" - caught before production |
|
||||||
|
| 5 | Compliance Export | SOC 2 evidence in minutes - JSON with full provenance |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Keyboard Shortcuts (Slides)
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|-----|--------|
|
||||||
|
| `->` / `Space` | Next slide/fragment |
|
||||||
|
| `<-` | Previous |
|
||||||
|
| `S` | Speaker notes (new window) |
|
||||||
|
| `ESC` | Overview mode |
|
||||||
|
| `B` | Blackout |
|
||||||
|
| `F` | Fullscreen |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## If Something Goes Wrong
|
||||||
|
|
||||||
|
| Problem | Recovery |
|
||||||
|
|---------|----------|
|
||||||
|
| Aphoria not found | Run `cargo build --release` in applications/aphoria |
|
||||||
|
| No violations detected | Check demo files exist in /tmp/aphoria-demo |
|
||||||
|
| Slides won't load | Check port 3001, run `npm run dev` |
|
||||||
|
| Slides won't advance | Click in the slide area first |
|
||||||
|
| Drift not showing | Ensure you ran `--persist` on both scans |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Marcus Thompson Persona Notes
|
||||||
|
|
||||||
|
**Who he is:**
|
||||||
|
- VP Platform Engineering at Series C fintech
|
||||||
|
- 400 engineers, scaling fast
|
||||||
|
- Burned by SonarQube, Snyk, Semgrep "shelfware"
|
||||||
|
- Needs proof, not promises
|
||||||
|
|
||||||
|
**What he cares about:**
|
||||||
|
- Developer velocity (won't slow down CI)
|
||||||
|
- Audit readiness (SOC 2 is on the roadmap)
|
||||||
|
- Signal vs noise (hates false positives)
|
||||||
|
- Proof of enforcement (not just "we have policies")
|
||||||
|
|
||||||
|
**What makes him skeptical:**
|
||||||
|
- "We tried Semgrep. Developers ignored it."
|
||||||
|
- "Snyk alerts are noise. Nobody reads them."
|
||||||
|
- "SonarQube was a 6-month project. Then everyone turned it off."
|
||||||
|
|
||||||
|
**What wins him over:**
|
||||||
|
- Speed (<100ms staged means pre-commit is viable)
|
||||||
|
- Attribution (policy sources traced to signed Trust Packs)
|
||||||
|
- Tracked exceptions (not .ignore files)
|
||||||
|
- Drift detection (proactive, not reactive)
|
||||||
|
- JSON export (audit evidence generation)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Last updated: 2026-02-06*
|
||||||
359
applications/aphoria-pitch/index.html
Normal file
359
applications/aphoria-pitch/index.html
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Aphoria - Code-Level Truth Linting</title>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reset.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/theme/night.css">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--r-background-color: #0f0f14;
|
||||||
|
--r-main-color: #e4e4e7;
|
||||||
|
--r-heading-color: #a1a1aa;
|
||||||
|
--r-link-color: #60a5fa;
|
||||||
|
--r-selection-background-color: #27272a;
|
||||||
|
--r-main-font-size: 32px;
|
||||||
|
}
|
||||||
|
.reveal {
|
||||||
|
font-size: var(--r-main-font-size);
|
||||||
|
}
|
||||||
|
.reveal h1 {
|
||||||
|
font-size: 2.2em;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #fafafa;
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
.reveal h2 {
|
||||||
|
font-size: 1.6em;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #fafafa;
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
margin-bottom: 0.8em;
|
||||||
|
}
|
||||||
|
.reveal h3 {
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #a1a1aa;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
.reveal p {
|
||||||
|
font-size: 0.95em;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #d4d4d8;
|
||||||
|
}
|
||||||
|
.reveal .highlight {
|
||||||
|
color: #fbbf24;
|
||||||
|
}
|
||||||
|
.reveal .muted {
|
||||||
|
color: #71717a;
|
||||||
|
}
|
||||||
|
.reveal .negative {
|
||||||
|
color: #f87171;
|
||||||
|
}
|
||||||
|
.reveal .positive {
|
||||||
|
color: #4ade80;
|
||||||
|
}
|
||||||
|
.reveal ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.reveal ul li {
|
||||||
|
margin: 0.6em 0;
|
||||||
|
padding-left: 1.2em;
|
||||||
|
position: relative;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #d4d4d8;
|
||||||
|
}
|
||||||
|
.reveal ul li::before {
|
||||||
|
content: "—";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
color: #52525b;
|
||||||
|
}
|
||||||
|
.reveal .stat-block {
|
||||||
|
background: linear-gradient(135deg, #18181b 0%, #1f1f23 100%);
|
||||||
|
border: 1px solid #27272a;
|
||||||
|
padding: 1.2em 1.6em;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin: 1.2em 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.reveal .stat-block .number {
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fbbf24;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.2em;
|
||||||
|
}
|
||||||
|
.reveal .stat-block .label {
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: #a1a1aa;
|
||||||
|
}
|
||||||
|
.reveal .demo-preview {
|
||||||
|
background: #18181b;
|
||||||
|
border: 1px solid #27272a;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1.5em;
|
||||||
|
text-align: left;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
.reveal .demo-preview code {
|
||||||
|
font-family: "SF Mono", "Fira Code", monospace;
|
||||||
|
font-size: 0.75em;
|
||||||
|
color: #60a5fa;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
.reveal .cli-preview {
|
||||||
|
font-family: "SF Mono", "Fira Code", monospace;
|
||||||
|
font-size: 0.65em;
|
||||||
|
color: #a1a1aa;
|
||||||
|
background: #0f0f14;
|
||||||
|
padding: 0.8em 1em;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 3px solid #f87171;
|
||||||
|
margin: 0.8em 0;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.reveal .cli-preview .cmd {
|
||||||
|
color: #4ade80;
|
||||||
|
}
|
||||||
|
.reveal .cli-preview .block {
|
||||||
|
color: #f87171;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.reveal .cli-preview .policy {
|
||||||
|
color: #fbbf24;
|
||||||
|
}
|
||||||
|
.reveal blockquote {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
font-style: normal;
|
||||||
|
padding: 0;
|
||||||
|
margin: 1.5em 0;
|
||||||
|
font-size: 0.85em;
|
||||||
|
color: #a1a1aa;
|
||||||
|
}
|
||||||
|
.reveal .capabilities-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 1em;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
.reveal .capability-card {
|
||||||
|
background: #18181b;
|
||||||
|
border: 1px solid #27272a;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 1em;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.reveal .capability-card h4 {
|
||||||
|
font-size: 0.8em;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fafafa;
|
||||||
|
margin: 0 0 0.4em 0;
|
||||||
|
}
|
||||||
|
.reveal .capability-card p {
|
||||||
|
font-size: 0.65em;
|
||||||
|
color: #a1a1aa;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.reveal .footer {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 1em;
|
||||||
|
left: 1em;
|
||||||
|
font-size: 0.4em;
|
||||||
|
color: #52525b;
|
||||||
|
}
|
||||||
|
.reveal .transition-slide h2 {
|
||||||
|
font-size: 1.4em;
|
||||||
|
color: #a1a1aa;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="reveal">
|
||||||
|
<div class="slides">
|
||||||
|
|
||||||
|
<!-- Slide 1: The Hook -->
|
||||||
|
<section>
|
||||||
|
<h2>SOC 2 audit prep takes <span class="highlight">180 hours</span>.<br>60% is proving "who approved what."</h2>
|
||||||
|
<div class="stat-block">
|
||||||
|
<span class="number">63%</span>
|
||||||
|
<span class="label">of security incidents trace to config drift<br>from a known-good state.</span>
|
||||||
|
</div>
|
||||||
|
<p class="fragment fade-up muted" style="font-size: 0.8em; margin-top: 1.5em;">
|
||||||
|
The problem isn't missing policies. It's proving you enforced them.
|
||||||
|
</p>
|
||||||
|
<aside class="notes">
|
||||||
|
180 hours: Based on industry surveys of Series B-D companies going through SOC 2 Type II.
|
||||||
|
60%: Most time is spent on "audit archaeology" - reconstructing who approved what.
|
||||||
|
63% stat: Industry data on security incidents caused by configuration drift.
|
||||||
|
The hook: Security teams have policies. The problem is proving enforcement with provenance.
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Slide 2: Why This Keeps Happening -->
|
||||||
|
<section>
|
||||||
|
<h2>Why this keeps happening</h2>
|
||||||
|
<ul>
|
||||||
|
<li class="fragment">AI generates code that <span class="negative">looks correct</span> but violates your internal policies</li>
|
||||||
|
<li class="fragment">Staff engineer's "best practices" wiki is <span class="negative">ignored by new hires</span></li>
|
||||||
|
<li class="fragment">"Who approved this exception?" → <span class="negative">dig through Slack for 3 hours</span></li>
|
||||||
|
</ul>
|
||||||
|
<p class="fragment muted" style="font-size: 0.75em; margin-top: 1.5em;">
|
||||||
|
Your security team writes policies. Nobody can prove they're followed.
|
||||||
|
</p>
|
||||||
|
<aside class="notes">
|
||||||
|
AI code generation: Copilot/ChatGPT code often includes InsecureSkipVerify, weak crypto, etc.
|
||||||
|
Wiki problem: Institutional knowledge trapped in documents nobody reads.
|
||||||
|
Slack archaeology: The audit trail exists, but it takes hours to reconstruct.
|
||||||
|
Marcus's pain: He's been burned by shelfware. He needs proof, not promises.
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Slide 3: Introducing Aphoria -->
|
||||||
|
<section>
|
||||||
|
<h1 style="font-size: 2.8em; font-weight: 600; letter-spacing: -0.03em;">Aphoria</h1>
|
||||||
|
<p style="font-size: 1em; color: #a1a1aa; margin-top: 0.5em;">
|
||||||
|
Code-level truth linting. Claims, not rules.
|
||||||
|
</p>
|
||||||
|
<p class="fragment muted" style="font-size: 0.75em; margin-top: 2em;">
|
||||||
|
Validate code against authoritative sources with cryptographic provenance.
|
||||||
|
</p>
|
||||||
|
<aside class="notes">
|
||||||
|
"Aphoria" = Greek for "bearing away uncertainty"
|
||||||
|
"Claims, not rules" = We don't pattern match. We validate against authoritative sources.
|
||||||
|
Cryptographic provenance = Ed25519-signed Trust Packs trace every policy to an approver.
|
||||||
|
Keep this slide brief - the next one explains the approach.
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Slide 4: Every Policy Has a Source -->
|
||||||
|
<section>
|
||||||
|
<h2>Every policy has a source</h2>
|
||||||
|
<p style="margin-bottom: 1em;">
|
||||||
|
Aphoria stores <span class="highlight">authoritative claims with provenance</span>, not regex patterns.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li class="fragment"><span class="positive">Cryptographic attribution:</span> Ed25519-signed Trust Packs trace every policy to an approver</li>
|
||||||
|
<li class="fragment"><span class="positive">Sub-second scanning:</span> <100ms pre-commit, <1s full scan. Developers won't disable it.</li>
|
||||||
|
<li class="fragment"><span class="positive">AI guardrails:</span> Catch <code>InsecureSkipVerify = true</code> before the PR</li>
|
||||||
|
</ul>
|
||||||
|
<aside class="notes">
|
||||||
|
Cryptographic attribution: Not "the linter said so." Trust Packs are Ed25519-signed with issuer provenance.
|
||||||
|
Sub-second: <100ms for staged files, <1s for full scan. Fast enough for pre-commit. Developers won't bypass it.
|
||||||
|
AI guardrails: Copilot generates insecure code. This catches it instantly.
|
||||||
|
Key differentiator: Every violation traces to a signed Trust Pack, not a regex rule.
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Slide 5: What This Enables -->
|
||||||
|
<section>
|
||||||
|
<h2>What this enables</h2>
|
||||||
|
<div class="capabilities-grid">
|
||||||
|
<div class="capability-card">
|
||||||
|
<h4>Policy Governance</h4>
|
||||||
|
<p>Security team publishes once. 400 engineers inherit instantly.</p>
|
||||||
|
</div>
|
||||||
|
<div class="capability-card">
|
||||||
|
<h4>Drift Detection</h4>
|
||||||
|
<p>"TLS config changed from 1.3 to 1.2" - caught before production.</p>
|
||||||
|
</div>
|
||||||
|
<div class="capability-card">
|
||||||
|
<h4>Compliance Export</h4>
|
||||||
|
<p>SOC 2 evidence in 15 minutes, not 3 days.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="fragment muted" style="font-size: 0.7em; margin-top: 1.2em;">
|
||||||
|
Every exception tracked with reason and timestamp.
|
||||||
|
</p>
|
||||||
|
<aside class="notes">
|
||||||
|
Policy Governance: No more "update 50 repos" - publish to StemeDB once, all scans use it.
|
||||||
|
Drift Detection: --persist mode tracks changes between scans. See what drifted.
|
||||||
|
Compliance Export: JSON output with full provenance. Feed it to your SOC 2 report.
|
||||||
|
Exceptions: Not .sonar-ignore. Tracked acknowledgments with reasons and timestamps.
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Slide 6: Demo Preview -->
|
||||||
|
<section class="transition-slide">
|
||||||
|
<h2>Here's what it looks like</h2>
|
||||||
|
<div class="demo-preview">
|
||||||
|
<p style="font-size: 0.75em; color: #a1a1aa; margin: 0 0 0.8em 0;">Terminal:</p>
|
||||||
|
<div class="cli-preview">
|
||||||
|
<span class="cmd">$ aphoria scan</span><br><br>
|
||||||
|
<span class="block">BLOCK</span> code://go/auth/tls/cert_verification<br>
|
||||||
|
Your code: TLS certificate verification is disabled (main.go:12)<br>
|
||||||
|
Regulatory: Boolean(true) (Tier 0)<br>
|
||||||
|
Action: Fix or acknowledge with: <span class="policy">aphoria ack <path> --reason "..."</span>
|
||||||
|
</div>
|
||||||
|
<p style="font-size: 0.7em; color: #71717a; margin: 0.8em 0 0 0;">
|
||||||
|
I'm going to run this exact command live...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<aside class="notes">
|
||||||
|
This is the transition slide. Show them what they're about to see.
|
||||||
|
Key points to emphasize:
|
||||||
|
- BLOCK status with clear subject path
|
||||||
|
- "Your code" vs "Regulatory" - the conflict is explicit
|
||||||
|
- Action line shows how to handle exceptions
|
||||||
|
- When Trust Pack imported, policy source also shown
|
||||||
|
Then switch to terminal for the live demo.
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Slide 7: Q&A -->
|
||||||
|
<section>
|
||||||
|
<h2>Questions</h2>
|
||||||
|
<div style="margin-top: 1.5em; text-align: left;">
|
||||||
|
<p class="muted" style="font-size: 0.7em; margin-bottom: 0.8em;">What you saw:</p>
|
||||||
|
<ul style="font-size: 0.75em;">
|
||||||
|
<li><span class="highlight">Speed</span> - <100ms staged, <1s full scan, fast enough for pre-commit</li>
|
||||||
|
<li><span class="highlight">Attribution</span> - Every policy signed by an approver</li>
|
||||||
|
<li><span class="highlight">Acknowledgments</span> - Exceptions tracked, not ignored</li>
|
||||||
|
<li><span class="highlight">Drift Detection</span> - Config changes caught before production</li>
|
||||||
|
<li><span class="highlight">Compliance Export</span> - SOC 2 evidence in 15 minutes</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<aside class="notes">
|
||||||
|
Be ready for:
|
||||||
|
- "Why not just write better Semgrep rules?" → Semgrep can't track who approved exceptions
|
||||||
|
- "What's the false positive rate?" → We check against authoritative sources, not patterns
|
||||||
|
- "I already have pre-commit hooks" → Hooks catch violations. Aphoria proves who approved the policy
|
||||||
|
- "SOC 2 certified?" → In progress. But you can generate the evidence today
|
||||||
|
- "Why not Postgres?" → You could build this. 6-9 months, 2-3 engineers. We've done the hard work
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
Aphoria
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/plugin/notes/notes.js"></script>
|
||||||
|
<script>
|
||||||
|
Reveal.initialize({
|
||||||
|
hash: true,
|
||||||
|
slideNumber: false,
|
||||||
|
controls: false,
|
||||||
|
progress: false,
|
||||||
|
transition: 'none',
|
||||||
|
transitionSpeed: 'fast',
|
||||||
|
plugins: [ RevealNotes ],
|
||||||
|
width: 1280,
|
||||||
|
height: 720,
|
||||||
|
margin: 0.1
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
13
applications/aphoria-pitch/package.json
Normal file
13
applications/aphoria-pitch/package.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "aphoria-pitch",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Aphoria enterprise pitch presentation",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "npx serve -l 3001",
|
||||||
|
"start": "npx serve -l 3001"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"serve": "^14.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1372,7 +1372,7 @@ require_validation = true # Must pass validation suite
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Phase 9: Autonomous Extractor Generation ⬜
|
## Phase 9: Autonomous Extractor Generation 🎯
|
||||||
|
|
||||||
> The system generates, tests, and deploys extractors without human approval for high-confidence patterns. This is the endgame: a fully self-improving extraction system.
|
> The system generates, tests, and deploys extractors without human approval for high-confidence patterns. This is the endgame: a fully self-improving extraction system.
|
||||||
|
|
||||||
@ -1392,87 +1392,296 @@ If FP rate < 5%: auto-deploy
|
|||||||
If FP rate spikes: auto-rollback
|
If FP rate spikes: auto-rollback
|
||||||
```
|
```
|
||||||
|
|
||||||
### 9.1 Autonomous Promotion ⬜
|
---
|
||||||
|
|
||||||
| Task | Description |
|
## Phase 7.8: LLM Prompt Evaluation ✅
|
||||||
|------|-------------|
|
|
||||||
| High-confidence threshold | Skip human review for >0.95 confidence |
|
|
||||||
| Project threshold | Require >10 projects for autonomous |
|
|
||||||
| Validation strictness | Stricter validation for autonomous |
|
|
||||||
|
|
||||||
```rust
|
> Measure and improve LLM extraction quality through golden fixtures and regression detection. Essential for prompt engineering without breaking existing quality.
|
||||||
fn should_auto_promote(pattern: &LearnedPattern, validation: &ValidationResult) -> bool {
|
|
||||||
pattern.avg_confidence > 0.95 &&
|
### Vision
|
||||||
pattern.project_hashes.len() > 10 &&
|
|
||||||
validation.positive_failures.is_empty() &&
|
```
|
||||||
!validation.false_positive_warning &&
|
Golden Fixtures (TOML) Evaluation Harness
|
||||||
!validation.performance_warning
|
├── tls-001: verify=False ├── Load fixtures
|
||||||
}
|
├── jwt-001: algorithm=none --> ├── Run extraction (live/cached/mock)
|
||||||
|
└── secrets-001: hardcoded key ├── Match against expectations
|
||||||
|
├── Compute precision/recall/F1
|
||||||
|
└── Compare to baseline (regression detection)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 9.2 Shadow Mode Testing ⬜
|
### 7.8.1 Fixture Format ✅
|
||||||
|
|
||||||
| Task | Description |
|
| Task | Status |
|
||||||
|------|-------------|
|
|------|--------|
|
||||||
| Shadow execution | Run new extractor alongside existing |
|
| `Fixture` type | ✅ `eval/fixture.rs` — TOML-based test cases |
|
||||||
| Metrics collection | Track matches, FP rate, performance |
|
| `ExpectedClaim` | ✅ Subject/predicate/value expectations |
|
||||||
| Comparison report | Compare shadow vs production results |
|
| `must_contain` | ✅ Claims that MUST be extracted (recall) |
|
||||||
| Promotion criteria | Promote if metrics meet threshold |
|
| `must_not_contain` | ✅ Claims that MUST NOT appear (precision) |
|
||||||
|
| `FixtureLoader` | ✅ Load fixtures from directory tree |
|
||||||
|
| `CorpusManifest` | ✅ Corpus metadata + baseline metrics |
|
||||||
|
| Validation | ✅ Duplicate ID, empty content, missing expectations |
|
||||||
|
|
||||||
```rust
|
```toml
|
||||||
pub struct ShadowTest {
|
# tests/llm_fixtures/tls/tls-001-disabled-verification.toml
|
||||||
extractor: DeclarativeExtractor,
|
[metadata]
|
||||||
start_time: DateTime<Utc>,
|
id = "tls-001"
|
||||||
scans_completed: u32,
|
name = "TLS verification disabled in Python requests"
|
||||||
matches: u32,
|
category = "tls"
|
||||||
confirmed_true_positives: u32,
|
language = "python"
|
||||||
confirmed_false_positives: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ShadowTest {
|
[input]
|
||||||
fn false_positive_rate(&self) -> f32 {
|
filename = "api_client.py"
|
||||||
self.confirmed_false_positives as f32 / self.matches as f32
|
content = """
|
||||||
}
|
response = requests.get(url, verify=False)
|
||||||
|
"""
|
||||||
|
|
||||||
fn should_promote(&self) -> bool {
|
[expected]
|
||||||
self.scans_completed >= 100 &&
|
must_contain = [
|
||||||
self.false_positive_rate() < 0.05
|
{ subject = "tls/cert_verification", predicate = "enabled", value = false }
|
||||||
}
|
]
|
||||||
}
|
must_not_contain = [
|
||||||
|
{ subject = "tls/cert_verification", predicate = "enabled", value = true }
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
### 9.3 Auto-Rollback ⬜
|
### 7.8.2 Claim Matching ✅
|
||||||
|
|
||||||
| Task | Description |
|
| Task | Status |
|
||||||
|------|-------------|
|
|------|--------|
|
||||||
| Anomaly detection | Detect FP rate spikes |
|
| `ClaimMatcher` | ✅ `eval/matcher.rs` — Flexible claim comparison |
|
||||||
| Rollback trigger | Auto-disable if FP > 10% |
|
| Tail-path matching | ✅ Last 2 segments for subject comparison |
|
||||||
| Notification | Alert on rollback |
|
| Type coercion | ✅ Boolean↔string ("true"/"yes"), number↔string |
|
||||||
| Quarantine | Move extractor to review queue |
|
| Confidence thresholds | ✅ Optional min_confidence per expectation |
|
||||||
|
| `count_false_positives()` | ✅ Detect unexpected claims |
|
||||||
|
|
||||||
```rust
|
### 7.8.3 Metrics Computation ✅
|
||||||
async fn check_extractor_health(extractor_id: &str, metrics: &Metrics) -> Action {
|
|
||||||
let recent_fp_rate = metrics.false_positive_rate_last_24h(extractor_id);
|
|
||||||
let baseline_fp_rate = metrics.false_positive_rate_baseline(extractor_id);
|
|
||||||
|
|
||||||
if recent_fp_rate > 0.10 {
|
| Task | Status |
|
||||||
Action::Rollback { reason: "FP rate exceeded 10%" }
|
|------|--------|
|
||||||
} else if recent_fp_rate > baseline_fp_rate * 2.0 {
|
| `Metrics` | ✅ `eval/metrics.rs` — Aggregate evaluation metrics |
|
||||||
Action::Rollback { reason: "FP rate doubled from baseline" }
|
| Precision/Recall/F1 | ✅ Standard information retrieval metrics |
|
||||||
} else {
|
| Per-category breakdown | ✅ Metrics by fixture category |
|
||||||
Action::Continue
|
| Cost estimation | ✅ Token-based cost tracking |
|
||||||
}
|
| `BaselineComparison` | ✅ Compare current run to stored baseline |
|
||||||
}
|
| Regression detection | ✅ Flag if F1/precision/recall drop > threshold |
|
||||||
|
|
||||||
|
### 7.8.4 Evaluation Harness ✅
|
||||||
|
|
||||||
|
| Task | Status |
|
||||||
|
|------|--------|
|
||||||
|
| `EvalHarness` | ✅ `eval/harness.rs` — Orchestrates evaluation runs |
|
||||||
|
| `EvalMode::Live` | ✅ Real LLM API calls |
|
||||||
|
| `EvalMode::Cached` | ✅ Use cached responses (deterministic CI) |
|
||||||
|
| `EvalMode::Mock` | ✅ No LLM, tests harness itself |
|
||||||
|
| `EvalVerdict` | ✅ Pass, Regression, Review, Error |
|
||||||
|
| `update_baseline()` | ✅ Save current metrics as new baseline |
|
||||||
|
|
||||||
|
### 7.8.5 Report Generation ✅
|
||||||
|
|
||||||
|
| Task | Status |
|
||||||
|
|------|--------|
|
||||||
|
| `Report` | ✅ `eval/report.rs` — Multi-format output |
|
||||||
|
| Table format | ✅ Terminal tables with color-coded results |
|
||||||
|
| JSON format | ✅ Machine-readable for CI/CD integration |
|
||||||
|
| Markdown format | ✅ Documentation and PR comments |
|
||||||
|
| Failed fixture details | ✅ Shows unmatched expectations with rationale |
|
||||||
|
|
||||||
|
### 7.8.6 CLI Commands ✅
|
||||||
|
|
||||||
|
| Task | Status |
|
||||||
|
|------|--------|
|
||||||
|
| `aphoria eval run` | ✅ Run evaluation against fixtures |
|
||||||
|
| `aphoria eval baseline` | ✅ Show current baseline metrics |
|
||||||
|
| `aphoria eval update-baseline` | ✅ Update baseline (--force required) |
|
||||||
|
| `aphoria eval list-fixtures` | ✅ List available fixtures by category |
|
||||||
|
| `aphoria eval validate-fixtures` | ✅ Validate fixture format |
|
||||||
|
| `--fail-on-regression` | ✅ Exit code 1 if regression detected |
|
||||||
|
| `--threshold` | ✅ Configurable regression threshold (default 5%) |
|
||||||
|
| `--mode` | ✅ live, cached, or mock |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run evaluation in mock mode
|
||||||
|
aphoria eval run --fixtures tests/llm_fixtures --mode mock
|
||||||
|
|
||||||
|
# CI: fail on regression
|
||||||
|
aphoria eval run --mode cached --fail-on-regression --threshold 0.05
|
||||||
|
|
||||||
|
# Update baseline after prompt improvements
|
||||||
|
aphoria eval update-baseline --fixtures tests/llm_fixtures --force
|
||||||
|
|
||||||
|
# List fixtures by category
|
||||||
|
aphoria eval list-fixtures --category tls
|
||||||
```
|
```
|
||||||
|
|
||||||
### 9.4 Cross-Project Learning ⬜
|
### 7.8.7 Seed Fixtures ✅
|
||||||
|
|
||||||
| Task | Description |
|
| Category | Fixture | Description |
|
||||||
|------|-------------|
|
|----------|---------|-------------|
|
||||||
| Hosted pattern sync | Patterns from all projects aggregate on server |
|
| tls | tls-001 | Python requests verify=False |
|
||||||
| Global promotion | Promote patterns seen across many orgs |
|
| tls | tls-002 | Node.js TLSv1 deprecated protocol |
|
||||||
| Privacy preservation | Only normalized patterns shared, no code |
|
| jwt | jwt-001 | Algorithm 'none' allowed |
|
||||||
| Opt-in distribution | Orgs can opt-in to receive community extractors |
|
| jwt | jwt-002 | Go WithoutClaimsValidation |
|
||||||
|
| secrets | secrets-001 | Hardcoded API key |
|
||||||
|
| secrets | secrets-002 | High-entropy JWT in config |
|
||||||
|
| auth | auth-001 | Debug authentication bypass |
|
||||||
|
| negative | negative-001 | Safe TLS config (no findings expected) |
|
||||||
|
| negative | negative-002 | Env-loaded secrets (no findings expected) |
|
||||||
|
| edge | edge-001 | Empty file edge case |
|
||||||
|
|
||||||
|
**Files:** `eval/mod.rs`, `eval/fixture.rs`, `eval/matcher.rs`, `eval/metrics.rs`, `eval/harness.rs`, `eval/report.rs`, `handlers/eval.rs`, `cli.rs`, `tests/llm_fixtures/`
|
||||||
|
|
||||||
|
**Documentation:** [docs/llm-optimization/](docs/llm-optimization/index.md) — Full optimization playbook with decision trees, research templates, and baseline tracking.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 9.1 Autonomous Promotion ✅
|
||||||
|
|
||||||
|
| Task | Description | Status |
|
||||||
|
|------|-------------|--------|
|
||||||
|
| `AutonomousConfig` | Configuration with kill switch (enabled: false default) | ✅ |
|
||||||
|
| High-confidence threshold | Skip human review for >0.95 confidence | ✅ |
|
||||||
|
| Project threshold | Require >10 projects for autonomous | ✅ |
|
||||||
|
| Validation strictness | Zero failures, zero warnings required | ✅ |
|
||||||
|
| `should_auto_promote()` | Decision logic on `PromotionCandidate` | ✅ |
|
||||||
|
| `auto_promotion_blockers()` | Explains why pattern can't be auto-promoted | ✅ |
|
||||||
|
| `AutonomousAuditLog` | JSONL audit trail for all decisions | ✅ |
|
||||||
|
| `smart_auto_promote_all()` | Pipeline integration with audit logging | ✅ |
|
||||||
|
| YAML header enhancement | "AUTO-PROMOTED" + "Approved by: autonomous" | ✅ |
|
||||||
|
| CLI command | `aphoria extractors auto-promote [--dry-run]` | ✅ |
|
||||||
|
|
||||||
|
**Safety Features:**
|
||||||
|
- Kill switch: `enabled: false` by default (opt-in only)
|
||||||
|
- Auditability: All decisions logged to `~/.aphoria/audit/autonomous-decisions.jsonl`
|
||||||
|
- Reversibility: Can delete YAML + reset pattern.promoted
|
||||||
|
- Blast radius: One pattern = one YAML file
|
||||||
|
- Traceability: YAML header shows approval source
|
||||||
|
|
||||||
|
**Files:** `config/types/autonomous.rs`, `promotion/audit.rs`, `promotion/types.rs`, `promotion/pipeline.rs`, `promotion/writer.rs`, `handlers/extractors.rs`
|
||||||
|
|
||||||
|
**Configuration:**
|
||||||
|
```toml
|
||||||
|
[autonomous]
|
||||||
|
enabled = true # Master switch (default: false)
|
||||||
|
min_confidence = 0.95 # Stricter than standard 0.8
|
||||||
|
min_projects = 10 # Stricter than standard 5
|
||||||
|
require_zero_failures = true
|
||||||
|
require_zero_warnings = true
|
||||||
|
audit_log = true
|
||||||
|
audit_dir = "~/.aphoria/audit/"
|
||||||
|
```
|
||||||
|
|
||||||
|
**CLI Usage:**
|
||||||
|
```bash
|
||||||
|
# Preview what would be auto-promoted
|
||||||
|
aphoria extractors auto-promote --dry-run
|
||||||
|
|
||||||
|
# Run autonomous promotion
|
||||||
|
aphoria extractors auto-promote
|
||||||
|
|
||||||
|
# Override thresholds
|
||||||
|
aphoria extractors auto-promote --min-confidence 0.97 --min-projects 15
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9.2 Shadow Mode Testing ✅
|
||||||
|
|
||||||
|
| Task | Description | Status |
|
||||||
|
|------|-------------|--------|
|
||||||
|
| `ShadowConfig` | Configuration for shadow mode (min_scans, max_fp_rate, rollback_threshold) | ✅ |
|
||||||
|
| `ShadowTest`, `ShadowStatus`, `ShadowMetrics` | Core types for tracking shadow extractors | ✅ |
|
||||||
|
| `ShadowStore` | JSONL persistence for tests, matches, and decisions | ✅ |
|
||||||
|
| `ShadowExtractorRegistry` | Loads shadow extractors from learned/ directory | ✅ |
|
||||||
|
| `ShadowExecutor` | Runs shadow extractors during scans, stores matches separately | ✅ |
|
||||||
|
| `FeedbackCollector` | TP/FP feedback collection and metrics update | ✅ |
|
||||||
|
| `GraduationManager` | Shadow → production promotion and rollback logic | ✅ |
|
||||||
|
| CLI commands | `shadow-status`, `feedback`, `graduate`, `rollback` | ✅ |
|
||||||
|
|
||||||
|
**Safety Features:**
|
||||||
|
- Shadow isolation: Matches stored separately, not in production output
|
||||||
|
- Metrics transparency: FP rate visible via `shadow-status`
|
||||||
|
- Graduation gate: Must meet min_scans (100) + max_fp_rate (5%) + feedback exists
|
||||||
|
- Manual control: `rollback` command for immediate removal
|
||||||
|
- Audit trail: All decisions logged to `decisions.jsonl`
|
||||||
|
|
||||||
|
**Files:** `shadow/mod.rs`, `shadow/types.rs`, `shadow/store.rs`, `shadow/registry.rs`, `shadow/executor.rs`, `shadow/feedback.rs`, `shadow/graduation.rs`, `handlers/shadow.rs`, `config/types/shadow.rs`
|
||||||
|
|
||||||
|
**Configuration:**
|
||||||
|
```toml
|
||||||
|
[shadow]
|
||||||
|
enabled = true # Shadow mode on by default
|
||||||
|
min_scans = 100 # Scans before graduation eligible
|
||||||
|
max_fp_rate = 0.05 # Maximum FP rate for graduation
|
||||||
|
rollback_threshold = 0.15 # FP rate that triggers rollback
|
||||||
|
retention_days = 30 # Days to retain shadow data
|
||||||
|
```
|
||||||
|
|
||||||
|
**CLI Usage:**
|
||||||
|
```bash
|
||||||
|
# View shadow test status
|
||||||
|
aphoria extractors shadow-status [-v]
|
||||||
|
|
||||||
|
# Provide TP/FP feedback on matches
|
||||||
|
aphoria extractors feedback <test-name> [--limit 10]
|
||||||
|
|
||||||
|
# Graduate shadow test to production
|
||||||
|
aphoria extractors graduate <test-name> [--force]
|
||||||
|
|
||||||
|
# Rollback a shadow test
|
||||||
|
aphoria extractors rollback <test-name> --reason "too many FPs"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tests:** 44 tests covering types, store, registry, executor, feedback, graduation, and auto-rollback.
|
||||||
|
|
||||||
|
### 9.3 Auto-Rollback ✅
|
||||||
|
|
||||||
|
| Task | Description | Status |
|
||||||
|
|------|-------------|--------|
|
||||||
|
| `auto_rollback_enabled` config | Toggle to enable/disable auto-rollback (default: true) | ✅ |
|
||||||
|
| Feedback-time check | Auto-rollback triggered immediately after FP feedback | ✅ |
|
||||||
|
| `FeedbackWithRollback` return | `record_feedback()` returns rollback info | ✅ |
|
||||||
|
| `AutoRollbackResult` | Track checked count, rolled back names, errors | ✅ |
|
||||||
|
| CLI command | `aphoria extractors auto-check` for manual batch checking | ✅ |
|
||||||
|
| Audit trail | Decision logged as `ShadowDecisionKind::AutoRollback` | ✅ |
|
||||||
|
| YAML deletion | Extractor file deleted from learned/ on rollback | ✅ |
|
||||||
|
|
||||||
|
**Safety Features:**
|
||||||
|
- Toggle: `auto_rollback_enabled` can disable feature for testing or manual-only workflows
|
||||||
|
- Threshold configurable: `rollback_threshold` in config (default: 15%)
|
||||||
|
- Minimum reviews: Requires 10+ reviewed matches before auto-rollback triggers
|
||||||
|
- Audit trail: All auto-rollback decisions logged to `decisions.jsonl`
|
||||||
|
- CLI fallback: `auto-check` command for manual verification
|
||||||
|
|
||||||
|
**Files:** `shadow/feedback.rs`, `shadow/graduation.rs`, `config/types/shadow.rs`, `handlers/shadow.rs`, `cli.rs`
|
||||||
|
|
||||||
|
**Configuration:**
|
||||||
|
```toml
|
||||||
|
[shadow]
|
||||||
|
enabled = true
|
||||||
|
auto_rollback_enabled = true # NEW: Enable automatic rollback (default: true)
|
||||||
|
rollback_threshold = 0.15 # FP rate that triggers auto-rollback
|
||||||
|
```
|
||||||
|
|
||||||
|
**CLI Usage:**
|
||||||
|
```bash
|
||||||
|
# Automatic: Rollback happens immediately when feedback pushes FP rate over threshold
|
||||||
|
aphoria extractors feedback <test-name> --limit 10
|
||||||
|
# If FP rate exceeds 15%, you'll see:
|
||||||
|
# ⚠️ AUTO-ROLLBACK TRIGGERED: <extractor-name>
|
||||||
|
|
||||||
|
# Manual batch check: Scan all active tests and rollback any over threshold
|
||||||
|
aphoria extractors auto-check
|
||||||
|
# Output: "⚠️ Auto-rolled back 1 of 5 shadow test(s): ..."
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tests:** 3 new tests covering auto-rollback triggering, disabled toggle, and threshold boundary.
|
||||||
|
|
||||||
|
### 9.4 Cross-Project Learning ✅
|
||||||
|
|
||||||
|
| Task | Description | Status |
|
||||||
|
|------|-------------|--------|
|
||||||
|
| Hosted pattern sync | Patterns from all projects aggregate on server | ✅ |
|
||||||
|
| Global promotion | Promote patterns seen across many orgs | ✅ |
|
||||||
|
| Privacy preservation | Only normalized patterns shared, no code | ✅ |
|
||||||
|
| Opt-in distribution | Orgs can opt-in to receive community extractors | ✅ |
|
||||||
|
|
||||||
```
|
```
|
||||||
Org A: Pattern seen in 3 projects → shared to hosted
|
Org A: Pattern seen in 3 projects → shared to hosted
|
||||||
@ -1486,29 +1695,91 @@ Promotes to community extractor
|
|||||||
All orgs receive new extractor (if opted in)
|
All orgs receive new extractor (if opted in)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 9.5 Extractor Versioning ⬜
|
**Implementation:**
|
||||||
|
- `CrossProjectConfig` with opt-in flags (`contribute_patterns`, `receive_community`)
|
||||||
|
- `PatternSyncer` for uploading anonymized patterns to hosted server
|
||||||
|
- `CommunityExtractorLoader` for pulling community extractors as YAML files
|
||||||
|
- BLAKE3 hashing for pattern deduplication and org anonymization
|
||||||
|
- Privacy guarantees: `normalized_pattern` shared, but NOT `example_code` or `project_hashes`
|
||||||
|
- CLI commands: `aphoria patterns sync`, `aphoria patterns status`, `aphoria patterns pull-community`
|
||||||
|
|
||||||
| Task | Description |
|
**Files:** `config/types/cross_project.rs`, `community/pattern_syncer.rs`, `community/extractor_loader.rs`, `handlers/patterns.rs`
|
||||||
|------|-------------|
|
|
||||||
| Version tracking | Track which version caught which issues |
|
|
||||||
| Changelog | Record changes between versions |
|
|
||||||
| Rollback support | Revert to previous version |
|
|
||||||
| A/B metrics | Compare versions side-by-side |
|
|
||||||
|
|
||||||
|
**Tests:** 7 new tests covering pattern hashing, subject exclusion, anonymization, and extractor loading.
|
||||||
|
|
||||||
|
### 9.5 Extractor Versioning ✅
|
||||||
|
|
||||||
|
| Task | Description | Status |
|
||||||
|
|------|-------------|--------|
|
||||||
|
| Version tracking | Track which version caught which issues | ✅ `ExtractorVersion` + `VersionStore` |
|
||||||
|
| Changelog | Record changes between versions | ✅ `ExtractorChangelog` + `ChangelogEntry` |
|
||||||
|
| Rollback support | Revert to previous version | ✅ `aphoria extractors rollback-version` |
|
||||||
|
| A/B metrics | Compare versions side-by-side | ✅ `aphoria extractors compare` + `compute_metrics_delta()` |
|
||||||
|
| CLI commands | versions, compare, rollback-version | ✅ Full CLI implementation |
|
||||||
|
| Tests | Unit tests for all components | ✅ 15+ version/changelog tests |
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- `promotion/version.rs` - Core types (`ExtractorVersion`, `ChangelogEntry`, `MetricsDelta`, `ExtractorChangelog`, `VersionStore`)
|
||||||
|
- `promotion/writer.rs` - Versioned YAML output (`write_versioned()`)
|
||||||
|
- `promotion/types.rs` - Version field in `PromotionMetadata`
|
||||||
|
- `handlers/extractors.rs` - CLI handlers (`handle_versions`, `handle_compare`, `handle_rollback_version`)
|
||||||
|
- `cli.rs` - CLI commands (`Versions`, `Compare`, `RollbackVersion`)
|
||||||
|
|
||||||
|
**CLI Usage:**
|
||||||
|
```bash
|
||||||
|
# List versions
|
||||||
|
aphoria extractors versions learned_tls_min_version
|
||||||
|
# Version History: learned_tls_min_version
|
||||||
|
# Version Date Changes
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# 2 2026-03-15 Added support for YAML configs
|
||||||
|
# 1 2026-02-01 Initial promotion from learned pattern
|
||||||
|
|
||||||
|
# Compare versions
|
||||||
|
aphoria extractors compare learned_tls_min_version -a 1 -b 2
|
||||||
|
# Comparison: learned_tls_min_version v1 vs v2
|
||||||
|
# Matches +15%
|
||||||
|
# False Positives -3%
|
||||||
|
|
||||||
|
# Rollback
|
||||||
|
aphoria extractors rollback-version learned_tls_min_version --version 1 --reason "v2 edge case bug"
|
||||||
|
# Rolled back learned_tls_min_version to v1
|
||||||
|
```
|
||||||
|
|
||||||
|
**YAML Output:**
|
||||||
```yaml
|
```yaml
|
||||||
# .aphoria/extractors/learned/tls_min_version_const.yaml
|
# Generated from learned pattern. Review before editing.
|
||||||
|
# Pattern ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
||||||
|
# Version: 2 (previous: 1)
|
||||||
|
# Promoted: 2026-03-15 14:30:00 UTC
|
||||||
|
|
||||||
|
name: learned_tls_min_version
|
||||||
|
description: TLS minimum version set to deprecated value
|
||||||
version: 2
|
version: 2
|
||||||
previous_version: 1
|
previous_version: 1
|
||||||
|
languages:
|
||||||
|
- rust
|
||||||
|
- go
|
||||||
|
pattern: '(?i)tls_?min_?(version)?\s*[:=]\s*["\']?(?P<value>1\.[01])["\']?'
|
||||||
|
claim:
|
||||||
|
subject: tls/min_version
|
||||||
|
predicate: version
|
||||||
|
value_from_match: true
|
||||||
|
confidence: 0.97
|
||||||
|
metadata:
|
||||||
|
source: learned
|
||||||
|
pattern_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
|
||||||
|
version: 2
|
||||||
changelog:
|
changelog:
|
||||||
- version: 2
|
- version: 2
|
||||||
date: 2026-03-15
|
date: 2026-03-15
|
||||||
changes: "Added support for YAML configs"
|
changes: "Added support for YAML configs"
|
||||||
metrics:
|
metrics:
|
||||||
matches: +15%
|
matches: "+15%"
|
||||||
false_positives: -3%
|
false_positives: "-3%"
|
||||||
- version: 1
|
- version: 1
|
||||||
date: 2026-02-10
|
date: 2026-02-01
|
||||||
changes: "Initial auto-generated version"
|
changes: "Initial promotion from learned pattern"
|
||||||
```
|
```
|
||||||
|
|
||||||
### 9.6 Configuration ⬜
|
### 9.6 Configuration ⬜
|
||||||
@ -1554,16 +1825,27 @@ contribute_patterns = true # Share patterns to community
|
|||||||
| **7.5** | **LLM-in-the-Loop Extraction (Gemini)** | Phase 7 | ✅ |
|
| **7.5** | **LLM-in-the-Loop Extraction (Gemini)** | Phase 7 | ✅ |
|
||||||
| **7.6** | **Pattern Learning Store** | Phase 7.5 | ✅ |
|
| **7.6** | **Pattern Learning Store** | Phase 7.5 | ✅ |
|
||||||
| **7.7** | **Pattern → Extractor Promotion** | Phase 7.6 | ✅ |
|
| **7.7** | **Pattern → Extractor Promotion** | Phase 7.6 | ✅ |
|
||||||
| 8 | Enterprise Extractors (MVP: 8.1, 8.6, 8.11) | Phase 7.5 | ✅ |
|
| **7.8** | **LLM Prompt Evaluation** | Phase 7.5 | ✅ |
|
||||||
| **9** | **Autonomous Extractor Generation** | Phase 8 | ⬜ |
|
| 8 | Enterprise Extractors (8.1-8.11) | Phase 7.5 | ✅ |
|
||||||
|
| **8.2** | **Framework-Specific Extractors (10 frameworks)** | Phase 8 | ✅ |
|
||||||
|
| **9.1** | **Autonomous Promotion** | Phase 8 | ✅ |
|
||||||
|
| **9.2** | **Shadow Mode Testing** | Phase 9.1 | ✅ |
|
||||||
|
| **9.3** | **Auto-Rollback** | Phase 9.2 | ✅ |
|
||||||
|
| **9.4** | **Cross-Project Learning** | Phase 9.1 | ✅ |
|
||||||
|
| **9.5** | **Extractor Versioning** | Phase 9.4 | ✅ |
|
||||||
|
|
||||||
**Current state:**
|
**Current state:**
|
||||||
- Phases 0-3, 4.5, 4A-4E, 5, 5.6, 6, 7, 7.5, 7.6, 7.7, 8 (MVP) complete (clippy clean)
|
- Phases 0-3, 4.5, 4A-4E, 5, 5.6, 6, 7, 7.5, 7.6, 7.7, 7.8, 8, 9.1, 9.2, 9.3, 9.4, 9.5 complete (clippy clean)
|
||||||
- Full corpus: RFC, OWASP, Vendor sources
|
- Full corpus: RFC, OWASP, Vendor sources
|
||||||
- 25 extractors including security (weak_crypto, command_injection, sql_injection, high_entropy_secrets, auth_bypass, insecure_cookies, path_traversal, unvalidated_redirects, weak_password, security_headers, insecure_deserialization, ssrf, orm_injection, xxe)
|
- **36 extractors** including:
|
||||||
|
- Security: weak_crypto, command_injection, sql_injection, high_entropy_secrets, auth_bypass, insecure_cookies, path_traversal, unvalidated_redirects, weak_password, security_headers, insecure_deserialization, ssrf, orm_injection, xxe
|
||||||
|
- Framework-specific: django, express, flask, fastapi, nestjs, nextjs, spring, laravel, rails, aspnet
|
||||||
- Trust Packs: signed policy bundles with import/export
|
- Trust Packs: signed policy bundles with import/export
|
||||||
- Ephemeral mode: 40x faster for CI
|
- Ephemeral mode: 40x faster for CI
|
||||||
- Observation write-back: `--sync` records novel claims as Tier 4 project memory
|
- Observation write-back: `--sync` records novel claims as Tier 4 project memory
|
||||||
|
- **Autonomous promotion**: High-confidence patterns (>0.95, 10+ projects) can skip human review with full audit trail
|
||||||
|
- **Shadow mode testing**: Auto-promoted extractors run in shadow mode to measure FP rate before graduation
|
||||||
|
- **Auto-rollback**: Shadow extractors exceeding FP threshold (15%) are automatically rolled back
|
||||||
- Drift detection: Detects changes from prior observations
|
- Drift detection: Detects changes from prior observations
|
||||||
- Staged scanning: `--staged` flag for fast pre-commit hooks
|
- Staged scanning: `--staged` flag for fast pre-commit hooks
|
||||||
- Hosted mode: Team aggregation via central StemeDB server
|
- Hosted mode: Team aggregation via central StemeDB server
|
||||||
@ -1571,11 +1853,13 @@ contribute_patterns = true # Share patterns to community
|
|||||||
- Community Corpus: Opt-in anonymous pattern sharing with privacy-preserving anonymization
|
- Community Corpus: Opt-in anonymous pattern sharing with privacy-preserving anonymization
|
||||||
- Declarative Extractors: TOML-defined custom extractors without Rust code
|
- Declarative Extractors: TOML-defined custom extractors without Rust code
|
||||||
- LLM Extraction: Gemini-powered semantic claim extraction for high-value files
|
- LLM Extraction: Gemini-powered semantic claim extraction for high-value files
|
||||||
- Enterprise Extractors: High-entropy secrets, auth bypass, insecure cookies, path traversal, unvalidated redirects, weak passwords, security headers, insecure deserialization, SSRF, ORM injection, XXE
|
|
||||||
- Pattern Learning: LLM-extracted claims recorded for promotion to declarative extractors
|
- Pattern Learning: LLM-extracted claims recorded for promotion to declarative extractors
|
||||||
- Pattern Promotion: CLI workflow to promote learned patterns to declarative extractors with Gemini regex generation and validation
|
- Pattern Promotion: CLI workflow to promote learned patterns to declarative extractors with Gemini regex generation and validation
|
||||||
|
- **LLM Prompt Evaluation**: Golden fixtures with precision/recall metrics, baseline comparison, and regression detection for prompt engineering
|
||||||
|
- **Cross-Project Learning**: Privacy-preserving pattern sync to hosted server, community extractor pull, BLAKE3-based deduplication, opt-in sharing with `CrossProjectConfig`
|
||||||
|
- **Extractor Versioning**: Version tracking with changelogs, safe rollback to previous versions, A/B metrics comparison between versions via `VersionStore`
|
||||||
|
|
||||||
**Next:** Phase 8 (full) → 9 (Self-Learning Extraction System)
|
**Phase 9 Complete!** Autonomous Generation pipeline is fully self-improving.
|
||||||
|
|
||||||
### The Self-Learning Vision
|
### The Self-Learning Vision
|
||||||
|
|
||||||
@ -1588,9 +1872,20 @@ Phase 7.6: Pattern Learning (remember what LLM finds) ✅ COMPLETE
|
|||||||
↓
|
↓
|
||||||
Phase 7.7: Pattern Promotion (patterns → extractors) ✅ COMPLETE
|
Phase 7.7: Pattern Promotion (patterns → extractors) ✅ COMPLETE
|
||||||
↓
|
↓
|
||||||
Phase 8: Enterprise Extractors (generated + curated) ✅ MVP (8.1, 8.6, 8.11)
|
Phase 7.8: LLM Prompt Evaluation (measure & improve) ✅ COMPLETE
|
||||||
↓
|
↓
|
||||||
Phase 9: Autonomous Generation (fully self-improving) ⬜ NEXT
|
Phase 8: Enterprise Extractors (36 total) ✅ COMPLETE
|
||||||
|
├── 8.1: High-entropy secrets ✅
|
||||||
|
├── 8.2: Framework extractors (10 frameworks) ✅
|
||||||
|
├── 8.3: Config deep parsing ✅
|
||||||
|
├── 8.4-8.11: Security patterns ✅
|
||||||
|
↓
|
||||||
|
Phase 9: Autonomous Generation (fully self-improving) ✅ COMPLETE
|
||||||
|
├── 9.1: Autonomous Promotion ✅ COMPLETE
|
||||||
|
├── 9.2: Shadow Mode Testing ✅ COMPLETE
|
||||||
|
├── 9.3: Auto-Rollback ✅ COMPLETE
|
||||||
|
├── 9.4: Cross-Project Learning ✅ COMPLETE
|
||||||
|
└── 9.5: Extractor Versioning ✅ COMPLETE
|
||||||
```
|
```
|
||||||
|
|
||||||
**The endgame:** Every PR teaches Aphoria. After a month, it knows your security patterns better than your team does.
|
**The endgame:** Every PR teaches Aphoria. After a month, it knows your security patterns better than your team does.
|
||||||
@ -1661,11 +1956,30 @@ max_length = 200 # Maximum string length
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 8.2 Framework-Specific Extractors ⬜
|
### 8.2 Framework-Specific Extractors ✅
|
||||||
|
|
||||||
**Impact:** HIGH | **Effort:** HIGH
|
**Impact:** HIGH | **Effort:** HIGH | **Status:** Complete
|
||||||
|
|
||||||
Generic patterns miss framework-specific misconfigurations. Enterprise codebases use frameworks.
|
**Research Document:** [`docs/architecture/framework-security-extractors.md`](./docs/architecture/framework-security-extractors.md)
|
||||||
|
|
||||||
|
All 10 framework-specific extractors implemented and tested:
|
||||||
|
|
||||||
|
| Framework | Extractor | Languages | Tests |
|
||||||
|
|-----------|-----------|-----------|-------|
|
||||||
|
| Spring Boot | `spring_security` | Java, YAML, Properties | 7 |
|
||||||
|
| Django | `django_security` | Python | 7 |
|
||||||
|
| Express.js | `express_security` | JavaScript, TypeScript | 5 |
|
||||||
|
| Rails | `rails_security` | Ruby, YAML | 6 |
|
||||||
|
| ASP.NET Core | `aspnet_security` | C# (via regex), JSON | 6 |
|
||||||
|
| Laravel | `laravel_security` | PHP (via regex) | 5 |
|
||||||
|
| FastAPI | `fastapi_security` | Python | 5 |
|
||||||
|
| Next.js | `nextjs_security` | JavaScript, TypeScript | 5 |
|
||||||
|
| Flask | `flask_security` | Python | 6 |
|
||||||
|
| NestJS | `nestjs_security` | TypeScript | 5 |
|
||||||
|
|
||||||
|
**Total:** 10 extractors, 57+ tests, 100+ patterns
|
||||||
|
|
||||||
|
**Files:** `extractors/{django,express,flask,fastapi,nestjs,nextjs,spring,laravel,rails,aspnet}_security.rs`
|
||||||
|
|
||||||
#### 8.2.1 Spring Boot Security
|
#### 8.2.1 Spring Boot Security
|
||||||
```yaml
|
```yaml
|
||||||
@ -1714,38 +2028,33 @@ config.action_dispatch.cookies_same_site_protection = :none
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 8.3 Config File Deep Parsing ⬜
|
### 8.3 Config File Deep Parsing ✅
|
||||||
|
|
||||||
**Impact:** HIGH | **Effort:** MEDIUM
|
**Impact:** HIGH | **Effort:** MEDIUM | **Status:** Complete
|
||||||
|
|
||||||
Current extractors use regex on config files. This misses:
|
| Task | Status |
|
||||||
- Nested structures
|
|------|--------|
|
||||||
- Environment-specific overrides
|
| `ConfigValue` enum | ✅ `extractors/config_parser.rs` |
|
||||||
- Comments that disable security
|
| YAML/JSON/TOML parsers | ✅ Using `serde_yaml`, `serde_json`, `toml` |
|
||||||
|
| Tree walker with path tracking | ✅ `walk_config()` with dot-path |
|
||||||
|
| `ConfigSecurityExtractor` | ✅ `extractors/config_security.rs` |
|
||||||
|
| Security rules (11 rules) | ✅ TLS, CSRF, debug, password, cookies, CORS, rate limit |
|
||||||
|
| Dev file exclusion | ✅ Skip debug warnings in dev/test configs |
|
||||||
|
| Tests | ✅ 26 tests for parsing + security rules |
|
||||||
|
|
||||||
**Implementation:**
|
**Patterns now caught (nested to any depth):**
|
||||||
```rust
|
- `*.tls.verify: false` — TLS verification disabled
|
||||||
// Parse YAML/JSON/TOML into structured form
|
- `*.insecure_skip_verify: true` — Skip verification enabled
|
||||||
enum ConfigValue {
|
- `*.security.enabled: false` — Security disabled
|
||||||
String(String),
|
- `*.csrf.enabled: false` — CSRF protection disabled
|
||||||
Number(f64),
|
- `debug: true` — Debug mode (only in production files)
|
||||||
Bool(bool),
|
- `*.password.min_length < 8` — Weak password policy
|
||||||
Array(Vec<ConfigValue>),
|
- `*.cookie.secure: false` — Cookie secure flag disabled
|
||||||
Object(HashMap<String, ConfigValue>),
|
- `*.cookie.httpOnly: false` — Cookie httpOnly disabled
|
||||||
}
|
- `*.cors.allow_origin: "*"` — CORS allows all origins
|
||||||
|
- `*.rate_limit.enabled: false` — Rate limiting disabled
|
||||||
|
|
||||||
// Then extract with path awareness
|
**Languages:** YAML, JSON, TOML
|
||||||
fn extract_config_claims(config: &ConfigValue, path: &[String]) -> Vec<ExtractedClaim> {
|
|
||||||
// Recursively walk structure
|
|
||||||
// Track full path: "server.tls.min_version"
|
|
||||||
// Apply semantic rules based on path
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Patterns to catch:**
|
|
||||||
- `tls.verify: false` anywhere in hierarchy
|
|
||||||
- `security.enabled: false` in production configs
|
|
||||||
- `debug: true` or `DEBUG: true` in non-dev files
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -2193,7 +2502,7 @@ async fn extract_with_llm(code: &str, file: &str) -> Vec<ExtractedClaim> {
|
|||||||
|-------|------------|--------|--------|------------------|--------|
|
|-------|------------|--------|--------|------------------|--------|
|
||||||
| **8.1** | High-entropy secrets | HIGH | MEDIUM | Catches real leaked secrets | ✅ |
|
| **8.1** | High-entropy secrets | HIGH | MEDIUM | Catches real leaked secrets | ✅ |
|
||||||
| **8.2** | Framework-specific | HIGH | HIGH | Spring/Django/Express coverage | ⬜ |
|
| **8.2** | Framework-specific | HIGH | HIGH | Spring/Django/Express coverage | ⬜ |
|
||||||
| **8.3** | Config deep parsing | HIGH | MEDIUM | Nested YAML/JSON understanding | ⬜ |
|
| **8.3** | Config deep parsing | HIGH | MEDIUM | Nested YAML/JSON understanding | ✅ |
|
||||||
| **8.4** | Semantic TLS | MEDIUM | MEDIUM | Catches const TLS_MIN = "1.0" | ✅ |
|
| **8.4** | Semantic TLS | MEDIUM | MEDIUM | Catches const TLS_MIN = "1.0" | ✅ |
|
||||||
| **8.5** | ORM SQL injection | MEDIUM | MEDIUM | SQLAlchemy, Django, Sequelize | ✅ |
|
| **8.5** | ORM SQL injection | MEDIUM | MEDIUM | SQLAlchemy, Django, Sequelize | ✅ |
|
||||||
| **8.6** | Auth bypass | HIGH | MEDIUM | Backdoors, hardcoded creds | ✅ |
|
| **8.6** | Auth bypass | HIGH | MEDIUM | Backdoors, hardcoded creds | ✅ |
|
||||||
@ -2207,11 +2516,10 @@ async fn extract_with_llm(code: &str, file: &str) -> Vec<ExtractedClaim> {
|
|||||||
| **8.14** | Weak passwords | MEDIUM | LOW | MIN_LENGTH = 4 | ✅ |
|
| **8.14** | Weak passwords | MEDIUM | LOW | MIN_LENGTH = 4 | ✅ |
|
||||||
| **8.15** | LLM extraction | VERY HIGH | VERY HIGH | Semantic understanding | ✅ (Phase 7.5) |
|
| **8.15** | LLM extraction | VERY HIGH | VERY HIGH | Semantic understanding | ✅ (Phase 7.5) |
|
||||||
|
|
||||||
**Phase 8 Complete (8.1, 8.4, 8.5-8.14):** All first-pass extractors implemented. 12 of 14 Phase 8 extractors complete.
|
**Phase 8 Complete (8.1, 8.3, 8.4, 8.5-8.14):** All first-pass extractors implemented. 13 of 14 Phase 8 extractors complete.
|
||||||
|
|
||||||
**Remaining deferred extractors:**
|
**Remaining deferred extractors:**
|
||||||
1. **8.2** Framework-specific (HIGH effort - Spring, Django, Express, Rails)
|
1. **8.2** Framework-specific (HIGH effort - Spring, Django, Express, Rails)
|
||||||
2. **8.3** Config deep parsing (HIGH effort - YAML/JSON AST parsing)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -2225,3 +2533,143 @@ async fn extract_with_llm(code: &str, file: &str) -> Vec<ExtractedClaim> {
|
|||||||
| Framework coverage | 0 | 4 major | Spring, Django, Express, Rails |
|
| Framework coverage | 0 | 4 major | Spring, Django, Express, Rails |
|
||||||
| Enterprise pilot feedback | N/A | >4/5 | Post-pilot survey |
|
| Enterprise pilot feedback | N/A | >4/5 | Post-pilot survey |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 10: UX & Enterprise Polish ⬜
|
||||||
|
|
||||||
|
> **Goal:** Address enterprise buyer feedback from pilot demos. Close gaps between pitch claims and actual functionality.
|
||||||
|
> **Source:** Skeptical buyer review of `applications/aphoria-pitch/` materials.
|
||||||
|
|
||||||
|
### 10.1 Acknowledgment Expiry ✅
|
||||||
|
|
||||||
|
**Impact:** HIGH | **Effort:** MEDIUM | **Priority:** P1
|
||||||
|
|
||||||
|
Add `--expires` flag to `aphoria ack` command for time-limited exceptions.
|
||||||
|
|
||||||
|
| Task | Status |
|
||||||
|
|------|--------|
|
||||||
|
| Add `expires_at: Option<String>` to `AcknowledgmentInfo` struct (ISO 8601 format) | ✅ |
|
||||||
|
| Add `--expires` CLI flag to `Commands::Ack` in `cli.rs` | ✅ |
|
||||||
|
| Parse durations: `--expires 90d`, `--expires 2026-12-31` (ISO 8601 date only) | ✅ |
|
||||||
|
| Filter expired acks in `check_conflicts()` | ✅ |
|
||||||
|
| Show "Ack expired, resurfaces as BLOCK" in output | ✅ |
|
||||||
|
| Add expiry to JSON export for audit trail | ✅ |
|
||||||
|
| Tests for expiry parsing and behavior | ✅ |
|
||||||
|
|
||||||
|
**Implementation Notes:**
|
||||||
|
- Created `src/expiry.rs` module with `parse_expiry()`, `is_expired()`, and `format_expiry()` functions
|
||||||
|
- Ack payloads stored as JSON with `{reason, expires_at}` for backwards compatibility
|
||||||
|
- Legacy plain-text acks treated as permanent (no expiry)
|
||||||
|
- Expired acks preserved for audit trail per patent claim 25
|
||||||
|
- Updated all report formatters (table, JSON, markdown) to show expiry info
|
||||||
|
|
||||||
|
**CLI changes (`cli.rs`):**
|
||||||
|
```rust
|
||||||
|
Ack {
|
||||||
|
concept_path: String,
|
||||||
|
#[arg(short, long)]
|
||||||
|
reason: String,
|
||||||
|
/// Optional expiry (e.g., "90d", "2026-12-31")
|
||||||
|
#[arg(long)]
|
||||||
|
expires: Option<String>,
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
# Expire after 90 days
|
||||||
|
aphoria ack code://go/auth/tls/cert_verification \
|
||||||
|
--reason "Integration test environment" \
|
||||||
|
--expires 90d
|
||||||
|
|
||||||
|
# Expire on specific date (ISO 8601)
|
||||||
|
aphoria ack code://go/auth/tls/cert_verification \
|
||||||
|
--reason "Legacy migration - ends Q2" \
|
||||||
|
--expires 2026-12-31
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output after expiry:**
|
||||||
|
```
|
||||||
|
BLOCK code://go/auth/tls/cert_verification
|
||||||
|
Your code: TLS certificate verification is disabled (main.go:12)
|
||||||
|
Note: Previous acknowledgment expired 2026-12-31
|
||||||
|
Action: Re-acknowledge or fix the issue
|
||||||
|
```
|
||||||
|
|
||||||
|
**Enterprise Value:** "Exceptions don't become permanent." SOC 2 auditors love time-limited exceptions because they force periodic review.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 10.2 Human-Readable Signer Names ⬜
|
||||||
|
|
||||||
|
**Impact:** MEDIUM | **Effort:** MEDIUM | **Priority:** P2
|
||||||
|
|
||||||
|
Map issuer hex IDs to human-readable team names in output.
|
||||||
|
|
||||||
|
| Task | Status |
|
||||||
|
|------|--------|
|
||||||
|
| Add `signer_name: Option<String>` to `PackHeader` | ⬜ |
|
||||||
|
| Add `contact: Option<String>` to `PackHeader` (Slack channel, email) | ⬜ |
|
||||||
|
| Update `policy export/import` to preserve new fields | ⬜ |
|
||||||
|
| Show "Signed by Platform Security Team" instead of hex in output | ⬜ |
|
||||||
|
| Show contact info in conflict output | ⬜ |
|
||||||
|
| Backward-compat: gracefully handle packs without new fields | ⬜ |
|
||||||
|
|
||||||
|
**Output with signer name:**
|
||||||
|
```
|
||||||
|
BLOCK code://go/auth/tls/cert_verification
|
||||||
|
Your code: TLS certificate verification is disabled (main.go:12)
|
||||||
|
Source: Acme Security Standard v3.2 (Platform Security Team)
|
||||||
|
Contact: #security-policy
|
||||||
|
Action: Fix or acknowledge with: aphoria ack <path> --reason "..."
|
||||||
|
```
|
||||||
|
|
||||||
|
**Enterprise Value:** Developers know who to contact. Auditors see clear attribution.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 10.3 Speed Benchmarks ⬜
|
||||||
|
|
||||||
|
**Impact:** LOW | **Effort:** LOW | **Priority:** P3
|
||||||
|
|
||||||
|
Document and automate speed benchmark testing.
|
||||||
|
|
||||||
|
| Task | Status |
|
||||||
|
|------|--------|
|
||||||
|
| Create `benchmarks/` directory with test corpora | ⬜ |
|
||||||
|
| Automate `time aphoria scan` on standard corpus | ⬜ |
|
||||||
|
| Document test conditions in benchmark results | ⬜ |
|
||||||
|
| Add `aphoria scan --benchmark` flag for self-test | ⬜ |
|
||||||
|
| Include benchmarks in CI (optional, non-blocking) | ⬜ |
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```bash
|
||||||
|
# Run benchmark on current directory
|
||||||
|
aphoria scan --benchmark
|
||||||
|
|
||||||
|
# Output includes timing breakdown
|
||||||
|
Benchmark Results:
|
||||||
|
Files scanned: 767
|
||||||
|
Lines of code: 187,918
|
||||||
|
Claims extracted: 722
|
||||||
|
Conflicts found: 186
|
||||||
|
Total time: 652ms
|
||||||
|
- File discovery: 45ms
|
||||||
|
- Extraction: 487ms
|
||||||
|
- Conflict query: 120ms
|
||||||
|
```
|
||||||
|
|
||||||
|
**Enterprise Value:** "Show me the benchmark on a 100K-line codebase" → `aphoria scan --benchmark`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 10 Completion Criteria
|
||||||
|
|
||||||
|
| Metric | Target |
|
||||||
|
|--------|--------|
|
||||||
|
| Ack expiry working with 90d default | ✓ |
|
||||||
|
| Demo output matches pitch slides exactly | ✓ |
|
||||||
|
| Buyer can see who signed a policy (name, not hex) | ✓ |
|
||||||
|
| Buyer can see how to contact policy owner | ✓ |
|
||||||
|
| Speed benchmarks documented and reproducible | ✓ |
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user