# Audit Flow Commands
Detailed SQL commands for the audit-flow skill.
**CRITICAL: Read `schema.sql` before running ANY SQLite command.** Understand tables, columns, constraints, CHECK values, and views FIRST. Never assume schema from context.
## Database Setup
```bash
python .claude/skills/audit-flow/scripts/audit.py init
# Or manually:
mkdir -p .audit && sqlite3 .audit/audit.db < .claude/skills/audit-flow/schema.sql
```
## Session Management
### Create Session
First capture git context:
```bash
git_commit=$(git rev-parse HEAD 2>/dev/null || echo "")
git_branch=$(git branch --show-current 2>/dev/null || echo "")
git_dirty=$(test -n "$(git status --porcelain 2>/dev/null)" && echo 1 || echo 0)
```
Then create session:
```sql
INSERT INTO sessions (id, name, purpose, description, granularity, git_commit, git_branch, git_dirty)
VALUES (
lower(hex(randomblob(8))),
'{name}',
'{purpose}', -- security-audit | documentation | compliance | ideation | brainstorming | debugging | architecture-review | incident-review
'{description}',
'{granularity}', -- fine | coarse
'{git_commit}',
'{git_branch}',
{git_dirty} -- 0 or 1
);
```
### List Sessions
```sql
SELECT * FROM v_session_summary ORDER BY created_at DESC;
```
## Flow Management
### Create Flow
```sql
INSERT INTO flows (session_id, name, entry_point, description)
VALUES (
'{session_id}',
'{flow-name}',
'{entry point description}',
'{optional description}'
);
```
### List Flows in Session
```sql
SELECT * FROM v_flow_summary WHERE session_id = '{session_id}';
```
## Tuple Operations
### Add Tuple
```sql
INSERT INTO tuples (flow_id, layer, action, subject, file_ref, props, notes, status)
VALUES (
{flow_id},
'{layer}', -- CODE | API | NETWORK | AUTH | DATA
'{action}', -- e.g., "onClick handler"
'{subject}', -- e.g., "LoginButton"
'{file_ref}', -- e.g., "src/components/LoginButton.tsx:24"
'{}', -- JSON props
'{notes}',
'traced' -- traced | verified | concern | deleted
);
```
### View Tuples
```sql
-- All tuples in flow
SELECT id, layer, action, subject, file_ref, status
FROM tuples WHERE flow_id = {flow_id} AND status != 'deleted'
ORDER BY timestamp;
-- Filter by layer
SELECT * FROM tuples WHERE flow_id = {flow_id} AND layer = 'AUTH';
-- View concerns
SELECT * FROM v_concerns WHERE flow_name = '{flow_name}';
```
### Update Tuple Status
```sql
UPDATE tuples SET status = 'concern' WHERE id = {id};
UPDATE tuples SET status = 'deleted' WHERE id = {id}; -- Soft delete
```
## Edge Operations
### Linear Edge
```sql
INSERT INTO edges (from_tuple, to_tuple, relation)
VALUES ({from_id}, {to_id}, '{relation}');
-- Relations: TRIGGERS | READS | WRITES | VALIDATES | TRANSFORMS
```
### Branching Edge (with condition)
```sql
INSERT INTO edges (from_tuple, to_tuple, relation, condition)
VALUES
({branch_point}, {path_a}, 'BRANCHES', 'condition A'),
({branch_point}, {path_b}, 'BRANCHES', 'condition B');
```
### Merging Edge
```sql
INSERT INTO edges (from_tuple, to_tuple, relation)
VALUES ({converging_tuple}, {merge_point}, 'MERGES');
```
### View Edges
```sql
SELECT e.*, t1.action as from_action, t2.action as to_action
FROM edges e
JOIN tuples t1 ON e.from_tuple = t1.id
JOIN tuples t2 ON e.to_tuple = t2.id
WHERE t1.flow_id = {flow_id};
```
### Detect Non-Linear Points
```sql
SELECT * FROM v_branch_merge_points WHERE flow_name = '{flow_name}';
```
## Findings
### Add Finding
```sql
INSERT INTO findings (session_id, flow_id, severity, category, description, tuple_refs)
VALUES (
'{session_id}',
{flow_id}, -- Optional: NULL for session-level finding
'{severity}', -- critical | high | medium | low | info
'{category}', -- e.g., "token-storage", "auth-bypass"
'{description}',
'[1, 2, 3]' -- JSON array of tuple IDs
);
```
### View Findings
```sql
-- By severity
SELECT * FROM findings WHERE session_id = '{session_id}'
ORDER BY CASE severity
WHEN 'critical' THEN 1 WHEN 'high' THEN 2
WHEN 'medium' THEN 3 WHEN 'low' THEN 4 ELSE 5
END;
-- Flow-specific findings
SELECT * FROM findings WHERE flow_id = {flow_id};
```
## Export
### Using CLI
```bash
# Export all flows in session
python .claude/skills/audit-flow/scripts/audit.py export {session}
# Export specific flow
python .claude/skills/audit-flow/scripts/audit.py export {session} -f {flow}
# Export specific format
python .claude/skills/audit-flow/scripts/audit.py export {session} -F mermaid
```
## Validation
### Validate Flow Data
```bash
python .claude/skills/audit-flow/scripts/audit.py validate {session}
```
Checks for common issues before export:
| Check | Level | Description |
| ----------------- | ----- | -------------------------------------------- |
| Branch conditions | ERROR | BRANCHES edges must have condition labels |
| Orphan nodes | WARN | Nodes with no edges (disconnected from flow) |
| Duplicate labels | WARN | Multiple nodes with same action text |
| Node count > 40 | WARN | Diagram readability threshold |
| Node count > 60 | ERROR | Diagram must be split into sub-flows |
| No entry point | WARN | No node with zero in-degree |
### Output Structure
```
docs/audits/{session-name}/
├── README.md # Session summary
├── session.json # Full session data
├── session.yaml # Full session data (YAML)
├── {flow-name}.md # Flow report
└── {flow-name}.mermaid # Flow diagram
```
### Mermaid Output Features
- **Step numbering**: Topological BFS order from entry point
- **Entry point marker**: Green stadium-shape node (`([label]):::entryPoint`)
- **Layer subgraphs**: Nodes sorted by step number within each layer
- **Relation-specific arrows**:
- `-->` solid: TRIGGERS, VALIDATES, TRANSFORMS, BRANCHES, MERGES
- `-.->` dotted: READS (data consumption, no mutation)
- `==>` thick: WRITES (data mutation)
- **Observation separation**: Pure concern chains in OBSERVATIONS subgraph
- **Branch conditions**: Always shown on edge labels
- **Label deduplication**: Duplicate actions auto-suffixed with subject
- **Legend**: Style key at bottom of diagram
- **Direction**: Default TD, override with `--direction LR`
### Export with Direction
```bash
# Default top-down
python .claude/skills/audit-flow/scripts/audit.py export {session} -F mermaid
# Horizontal layout for wide decision trees
python .claude/skills/audit-flow/scripts/audit.py export {session} -F mermaid --direction LR
```
Example output:
```mermaid
flowchart TD
subgraph CODE
T1(["1. fetch API"]):::entryPoint
end
subgraph AUTH
T2["2. check token"]
T3["3. proceed"]
T4["4. refresh token"]
end
subgraph API
T5["5. call endpoint"]
end
T1 -->|"TRIGGERS"| T2
T2 -->|"BRANCHES
token valid"| T3
T2 -->|"BRANCHES
token expired"| T4
T3 -->|"TRIGGERS"| T5
T4 -->|"MERGES"| T5
classDef entryPoint fill:#2ecc71,stroke:#27ae60,stroke-width:3px
classDef concern fill:#ff6b6b,stroke:#c92a2a
classDef observation fill:#ffd43b,stroke:#fab005,stroke-dasharray:5 5
subgraph Legend
L1(["Entry point"]):::entryPoint
L2["Flow step"]
L3["Concern"]:::concern
end
```
## Git Merge Driver
### Setup (once per clone)
```bash
python .claude/skills/audit-flow/scripts/audit.py git-setup
```
Configures:
- `merge.sqlite-audit.driver` — auto-merges `audit.db` on `git merge`
- `diff.sqlite.textconv` — shows SQL dump in `git diff`
Requires `.gitattributes` (already in repo):
```
.audit/audit.db diff=sqlite merge=sqlite-audit
```
### How the merge driver works
Git calls: `audit.py db-merge %O %A %B`
- `%O` = common ancestor (unused — full union merge)
- `%A` = ours (result written here)
- `%B` = theirs
The driver:
1. Opens both SQLite DBs directly
2. Merges sessions by `name` (later `updated_at` wins)
3. Flows follow parent session winner
4. Tuples/edges follow parent flow
5. Findings deduped by `(session_name, category, description)`
6. All INTEGER PKs remapped; foreign keys updated
7. Result written to `%A`, exit 0 = success
### Manual merge (if needed)
```bash
# If the auto-driver fails (exit 1), merge manually:
python .claude/skills/audit-flow/scripts/audit.py db-merge ancestor.db ours.db theirs.db
```
## CSV Backup (Optional)
CSV commands still available for backup/portability:
```bash
python .claude/skills/audit-flow/scripts/audit.py csv-export # DB → .audit/csv/*.csv
python .claude/skills/audit-flow/scripts/audit.py csv-import # CSV → DB
python .claude/skills/audit-flow/scripts/audit.py csv-merge # Merge CSV sets
```
CSV uses `QUOTE_ALL`, deterministic PK sort, multiline-safe (RFC 4180).
## Views Reference
| View | Purpose |
| ----------------------- | --------------------------------------- |
| `v_session_summary` | Sessions with flow/tuple/finding counts |
| `v_flow_summary` | Flows with tuple/concern counts |
| `v_layer_distribution` | Layer breakdown per flow |
| `v_concerns` | All tuples marked as concern |
| `v_branch_merge_points` | Non-linear nodes (branches/merges) |