|
| 1 | +# ADR-053: one light KeyLoad visual identity for the console and the site |
| 2 | + |
| 3 | +Status: Accepted. Date: 2026-10-02. Owner: KeyLoad lead. Related: REQ-AD-008..010 / AC-AD-008..010 ([AdminDashboard](../Features/AdminDashboard.md)), REQ-BC-029 / AC-BC-029 ([BenchmarkComparisons](../Features/BenchmarkComparisons.md)), ADR-040 site design, ADR-051 admin console. |
| 4 | + |
| 5 | +## Context |
| 6 | + |
| 7 | +The owner rejected the visuals of both surfaces: |
| 8 | +- The runtime console (`/admin`) used a dark mint theme, a text monogram and a single polyline chart. |
| 9 | +- The public site used a warm-paper/forest editorial style with serif display type. |
| 10 | + |
| 11 | +The two surfaces shared no logo, palette, typography or components, so KeyLoad read as two unrelated products. The owner asked for: |
| 12 | +- one style across both surfaces, starting with a simple, clear, light and attractive console; |
| 13 | +- clear charts; |
| 14 | +- convenient menus and categories; |
| 15 | +- error logs, data volume, performance and nodes. |
| 16 | + |
| 17 | +## Decision |
| 18 | + |
| 19 | +- **One brand source.** `src/KeyLoad.Server/Features/AdminDashboard/Assets/brand.css` holds the tokens (surfaces, ink, brand blue/indigo gradient, reserved status colours, the dataviz-validated categorical chart order, radii, shadows, focus ring and system font stacks) and the shared primitives (`kl-brand`, `kl-btn`, `kl-card`, `kl-badge`, `kl-chip`, reduced motion). |
| 20 | + - The logo `logo.svg` is a rounded indigo→blue tile with a "K" whose stem is three stacked replica blocks (RF3) and whose arms form a forward chevron. |
| 21 | + - `site/Features/BenchmarkComparisons/brand.css` and `site/favicon.svg` are byte-identical mirrors. |
| 22 | + - The SiteTests drift test `AC_VI_001` fails on any difference. Both surfaces keep their own CSP-compatible, same-origin delivery: the console whitelists embedded assets, and the site build copies listed assets. |
| 23 | +- **Light only.** System fonts only. No external fonts or CDNs. The console CSP is unchanged: styles and scripts are same-origin and SVG is drawn through DOM APIs. Dynamic geometry uses CSSOM properties only. |
| 24 | +- **Console information architecture.** |
| 25 | + - **Monitoring:** |
| 26 | + - Overview: KPI tiles with sparklines, a stacked request-activity chart, a storage donut, a node card, admission and recent errors. |
| 27 | + - Performance: throughput, latency and error-rate charts, lifetime totals and admission meters. |
| 28 | + - Errors & logs: the server failure log with status filters, plus session events. |
| 29 | + - **Data:** Catalog with kind chips, Collections, Queues and Blob storage. |
| 30 | + - **Infrastructure:** Nodes (RF3 voter figure and details) and Disk usage (category bar and largest files). |
| 31 | + - Every original `data-view` and pinned browser hook is preserved. |
| 32 | +- **Real data only.** Charts plot at most 120 comparable session samples and reset on process change, failure or reconnect. The error log is a new bounded server observation: `AdminHttpSnapshot.RecentFailures`, at most 50 newest-first entries holding the route template, normalised method, status, aborted flag and duration. It never holds a raw path, query, payload or credential. |
| 33 | + - The voter figure uses configured membership (`AdminNodeSnapshot.LocalVoter`, `Voters`) and the reported leader. Peers are labelled as not observed from the executing node. |
| 34 | +- **Site.** The site gets the same tokens, logo, sans display type, cards, buttons, tabs, bars and tables. Engine colours and the Three.js scene colours move to the brand palette. All site hooks, budgets and lifecycle contracts are unchanged. |
| 35 | + |
| 36 | +```mermaid |
| 37 | +flowchart LR |
| 38 | + Brand[brand.css and logo.svg canonical in console Assets] --> Console[admin console embedded whitelist] |
| 39 | + Brand -->|byte identical mirror| Site[site brand.css and favicon.svg] |
| 40 | + Drift[SiteTests AC_VI_001 parity] --> Site |
| 41 | + Drift --> Brand |
| 42 | + Server[AdminHttpMetrics ring of 50 failures] --> Snapshot[AdminNodeSnapshot] |
| 43 | + Config[Replica voter membership] --> Snapshot |
| 44 | + Snapshot --> Console |
| 45 | +``` |
| 46 | + |
| 47 | +## Alternatives |
| 48 | + |
| 49 | +- Restyle each surface separately. Rejected because drift returns. |
| 50 | +- A shared npm or MSBuild design package. Rejected: it adds tooling and dependencies, the Docker context holds only `src/`, and the site build is a separate pipeline. |
| 51 | +- Inline the logo into each page. Rejected because the favicon and logo bytes must stay one fact. |
| 52 | + |
| 53 | +## Implementation contract |
| 54 | + |
| 55 | +1. **VI-L (lead):** brand tokens and logo, mirrored to the site. Done before the UI packets. |
| 56 | +2. **VI-B (worker, sonnet):** ring buffer and middleware in `src/KeyLoad.Server/Features/AdminDashboard/AdminHttp*.cs`, with unit tests `AdminHttpMetricsTests` and `AdminHttpMetricsMiddlewareTests` written first. The DTO is frozen by the lead in Abstractions. |
| 57 | +3. **VI-D (lead):** console `Assets/*` and the `AdminStaticAssets` whitelist. The lead also adds the voter membership fields and observer, and owns the `AdminDashboardRf3Tests` assertions. |
| 58 | +4. **VI-S (lead):** site HTML/CSS/poster, colour constants in `measurements.mjs` and `scene-geometry.mjs`, `BUILD.assets` and SiteTests parity. |
| 59 | +5. **VI-J (lead):** feature docs, this ADR, the Architecture map and exact-SHA CI evidence. |
| 60 | + |
| 61 | +Dependencies: |
| 62 | +- Contract additions are additive init properties with defaults. The SDK and the official MCP output pick them up from the DTO type. |
| 63 | +- No schema, storage, routing or package change. |
| 64 | + |
| 65 | +Migration, rollback and verification: |
| 66 | +- **Rollout:** a single release. The console and the site deploy independently. |
| 67 | +- **Rollback:** revert the assets and remove the three init properties. Stored data is untouched. |
| 68 | +- **Verification:** |
| 69 | + - ci.yml unit tests: metrics ring and middleware. |
| 70 | + - RF3: failure-log route template and voter membership through the real SDK and official MCP. |
| 71 | + - Real Chrome console flow: existing hooks plus new views. |
| 72 | + - pages.yml SiteTests: unchanged hooks, budgets and the parity test. |
| 73 | + - Subjective beauty is judged from desktop/mobile screenshots of a real RF3 cluster (manual exception). It never replaces a functional gate. |
| 74 | + |
| 75 | +Join points: shared enum/DTO edits are lead-only, and backend and UI write scopes are disjoint. This ADR stays Accepted until exact-SHA unit, RF3 browser and site qualification pass. |
0 commit comments