diff --git a/README.md b/README.md index a690600c..f4322389 100644 --- a/README.md +++ b/README.md @@ -339,8 +339,13 @@ tiers that need one, the code) back to the *existing* auth-challenge machinery r decision path, which performs the real verification unchanged. The channel engages only while a dashboard's liveness heartbeat is fresh (< 5s old); a stale or missing heartbeat, or an unanswered approval, falls back to the next channel (MCP elicitation → GUI dialog → terminal) -with no added latency and no denial invented on the dashboard's behalf. Visual polish lands in -upcoming versions. +with no added latency and no denial invented on the dashboard's behalf. + +**Visual polish.** Dark-by-default (a `prefers-color-scheme: light` override is available), +with color-coded PASS/AUTH/BLOCK and risk badges in the live feed and pending-approval cards, a +header bar showing the current mode + effective enforcement at a glance, and a designed empty +state before any decisions arrive — no build step, no external assets, works fully offline like +the rest of the shell. ### Try the demo @@ -489,6 +494,7 @@ The adaptive layer's four SL5 "care" weights (`confidentiality`, `reversibility` - ✅ **Turn gate (Feature 11):** a second, pre-inference invocation point (`doberman.turngate`) that judges the user's *turn* — prompt plus attached/pasted/tool-fetched content — before a single inference token is spent. Tier 0 deterministic signatures (instruction nullification, authority override, secret export, encoded payload) hard-block on an issue-vs-mention + origin discrimination (untrusted-origin match always blocks; a typed *mention* steps up instead of blocking); Tier 1 heuristic classes (embedded pasted instructions, persona override, obfuscation, urgency+secrecy framing) are AUTH-only and structurally block-incapable; a stylometric co-occurrence gate steps up only when an extreme per-entity style outlier coincides with a sensitive apparent intent, never on style alone; a repeat-after-block escape hatch scales the re-challenge to the original block (Tier 0 → 2FA) with single-use approval and a third-attempt lockout. Released turns tag-and-pass a bounded, raise-only `TurnContext` into the action stage (a flagged turn's follow-on actions score harsher; flagged pasted segments inherit `provenance: untrusted_data`). The turn gate is additive and an efficiency/early-warning layer only — the action gate above remains the safety guarantee, and with no host pre-inference hook or `DOBERMAN_TURN_GATE=off` it is simply absent. - ✅ **Turn gate boundary:** the import-linter contract now forbids the policy core from importing **either** invocation adapter (`doberman.proxy`, `doberman.turngate`) — the turn gate stays a pure adapter, injected into the engine like the proxy, never a static dependency of it. - ✅ Dashboard, interactive AUTH approve/deny (D3): a `pending_approvals` queue mediates between the decision path and the dashboard purely through SQLite — never HTTP into the decision path. `DashboardPrompter` implements the existing `Prompter` interface, engaging the queue only while a liveness heartbeat is fresh; a stale/missing heartbeat, an unanswered approval, or a poll timeout all fall back to the next channel (elicitation → GUI → terminal) with zero added latency and no denial invented on the dashboard's behalf. Resolution is a single-use, race-safe `UPDATE ... WHERE status='pending'` transition (a resolved/expired row 409s), and the dashboard only ever relays a decision (plus, for 2FA tiers, a code) — verification stays entirely in the decision-path process via the existing TOTP check. Pending rows carry only already-redacted fields (action type, risk, reason codes, explanation, path class) — never a raw target or secret +- ✅ Dashboard visual polish (D5): color-coded PASS/AUTH/BLOCK and risk badges (mirroring the terminal's `[RISK: ]` convention) in the live feed and pending-approval cards, a header bar surfacing the current mode + effective enforcement from the existing `/api/stats` fields, and a CSS-only designed empty state for both the feed and the pending-approvals list before any decisions arrive. The dark-by-default palette is formalized as CSS custom properties with a `prefers-color-scheme: light` override — still one inline shell, no build step, no new dependencies, no endpoint/auth/redaction changes - 📋 Host-harness, continued (containment architecture): deeper Bash-command egress parsing · entropy-on-egress escalation · warm-daemon adaptive layer · honeytoken tripwire + session circuit-breaker - 🛠 Cost observability — **CB.1 + CB.2 landed**: a redaction-safe `CostEvent` + local append-only meter (`doberman.storage.cost`), advisory and strictly off the decision path; plus a `CostObserver` plugin seam (`doberman.cost_observers` entry-point group) — observers receive a copy of every recorded event, are isolated (a raising observer is logged and skipped, never breaks the record path), and can never alter a verdict. Next: raise-only loop-anomaly detector (CB.3) - 📋 Enterprise platform: centralized control plane, dashboards, org policy, SSO/RBAC diff --git a/src/doberman/dash/app.py b/src/doberman/dash/app.py index 1f765e0a..a97fe5b1 100644 --- a/src/doberman/dash/app.py +++ b/src/doberman/dash/app.py @@ -44,7 +44,10 @@ decision-path side, which feeds it through the EXISTING :func:`doberman.auth.totp.verify`. -D5 (polish) is a later slice - not built here. +D5 (polish) layers verdict/risk color badges, a mode + enforcement header bar, +and CSS-only empty states onto this same inline shell - the dark-by-default +palette is formalized as CSS custom properties. Still no build toolchain, no +new endpoints, no change to auth/redaction/decision-path behavior. """ from __future__ import annotations @@ -82,65 +85,140 @@ Doberman Dashboard -

Doberman Dashboard (preview)

-
connecting...
+
+

Doberman Dashboard

+
connecting...
+ mode: - + enforcement: - +
stats loading...

Pending approvals

-
no pending approvals
+
No pending approvals right now.

Recent decisions

+
Waiting for the first decision...