# Changelog

All notable changes to this project will be documented in this file.

## [0.16.1] - 2026-05-13

### Maintenance

- Republish the release pipeline to align all distribution channels for the v0.16 line. No code changes from v0.16.0.

## [0.16.0] - 2026-05-13

### Added

- **Agent runtime posture (`/dashboard/audit` reframed)** (#170): runtime-first view of what each agent did, with hardening secondary and suppressed when the runtime cannot prove protection.
- **Delegation as runtime authority** (#171): AND-strict ACL plus suspension on the root, signature required when a chain is present, sender-binding, shared depth cap.
- **AI analysis on runtime sessions** (#172): tri-state envelope, isolated runtime namespace, DOM-safe error panel, `mdToHTML` render.
- **Deterministic runtime evidence write path** (#173, #174): per-connection pragmas via DSN plus WaitGroup-backed `FlushActivity`. Integration tests are hermetic (DB path inside `t.TempDir`).
- **Provider-neutral `PrincipalContext` model** (#175): vendor-neutral identity enrichment carried through resolve and posture, deep-copied at every outward boundary. No OIDC or IdP adapter wired yet.
- **Unified Claude Code runtime client lifecycle** (#177, #178): shared helper across `run` / `connect` / `disconnect`. Already-present gateway converges via remove-and-re-add. Strict and best-effort modes.
- **Runtime sessions, detail, bulk export, hooks drawer drill-down** (#169): `ExcludeHeartbeats` SQL filter; all runtime-first.
- **Runtime event substrate** (#158, #159): sessions, actors, hook events. Hooks handler wired into `runtime.Store`.
- **Phase 2A coverage matrix on Overview** (#136).
- **Phase 2B.1 activity event foundation** (#137-#142): dual-write across gateway, forward proxy, and hooks; connector registry; hybrid coverage reader; activity drill-down.
- **Phase 1 surface-agnostic identity** (#133, #134, #135): bearer-token identity for MCP HTTP gateway; `oktsec tokens` CLI for principal token management; identity resolver extended to forward proxy and hooks.
- **Claude Code hooks installation** (#157): backup plus modern decision shape.
- **Claude Code connector inventory plus `doctor`** (#156).
- **Coverage drawer "Why this state"** (#144): includes the CLI command to inspect the underlying data.
- **Coverage cells as native buttons under strict CSP** (#143).
- **Read-only audit store hardening**: `NewStoreReadOnly` enforced on verification paths (`audit verify-chain`) so tampered rows surface instead of being silently rebuilt.

### Changed

- **Dashboard clarity sprint** (#116-#127): KPI labels, contrast, navigation, sorting, accessibility (skip link, `aria-current`, reduced motion); events page inspect buttons and redaction indicators; rules page filter chips and trigger counts; agent policy comprehension (ARIA tabs, wildcard explanations); AI analysis evidence framing, confidence column, rule IDs; posture page as a remediation surface with severity filters and copy buttons; graph readability and risk navigation; settings information architecture with inline confirmations.
- **Dashboard desktop polish slice** (#148-#153): topbar mode parity, gateway port readiness callback, idempotent `Store.Close`, routed-only visibility wording, neutral typography, contrast bump, gateway state coherence plus sparkline frame, auto-fit Agents grid plus Pipeline summary wrap, all-pages smoke test.
- **Public artifact wording sweep** (#147, #149, #154): visibility claims scoped to Oktsec-routed surfaces. README aligned with the dashboard public-contract spec. Banned-phrase plus stale rule-count sweep across rendered Overview, populated Overview, Gateway page, LLM page.
- **`CoverageFromHookEvent`** (#140): only `pre_tool_use` can claim `Protected`.
- **Setup banner live rule count plus dashboard page count** (#129).
- **Graph rendering aligned with audit truth and generalised across MCP clients** (#131, #132).
- **Generated configs no longer auto-purge audit evidence** (#155): preserves evidence by default.
- **Aguara v0.14.4 -> v0.14.5** (#105).

### Fixed

- **Wildcard egress, SDK auth, Go toolchain audit findings** (#107).
- **Agent spoofing, dual gateway, redaction audit findings** (#106).
- **Webhook masking, graph render, modal a11y** (#113).
- **ACL entry constraints wired into the policy evaluator** (#108).
- **Custom rule ID sanitisation before joining onto `CustomRulesDir`** (#165).
- **LLM queue buffer size capped to bound channel allocation** (#166).
- **Claude Code project directory validation** (#164).
- **Session cookie `Secure` flag derived from the request scheme** (#167, #168).
- **`oktsec run` Claude Code bootstrap when discovery is empty** (#177).
- **Overview sparkline test anchored on `time.Now()`** (#163).
- **Gateway runtime contradiction plus suppressed orphan Overview sparkline** (#152).
- **Dashboard accessibility regressions** (#126): skip link, `aria-current`, reduced motion.

### Security

- **Go toolchain bumped to 1.26.3** (#179): picks up patched standard library (GO-2026-4918, GO-2026-4971, GO-2026-4980, GO-2026-4982). `govulncheck` clean.
- **Principal name validation at every key sink** (#180): central validator with two-tier contract. `ValidatePrincipalName` is filesystem-safe and accepts the reserved `_proxy` signing principal; `ValidatePublicPrincipalName` layers a reserved-name refusal for HTTP, dashboard form, CLI, config-load, gateway auto-register, and SDK surfaces. Rejects path traversal, NUL, leading dot or dash, and Windows-reserved device basenames (`NUL`, `CON`, `COM1-9`, `LPT1-9`, `AUX`, `PRN`). Two package-local agent-name regexes removed in favour of the central validator.
- **Dashboard AI analysis transport** (#181): `Server.analysisHTTPClient` routes through `netutil.SafeDialContext`. A misconfigured `llm.base_url` pointed at `127.0.0.1`, `169.254.169.254`, or any private/reserved range is refused before the configured `Authorization` header leaves the process. Error catch handlers in `tmpl_quarantine.go` and `tmpl_session.go` switched from `innerHTML` concatenation against upstream provider error text to `createElement` plus `textContent`.
- **Gateway egress sandbox env precedence** (#182): when `EgressSandbox=true`, reserved proxy env keys from backend config (`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY`, plus lowercase variants) are dropped with a warning log. `ALL_PROXY` and `all_proxy` join the sandbox injection set. `Backend.buildChildEnv` extracted for testability.
- **Publish workflows hardened** (#183, #184): all 18 actions pinned to commit SHAs across CI, release, docs, and PyPI workflows. The Python SDK publish step migrates from a long-lived credential to PyPI Trusted Publishing via OIDC. Build and publish are separate jobs; `id-token: write` is scoped to the publish job only, never workflow-wide, so PyPI-sourced packaging tooling cannot mint a release credential. Same separation applied to `docs.yml` (deploy job carries `pages: write` plus `id-token: write`; build job does not).
- **P1 dashboard clarity** (#116): avg duration bug, contrast, KPI labels, confidence display.

## [0.15.2] - 2026-04-24

### Changed

- **Upgrade Aguara v0.13.0 → v0.14.4**. Zero code changes needed — public API identical. Gains:
  - Pattern matcher 3.7-6.4x speedup via Aho-Corasick prefilter.
  - Two new evasion decoders (base32, C-style octal escapes) in content scanning.
  - Tighter regexes on PROMPT_INJECTION_004/011 and UNI_001/006 (fewer FPs).
  - Documentation-context confidence penalty (findings in `## Installation` blocks score lower).
  - Fixed AC prefilter literal collision with `bashrc` (broken in v0.14.3, fixed in v0.14.4).

## [0.15.1] - 2026-04-16

### Fixed

- **CLI / server audit DB path divergence (#97)**: `defaultDBPath()` now honours `cfg.DBPath` from `oktsec.yaml` before falling back to the XDG default. Before the fix, every CLI subcommand except `audit verify-chain` and `audit archive` opened `~/.oktsec/oktsec.db` while the running server followed `cfg.DBPath` — operators saw different CRL / quarantine / audit history depending on which tool they reached for.

## [0.15.0] - 2026-04-16

### Added

- **Audit chain v2 (#95)**: `ComputeEntryHash` now commits to `policy_decision`, `rules_triggered` and `signature_verified` in addition to the v1 fields. Tampering any of those columns invalidates the chain. `VerifyChain` accepts both v1 and v2.
- **Read-only audit store (#95)**: `NewStoreReadOnly` opens the DB with `PRAGMA query_only=ON` and skips auto-repair / rebuild paths so `oktsec audit verify-chain` surfaces tampered rows instead of silently regenerating them.
- **Typed credential redaction (#95)**: `redactMatch` emits `[REDACTED:TYPE:len=N]` instead of the first 10 chars. 15 supported credential types.
- **Pre-parse IP rate limit (#95)**: `Handler.ipLimiter` runs before `parseRequest`, rejecting unauthenticated floods before JSON decode.
- **`RateStore` interface (#95)**: Rate limiter is now pluggable. `MemoryStore` default, `RedisRateStore` added in #96.
- **Gateway per-agent caps (#95)**: `Agent.MaxConcurrentCalls` (default 5) and `Agent.MaxDelegationDepth` (default 3).
- **Ed25519 key versioning (#95)**: `Agent.KeyVersion` + `X-Oktsec-Key-Version` header + `SignMessageV2` / `VerifyMessageV2` close the post-rotation signature-replay window.
- **CSRF Origin/Referer guard (#95)**: Dashboard middleware rejects cross-origin state-changing requests.
- **Atomic scanner cache (#95)**: Lock-free fast path via `atomic.Pointer`.
- **Tool classification (UK AISI taxonomy) (#95)**: Every MCP tool in the gateway gets an impact × generality risk tier.
- **Production-to-testcase pipeline (#95)**: `audit.ExportTestcase` + `oktsec rules testgen` / `oktsec rules validate`.
- **Webhook retry + DLQ (#96)**: 3-attempt exponential backoff. Terminal `dlq` status in the alerts log.
- **`oktsec keys rotate` bumps `KeyVersion` (#96)**.
- **Revocation list surface (#96)**: `oktsec keys list-revoked [--json]` + `GET /v1/revoked-keys`.
- **Audit archive + prune (#96)**: `oktsec audit archive --before=DATE --output=FILE.jsonl.gz` + `oktsec audit prune --before=DATE --yes`.
- **Redis-backed rate limiter (#96)**: Sliding-window Lua script. Pluggable via `rate_limit.backend: redis`.
- **OpenTelemetry tracing (#96)**: W3C traceparent propagation end-to-end. `internal/observability` package.

### Changed

- **README rewrite**: Leads with problem statement and positioning. New "What's new" and "How it compares" sections. Rule count reconciled to 268.
- **Dashboard LLM API key is write-only**: `value=""` removed from the password input.
- **Dashboard category capitalization**: acronym-aware (MCP, OpenClaw, Inter-Agent, IPI, JWT, …).
- **Severity color mapping**: case-insensitive.
- **Risk score rebalance**: replaced the saturating formula with `confidence * (80*blockRatio + 40*quarRatio)` where `confidence = min(1, total/10)`.
- **`oktsec status` separates oktsec health from environment findings**.
- **Gateway `DisableAutoRegister` opt-in**: reject tool calls from undeclared agents.

## [0.14.0] - 2026-04-15

### Added

- Security posture page redesign with auto-fix and AI enrichment (#93).
- Filesystem guard for AI tool config integrity (#92).
- Memory poisoning detection rules and defenses (#91).
- Dashboard visibility for egress sandbox, trust boundaries, dep check, two-stage LLM (#90).
- Auto-mode learnings: information stripping, overeager detection, two-stage LLM, trust boundaries (#89).
- 6 security hardening fixes from internal audit (#94): config file permissions 0o600, Go/Python SDK symlink rejection via O_NOFOLLOW, safefile TOCTOU fix, LLM regex ReDoS protection.

## [0.13.0] - 2026-04-12

### Added

- **Delegation chains (#81)**: Ed25519-signed delegation tokens with scope (tools, agents, depth, expiration). Sub-agents sign with their own key; gateway verifies the chain on every call.
- **Session tracking**: multi-agent session IDs propagated through the stack.
- **`oktsec audit` CLI**: generalized audit command with subcommands.
- **CE rules**: container escape detection.
- Aguara v0.12.0 and v0.12.1 (#87, #88).

## [0.12.0] - 2026-04-05

### Added

- **Supply chain defense phase 1 (#83)**: credential coverage, dependency rug-pull detection, Aguara v0.10.0.
- **Supply chain defense phase 2 (#84)**: egress sandbox, dependency auditing, 25 new detection rules.
- **Aguara v0.11.1 (#85)**: `check` / `clean` incident response commands.
- Optional anonymous usage telemetry with opt-out (#79).
- 13 IPI Arena detection rules and LLM prompt enhancement (#78).

### Fixed

- Dashboard bugs, telemetry client, docs (#80).

## [0.11.0] - 2026-03-28

### Added

- Homebrew tap via goreleaser.
- HOMEBREW_TAP_TOKEN in release workflow.
- PyPI workflow with version injection from git tag.

### Fixed

- TUI indent logic, stats polling, active agent count.
- `resolveAgent` false matches, hook port from config.
- Session leak, thread safety, abstraction simplification.

## [0.8.0] - 2026-03-05

### Added

- **`oktsec setup` command**: One-command onboarding that discovers all MCP clients, generates config with sensible defaults (observe mode), creates Ed25519 keypairs, wraps all servers through the security proxy, and prints a guided summary with next steps. Flags: `--enforce`, `--skip-wrap`, `--keys`, `--config`.
- **`oktsec wrap --all` flag**: Wraps all discovered MCP clients at once instead of requiring per-client `wrap` calls. Expanded wrappable client list to 13 clients (added Amp, Gemini CLI, Copilot CLI, Amazon Q, Roo Code, Kilo Code, BoltAI, JetBrains).
- **`WrapOpts` API**: Replaced global `WrapServersWithEnforce` variable with a `WrapOpts` struct carrying `Enforce` and `ConfigPath` fields. New `WrapAllClients()` and `WrappableClients()` exported functions.
- **Config passthrough in wrapper**: Wrapped proxy commands now include `--config <abs-path>`, so the proxy loads `allowed_tools`, `db_path`, and all config features. Previously the proxy ran without config access.
- **Shared audit trail**: Default DB location moved from `/tmp/oktsec.db` to `~/.oktsec/oktsec.db` (macOS/Linux) or `%LOCALAPPDATA%\oktsec\oktsec.db` (Windows). Both `oktsec proxy` and `oktsec serve` now use the same database, so dashboard shows proxy activity.
- **Quick-start documentation**: `DOCS/quick-start.md` — "Secure your MCP servers in 2 minutes" guide covering setup, enforcement, undo, and supported clients.
- **Wrapper test suite**: 11 new tests covering `wrapServers` (basic, skip-already-wrapped, enforce, config path, enforce+config, empty map, env preservation), `WrapClient` integration, `WrappableClients`, `isWrappable`, and backup creation.
- **Setup/wrap command tests**: 8 new tests covering `defaultDBPath` (path structure, idempotency, directory permissions), `setup` command flags and defaults, `wrap` argument validation (requires client or `--all`, mutual exclusion).

### Changed

- **`oktsec init` output**: Now suggests `oktsec wrap --all` and `oktsec setup` as next steps instead of per-client `oktsec wrap <client>`.
- **Generated config includes `db_path`**: Both `init` and `setup` set `db_path` to the shared location so proxy and serve align automatically.
- **README quick-start**: Replaced 4-step manual flow with `oktsec setup` + `oktsec serve` two-liner. Added `setup` to CLI reference.
- **Config validation errors**: Invalid rule action now lists valid values (`block`, `quarantine`, `allow-and-flag`, `ignore`).

### Fixed

- **Proxy audit trail invisible in dashboard**: Proxy wrote to `/tmp/oktsec.db` while serve used CWD `oktsec.db`. Now both default to `~/.oktsec/oktsec.db`.
- **Proxy ignored config features**: Wrapped proxy commands had no `--config` flag, so `allowed_tools` and other per-agent config was silently ignored.
- **`serve` without config failed silently**: Now prints warning with the error, suggests running `oktsec setup`, then falls back to defaults. Banner shows "No agents configured" hint when agent count is 0.
- **Dashboard empty state**: Overview page now shows welcome message when no agents are configured (links to `oktsec setup`) and "waiting for traffic" message when agents exist but no messages have been scanned yet.
- **Login page access code UX**: Added note that the code changes on each server restart.
- **`logs` empty state unhelpful**: Now explains that no messages have been scanned yet, shows the DB path, and suggests `oktsec logs --live`.
- **`logs --live` silent when idle**: Shows periodic heartbeat message ("waiting for messages...") after 10 seconds of inactivity, then every 30 seconds.
- **`wrap` "already wrapped" ambiguous**: Now suggests `oktsec logs --live` to verify traffic and hints at unwrap for mode changes.
- **`logs` used hardcoded DB path**: Now uses shared `~/.oktsec/oktsec.db` default and respects config `db_path`, matching the proxy and serve behavior.

## [0.7.0] - 2026-03-03

### Added

- **Mobile-responsive dashboard**: Three-tier breakpoint system (768px tablet, 480px phone) replaces the single desktop-only layout. Hamburger menu with slide-out sidebar, responsive grid utilities (`.grid-2/3/4`), horizontal-scrollable tables, and stacked stats on mobile. Inline grid styles extracted to CSS classes across all dashboard pages.
- **Dashboard visual polish**: Stat card accent gradient on hover with subtle lift, card hover shadows, card header border separators, accent-tinted table row hover, gradient buttons with micro-lift, sidebar section dividers, category card hover lift, blocked badge pulse animation, and improved login button glow.
- **Full-page rule detail view**: New `/dashboard/rules/{category}/{ruleID}` page with breadcrumb navigation, rule metadata (severity, category, description, patterns, true/false positive examples), inline rule testing via HTMX, and per-rule enforcement configuration. Replaces the side-panel rule view.
- **Inline rule testing**: New `POST /dashboard/api/rule/{id}/test` endpoint. Submit test content directly from the rule detail page and see real-time match/no-match results.
- **Per-category webhook configuration**: New `CategoryWebhook` config type and `POST /dashboard/rules/{category}/webhooks` endpoint. Assign default notification channels to entire rule categories. Rules without explicit webhook config fall back to their category's webhooks automatically.
- **Category webhook fallback in proxy**: `notifyByRuleOverrides()` now builds a category→notify lookup from `CategoryWebhooks` config and falls back to category-level notifications when a rule has no explicit notify configuration.
- **Traffic generator**: New `demo/traffic-gen` Go binary for realistic continuous traffic simulation. Uses all 10 agents with weighted selection (coordinator/coder weighted higher), Ed25519 signed messages (75% signed, 25% unsigned), malicious payload mix (20% of traffic) covering prompt injection, credential leaks, PII exposure, exfiltration, privilege escalation, code execution, and system prompt extraction. Configurable API endpoint and keys directory.
- **`inSlice` template function**: Helper for checking if a value exists in a slice, used in category webhook channel checkboxes.
- **Dashboard improvements (PRs #29, #30)**: Settings page with tabbed layout and full config editing. 5 production workflow improvements including event filters, agent detail enhancements, and search.
- **MCP audit checks**: Tool inventory validation and MCP-specific security checks in the deployment audit. New `checks_mcp.go` with test coverage.
- **Discovery improvements**: Enhanced MCP client scanner with better error handling and platform detection.
- **Deterministic graph layout**: Agent topology visualization uses circular initial placement instead of random positions, ensuring consistent layout across page reloads. Label background pills for readability, node layer rendered on top of edges/particles, subtler edge lines and particles.
- **Dashboard server tests**: 657-line test suite covering all dashboard routes, HTMX partials, authentication, and CSRF protection.
- **175 detection rules**: Up from 169, with 6 new rules across inter-agent and MCP categories.

### Changed

- **Fonts**: Switched from Google Fonts (Inter, JetBrains Mono) to system font stacks (`system-ui` for sans, `ui-monospace` for mono). Eliminates external font loading latency and GDPR/privacy concerns.
- **HTMX self-hosted**: Replaced CDN-loaded `htmx.org@2.0.4` with self-hosted `htmx.min.js` via `internal/dashboard/static/embed.go`. Dashboard now works fully offline.
- **Color palette softened**: Danger, success, and warning colors adjusted to softer variants (`#f87171`, `#34d399`, `#fbbf24`) for reduced eye strain on dark backgrounds. All severity and status badge backgrounds use consistent `rgba()` values.
- **Brand logo enlarged**: Sidebar brand font size increased from `1.12rem` to `1.35rem`. SVG favicon added across all pages.
- **Rule links**: Category detail page now links to full-page rule detail views instead of HTMX side panels.
- **Sidebar**: Uses CSS `transform:translateX(-100%)` with transition instead of `display:none` for mobile toggle, enabling smooth slide animation.
- **Overview page**: Removed redundant `h1` heading (page title already in topbar).

### Fixed

- **Flaky stdio test deadlock**: Reduced test timeout from 10 minutes to 0.1 seconds, preventing CI hangs from deadlocked goroutines.
- **Bulk toggle idempotency**: Enable/disable all rules toggle now correctly handles already-toggled states.
- **Export limit**: Audit log export no longer truncates at 1000 entries.
- **Agent descriptions**: Agent detail page now correctly displays the description field from config.

## [0.6.0] - 2026-02-28

### Added

- **MCP gateway mode**: Streamable HTTP MCP gateway that fronts backend MCP servers, intercepting every `tools/call` with the full security pipeline. Supports stdio and HTTP backend transports, tool discovery, automatic namespacing, per-agent tool allowlists, response scanning, and auto-port fallback. New `oktsec gateway` command.
- **`internal/safefile` package**: Symlink rejection via `Lstat`, size-limited reads via `ReadFileMax`, applied across config loading (1 MB cap), keypair loading (64 KB cap), and audit DB initialization.
- **`internal/mcputil` package**: Convenience helpers (`GetString`, `GetInt`, `GetArguments`, `NewToolResultText`, `NewToolResultError`) bridging the go-sdk raw JSON API to typed accessors.
- **SSRF hardening**: 21 RFC special-use CIDR ranges blocked for outbound connections (RFC 1918, loopback, link-local, TEST-NET, CGN, multicast, IPv6 ULA/Teredo/6to4/NAT64). Post-DNS `safeDialContext` validation prevents DNS rebinding. Alternative IP encoding detection (hex, octal, packed decimal). Applied to webhooks and forward proxy CONNECT tunneling.
- **Credential redaction**: 15 regex patterns (Anthropic, GitHub, AWS, Slack, GitLab, Stripe, SendGrid, PEM keys, JWTs) strip secrets from API responses, audit trail, and webhook payloads.
- **Replay protection**: 5-minute timestamp freshness window rejects replayed messages.
- **MCP client discovery expanded to 17 clients**: Added OpenCode, Zed, Amp, Gemini CLI, Copilot CLI, Amazon Q, Claude Code, Roo Code, Kilo Code, BoltAI, JetBrains/Junie.
- **Webhook enrichment**: Notifications now include `rule_name`, `category`, and `match` fields. Named webhook channels: define destinations once, reference by name in enforcement overrides. New template variables: `{{RULE_NAME}}`, `{{CATEGORY}}`, `{{MATCH}}`.
- **Dashboard enhancements**: Redesigned login page with SVG shield icon and animations. New 404 page. Root splash page at `/`. Agent metrics page with risk scores, traffic stats, communication partners. Events page with agent/time-range filters. Overview with detection rate, unsigned message %, average latency, top rules.
- **Dashboard analytics queries**: `QueryUnsignedRate`, `QueryTrafficAgents`, `QueryTopRules`, `QueryAgentRisk`, `QueryEdgeStats`, `QueryEdgeRules`, `QueryAgentTopRules`, `QueryAvgLatency`.
- **curl|bash install script**: One-liner installation from GitHub releases with checksum verification and cross-platform OS/arch detection.

### Changed

- **MCP SDK migration**: Replaced `mark3labs/mcp-go` (community, v0.44) with `modelcontextprotocol/go-sdk` (official Tier 1, v1.4.0). All MCP server, client, and transport code now uses the official SDK with semver stability guarantees and Linux Foundation governance.
- **Detection rules**: 169 total (148 Aguara + 6 IAP + 15 OpenClaw), up from 159 after aguara v0.3.1 bump.
- **File I/O hardened**: Config loading (1 MB cap), keypair loading (64 KB cap), audit DB rejects symlinked paths, public key loader skips symlinked `.pub` entries.
- **Configurable DB path**: New `db_path` config field (default `oktsec.db`), resolved to absolute path.

### Fixed

- **SSRF in forward proxy**: CONNECT tunneling now validates destinations through `safeDialContext` and `ValidateHost`.
- **Symlink attacks**: Audit DB, config files, and key files reject symlinks via `Lstat` checks.

## [0.5.0] - 2026-02-24

### Added

- **Policy as code**: Per-rule action overrides in `oktsec.yaml`. Configure `block`, `quarantine`, `allow-and-flag`, or `ignore` per rule ID. Per-rule webhook notifications with configurable URLs. Plain-text webhook templates with tag substitution (`{{RULE}}`, `{{SEVERITY}}`, `{{FROM}}`, `{{TO}}`, etc.) — system wraps in Slack-compatible JSON automatically. Dashboard enforcement tab with create/edit/delete, rule descriptions, expandable webhook and template previews.
- **HTTP forward proxy**: New `forward_proxy` mode for Docker Sandbox integration. Supports HTTP CONNECT tunneling so containerized agents route traffic through oktsec for scanning.
- **OpenClaw security rules OCLAW-008 to OCLAW-015**: Sandbox disabled, path traversal in mounts, missing auth on gateway, hardcoded credentials in env, gateway exposed without TLS, open DM with external agents, exec without resource limits, UI proxy without auth. Plus `ScanContentAs()` API for scanning content as a specific agent identity.
- **`oktsec audit` command**: 41-check deployment security auditor covering Oktsec (16 checks), OpenClaw (18 checks), and NanoClaw (7 checks). Health score with A-F grading, severity breakdown, actionable remediation commands. SARIF output (`--format sarif`) for GitHub code scanning integration.
- **`oktsec status` command**: One-line health score + top 3 issues for quick checks.
- **`internal/auditcheck` package**: Extracted audit checks from CLI into a shared library used by both CLI and dashboard. Finding enrichment with `ConfigPath` and `Remediation` fields.
- **Dashboard audit page**: Redesigned with stat strip (score/grade, severity breakdown), critical alert strip, per-product cards with icon/config/docs, expandable findings with inline remediation, and copy-to-clipboard.
- **Dashboard security hardening**: Session cookie `SameSite=Strict`, `HttpOnly`, `Secure` flags. CSRF protection on state-changing routes. X-Frame-Options and X-Content-Type-Options headers.
- **Audit store test coverage**: 9 new test functions covering key revocation, query stats, hourly stats, top rules, edge rules, agent risk scoring, quarantine lifecycle, hub broadcast.
- **Package documentation**: godoc-compliant package doc comments on all 9 internal packages.

### Changed

- **Dashboard CSS**: Severity labels simplified to text-only. Button glow effects removed. Card border-radius standardized to 10px.
- **CI pipeline**: Added `make integration-test` step to GitHub Actions workflow.
- **Detection rules**: 159 total (138 Aguara + 6 IAP + 15 OpenClaw).
- CLI `audit` and `status` commands now delegate to `internal/auditcheck` instead of inline check functions.

### Fixed

- **Forward proxy**: Wrapper applied outside middleware chain to prevent hijack conflicts with dashboard routes.

## [0.4.1] - 2026-02-23

### Added

- **Per-agent tool allowlist**: New `allowed_tools` config field restricts which MCP tools an agent can invoke via `tools/call` requests in the stdio proxy. Unlisted tools are blocked with a JSON-RPC error. Empty list means all tools allowed (ASI05).
- **MCP tool tests**: 19 tests covering all 6 MCP tools (`scan_message`, `list_agents`, `audit_query`, `get_policy`, `verify_agent`, `review_quarantine`).
- Documented tool allowlist in AGENTS.md with config example and JSON-RPC error format.

### Fixed

- **Flaky SQLITE_BUSY in tests**: Replaced `time.Sleep` with deterministic `Store.Flush()` that waits for async write channel to drain. Fixes intermittent CI failures on slow runners.

---

## [0.4.0] - 2026-02-23

OWASP agentic hardening release. Aligned with [OWASP Top 10 for Agentic Applications](https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications/). All changes are backward-compatible.

### Added

- **Default-deny policy**: New `default_policy: deny` config option rejects messages from unknown senders not listed in the agents map. Defaults to `allow` for backward compatibility (ASI03).
- **Agent suspension**: Agents can be suspended via CLI (`oktsec agent suspend <name>`) or dashboard toggle. Suspended agents have all messages rejected immediately — both as sender and recipient. New `suspended` field in agent config (ASI10).
- **`oktsec agent` command**: New subcommands `suspend`, `unsuspend`, and `list` for managing agent lifecycle from the CLI.
- **Enforcement mode for stdio proxy**: New `--enforce` flag on `oktsec proxy` and `oktsec wrap`. When enabled, malicious client→server requests are blocked and a JSON-RPC 2.0 error response is injected back to the MCP client (`{"jsonrpc":"2.0","id":<id>,"error":{"code":-32600,"message":"blocked by oktsec: <rule>"}}`). Server→client responses are always forwarded. Notifications are silently dropped when blocked. Without `--enforce`, behavior is observe-only (backward compatible) (ASI02, ASI05).
- **BlockedContent enforcement**: The `blocked_content` agent config field (previously dead code) is now enforced. When a scan finding's category matches an entry in the agent's `blocked_content` list, the verdict is escalated to block (ASI02).
- **Category field in FindingSummary**: Scan findings now include the Aguara rule category, enabling per-agent category-based filtering.
- **Per-agent rate limiting**: New `rate_limit` config section with `per_agent` (max messages per window) and `window` (seconds). Uses a sliding-window counter. Returns HTTP 429 when exceeded. Checked before any expensive operations. Disabled when `per_agent` is 0 (ASI02, ASI10).
- **Anomaly detection loop**: Background goroutine periodically queries `QueryAgentRisk()` and fires `agent_risk_elevated` webhook events when an agent's risk score exceeds the configured threshold. Configurable via `anomaly.check_interval`, `anomaly.risk_threshold`, `anomaly.min_messages`. Optional `anomaly.auto_suspend` automatically suspends high-risk agents (ASI10).
- **Multi-message verdict escalation**: Before applying the final verdict, the handler queries the last hour of audit entries for the sender. If 3+ recent blocks exist and the current verdict is flag → escalates to quarantine. If 5+ recent blocks and current verdict is quarantine → escalates to block. Uses the existing `idx_audit_ts_agent_status` index (ASI01).
- **Dashboard suspend toggle**: New `POST /dashboard/agents/{name}/suspend` route toggles agent suspension from the dashboard UI.
- **New decision labels**: Dashboard event detail now shows human-readable labels for `agent_suspended`, `recipient_suspended`, and `identity_rejected` policy decisions.

### Changed

- Handler pipeline expanded from 4 steps to 7: rate limit → identity → suspension → ACL → scan → blocked content → escalation → verdict.
- Stdio proxy refactored: split into `proxyClientToServer()` (can block + inject errors) and `proxyServerToClient()` (observe-only, always forwards). Mutex-protected stdout writes for concurrent goroutine safety.
- `FindingSummary` struct now includes `Category` field (populated from Aguara's `Finding.Category`).
- `NewStdioProxy()` signature updated to accept `enforce bool` parameter.

### OWASP Coverage

| Category | Before | After |
|----------|--------|-------|
| ASI01 - Goal Hijack | Partial | **Partial+** |
| ASI02 - Tool Misuse | Partial | **Strong** |
| ASI03 - Identity/Privilege | Strong | **Strong+** |
| ASI05 - Code Execution | Weak | **Partial** |
| ASI10 - Rogue Agents | Partial | **Strong** |

## [0.3.0] - 2026-02-22

### Added

- **OpenClaw detection**: Discover and analyze OpenClaw AI agent installations. OpenClaw uses a WebSocket gateway and JSON5 config (`~/.openclaw/openclaw.json`) instead of MCP — oktsec now parses both.
- **`oktsec scan-openclaw`**: New command that assesses OpenClaw config risk (7 checks) and scans workspace files (SOUL.md, AGENTS.md, TOOLS.md, USER.md) with the Aguara engine.
- **7 OCLAW detection rules** (OCLAW-001 through OCLAW-007) in new `openclaw-config` category:
  - OCLAW-001: Full tool profile without restrictions (critical)
  - OCLAW-002: Gateway exposed to network (high)
  - OCLAW-003: Open DM policy (high)
  - OCLAW-004: Exec/shell tool without sandbox (critical)
  - OCLAW-005: Path traversal in `$include` (critical)
  - OCLAW-006: Gateway missing authentication (high)
  - OCLAW-007: Hardcoded credentials in config (high)
- **`oktsec discover`** now detects OpenClaw installations and prints risk summary when found.
- **`oktsec wrap openclaw`** returns a clear error explaining the WebSocket architecture difference and points to `scan-openclaw`.
- **Dashboard** shows `openclaw-config` category on the rules page.
- **JSON5 support**: Config parser strips `//` and `/* */` comments from OpenClaw configs.
- **Risk assessor**: `discover.AssessOpenClawRisk()` checks 7 patterns: full tool profiles, exposed gateways, open DM policies, unsandboxed agents, path traversal in includes, exec tools, and messaging channel attack surface.

### Changed

- `oktsec init` now assigns risk level "high" to OpenClaw-sourced agents.
- Discovery fallback text updated to include OpenClaw.
- Total rule count: 151 (138 Aguara + 6 IAP + 7 OCLAW).

## [0.2.0] - 2026-02-22

### Added

- **Quarantine Queue**: Messages triggering high-severity rules are held for human review instead of being silently delivered. Quarantined messages return HTTP 202 with a `quarantine_id` for status polling. Reviewers can approve (delivers the message) or reject from dashboard, CLI, or MCP tool.
- **Dashboard v2**: Complete redesign with 5-tab navigation (Overview, Events, Rules, Agents, Settings).
  - **Events page**: Unified audit log and quarantine view with live SSE streaming, tab filters (All / Quarantine / Blocked), and human-readable event detail panels with clickable rule cards.
  - **Rules page**: Category card grid replacing the flat rule list. Click a category to drill into individual rules with inline enable/disable toggles.
  - **Settings page**: Security mode (enforce/observe), agent key management with revocation, quarantine configuration, server info.
  - **Analytics on Overview**: Top triggered rules, agent risk scores, severity distribution, hourly activity chart.
- **Agent CRUD**: Create, edit, and delete agents from the dashboard. Generate Ed25519 keypairs per agent. Agent metadata fields: description, creator, location, tags.
- **Brute-force protection**: Dashboard login rate-limited to 5 attempts per 15 minutes per IP (in-memory, no external dependencies).
- **MCP tool `review_quarantine`**: AI agents can list, inspect, approve, or reject quarantine items programmatically.
- **CLI `oktsec quarantine`**: Subcommands for `list`, `detail`, `approve`, `reject` with table output.
- **Log retention**: Configurable `retention_days` auto-purges audit entries older than N days. Runs alongside quarantine expiry in the background.

### Changed

- **Analytics queries use 24-hour time window**: `QueryTopRules`, `QueryAgentRisk`, and `QueryHourlyStats` now scan only the last 24 hours instead of the full table. Reduces query time from ~1,000ms to ~6ms at 1M rows.
- **Composite index** `(timestamp, from_agent, status)` added for covering index scans on analytics queries.
- **ANALYZE on startup**: SQLite query planner statistics are updated on every server start for optimal index usage.
- **RFC3339 timestamp comparisons**: All time-window queries use Go-computed RFC3339 cutoffs instead of SQLite's `datetime()` function, ensuring correct index utilization.
- Quarantine verdict now returns HTTP 202 Accepted (was 200 OK).
- Legacy dashboard URLs (`/dashboard/logs`, `/dashboard/identity`, `/dashboard/analytics`, `/dashboard/quarantine`) redirect to new locations with 301.

### Performance

| Query (at 1M rows) | Before | After |
|---------------------|--------|-------|
| Top rules           | 1,061 ms | 5.9 ms |
| Agent risk          | 980 ms | 1.6 ms |
| Hourly stats        | 55 ms | 1.4 ms |
| Write throughput    | — | ~90K inserts/sec (batched) |

## [0.1.0] - 2026-02-20

### Added

- Initial release: HTTP proxy, Ed25519 identity, YAML policy, SQLite audit trail.
- 144 detection rules (138 Aguara + 6 inter-agent protocol).
- Dashboard v1 with real-time log viewer.
- MCP integration (`scan_message`, `query_audit`).
- CLI: `serve`, `keygen`, `verify`, `logs`, `rules`, `version`.
- Auto-discovery of existing MCP servers (`oktsec init`).
