# v0.5 Roadmap — Security Differentiation (source brief)

> **Provenance:** User-authored strategic direction (2026-06-12), not a competitor
> release-intelligence scrape. Captured here as the source-of-record for the
> 2026-06-12 update in `../REQUIREMENTS.md`; scored requirements and per-feature
> plans derive from this document.
>
> **Positioning thesis:** evolve DvalinCode from *“small enough to audit”*
> (the code is auditable) to *“every agent action is auditable and
> policy-enforced”* (agent **behavior** is auditable and rules are enforced, not
> merely requested). Security is the differentiator, not a checkbox.
>
> **Sequencing principle (explicit):** rank by differentiation value + career
> signal per hour invested — **not** functional completeness, and **not** the
> catch-up scoring formula (which under-scores leadership plays; see the cycle
> note in REQUIREMENTS.md).

---

## P0-1 — Audit Trail: security-grade Agent Run Report

**Goal:** every agent run emits a tamper-evident structured audit log; the Run
Report is just its rendering layer. Core differentiator vs Claude Code / Cursor /
Aider.

### FR-1 Structured event log (foundation)
- One log file per run: `~/.dvalincode/audit/run-<timestamp>-<id>.jsonl`
- One event per line (JSONL):
  - `run_start` / `run_end` (task, mode, provider, model, cwd, git HEAD)
  - `tool_call` (tool, arg summary, result status, duration)
  - `file_read` / `file_write` / `file_delete` (path, +N/−M diff stat, before/after content hash)
  - `shell_exec` (command, exit code, sandboxed?)
  - `approval` (approve/reject, corresponding diff hash)
  - `policy_violation` (see P0-2 — the blocked operation)
- Each event carries `prev_hash` (SHA-256) → hash chain → tamper-evident.

### FR-2 Run Report (rendering layer)
- After a run, auto-generate Markdown from the JSONL: Task / Files read /
  Files changed / Commands run / Decisions / Diff summary / Test result.
- GUI: collapsible card at the end of the session; one-click copy / export.

### FR-3 CLI
```
dvalincode report --last
dvalincode report <run-id> --format markdown|json
dvalincode report verify <run-id>     # validate the hash chain
```

### Acceptance
- After any Cowork/Code run, a complete JSONL exists covering all tool calls.
- Hand-tamper any line → `report verify` reports the break and its position.
- Run Report “Files changed” matches the real git diff.
- Documented threat model: what the log defends (post-hoc forensics, behavior
  trace) vs not (local root attacker).

### Non-functional
- Append-only; a single failed event write must NOT abort the run (degrade to warning).
- Per-run size policy (diffs stored as hash + stat, not full text).

---

## P0-2 — Enforced Policy Engine: `dvalin.json` policies

**Goal:** move behavior constraints from prompt-level (“please follow AGENTS.md”)
to enforcement-level (intercepted in the ToolRegistry gating layer). The real
AppSec differentiator — no local agent does this.

### FR-1 Policy schema (new `policies` block in `dvalin.json`)
```json
{
  "policies": {
    "deny_paths": ["migrations/**", ".env*", "**/*.pem"],
    "readonly_paths": ["package-lock.json"],
    "shell_allowlist": ["npm test", "npm run lint", "git status"],
    "shell_denylist": ["rm -rf", "curl", "wget"],
    "require_approval": ["delete_file", "shell:git push"],
    "max_files_per_run": 20
  }
}
```

### FR-2 Enforcement layer
- Intercept at ToolRegistry permission gating — **before** the operation runs,
  independent of prompt compliance.
- Applies in **all** modes, including Code (full-auto) and Bypass. Bypass skips
  the interactive confirmation, not the policy.
- On block: return a structured error to the agent (so it can replan) and write a
  `policy_violation` audit event.

### FR-3 Source & precedence
- repo `dvalin.json` > user `~/.dvalincode/policy.json`; on conflict, the stricter wins.
- `.dvalincodeignore` is unchanged; document it as the read-dimension equivalent of `deny_paths`.

### Acceptance
- `deny_paths` hits block write/edit/delete in every mode; agent gets a clear error.
- `shell_denylist` hits are blocked in Code full-auto and logged to the audit trail.
- Writing “allow editing migrations” in AGENTS.md cannot bypass policy (enforcement > prompt).
- README/docs gain a “Prompt-level rules vs. enforced policies” comparison.

### Companion docs (first-class deliverable)
- `docs/THREAT-MODEL.md` aligned with OWASP LLM Top 10 / agentic-AI risk:
  over-permissioned actions, prompt-injection-driven unauthorized writes,
  sensitive-file exfiltration to the LLM. The doc is itself portfolio material.

---

## P1-1 — Checkpoint / Rollback: run-level snapshot

**Goal:** upgrade operation-level `/undo [N]` to a one-click run-level rollback —
remove the “the agent changed a pile of things and I can’t cleanly revert” fear.
Low cost (wraps git); ship it but don’t headline it.

### Functional
- Before a Cowork/Code run, auto-create a snapshot (`git stash create` or a shadow
  commit — does not pollute the working tree).
- After the run, GUI offers three choices: **Rollback this run / Keep changes /
  Create git commit**.
- CLI: `dvalincode checkpoint list` · `dvalincode rollback <run-id>`.
- Rollback itself is written to the audit trail (ties into P0-1).

### Acceptance
- Non-git directory → degrade to file-level backup or an explicit “unsupported” notice.
- Files the user hand-edited during the run → rollback warns about conflicts instead of silently overwriting.
- After rollback, `git status` is clean (or restored to the pre-run state).

---

## P1-2 — Technical blog post (non-code deliverable)

One design-decision article outweighs another routine feature for career signal.

- Working title: *“Why prompt-level rules can’t secure coding agents — building
  enforcement into the tool layer.”*
- Covers: P0-1 + P0-2 design motivation, hash-chain audit-log design, mapping to
  OWASP agentic risks, the “Bypass mode ≠ bypass policy” trade-off.
- Channels: repo `docs/` + personal blog / LinkedIn; quotable in job materials.

---

## P2 — Lower priority (only with spare capacity)

| Feature | Note | Why not prioritized |
|---|---|---|
| `dvalincode init` (scan → AGENTS.md + dvalin.json with suggested policies) | An `init`/`scan` command already exists (generates config) — extend to emit a starter playbook + suggested `policies` | Claude Code `/init`, Cursor rules are table stakes; no differentiation, but its absence looks incomplete — fast completeness item |
| PR Assistant (`dvalincode pr`) | Generate PR description, risk notes, test checklist from audit log + diff | Commodity on its own; **only** differentiated when fused with P0-1 (“evidence-backed PR description”) — depends on P0-1 landing first |
| Built-in Routines templates | Ship 5–8 quality routines (Explain repo / Find bugs / Add tests / Review diff / Quality gate) | Improves first-run UX, not a moat; ship templates, not a marketplace |

---

## Explicit non-goals

1. **VS Code extension** — head-on with Cursor/Cline on IDE experience; unwinnable.
2. **Plugin system** — over-architecture at current scale; routines templates suffice.
3. **New model providers** — OpenAI-compatible already covers it; zero marginal value.
4. **Multi-agent collaboration** — adds complexity the target user doesn’t need.
5. **Cloud autonomous agent** — conflicts with the local-first / safe-by-default identity.
6. **Routines marketplace / official directory** — castle in the air at this user volume.

---

## Milestones

```
v0.5.0  P0-1 Audit log + Run Report (incl. verify)
v0.5.x  P0-2 Policy Engine + THREAT-MODEL.md
v0.6.0  P1-1 Checkpoint/Rollback + blog post
later   P2 as capacity allows (init → routines templates → PR assistant)
```

**Overarching:** after v0.5, the README’s first-line pitch upgrades from
*“any model, safe by default”* to something like
*“A local-first coding agent that leaves a tamper-evident audit trail — and
enforces your repo’s rules instead of asking the model to follow them.”*
