feat(ep-td+dashboard): complete CUST-WP-0004 EP/TD tracking workstream

EP catalogue (all domains):
- EP-RAIL-001 ep_id patched (schema fix: add ep_id to EPUpdate)
- EP-RAIL-003 (git bare-repo mirrors) and EP-RAIL-004 (offsite secondary
  backup) registered from railiance-cluster/docs/backup-restore.md
- EP-CUST-003..007 ep_ids assigned to existing custodian EPs
- EP-CUST-008 (State Hub API auth) and EP-CUST-009 (update_workstream MCP
  tool) registered as new custodian extension points

TD catalogue (railiance — first 5 items):
- TD-RAIL-001: backup cron runs as root without audit trail (high/security)
- TD-RAIL-002: k3s kubeconfig world-readable mode 644 (medium/security)
- TD-RAIL-003: no Ansible role unit tests (medium/test)
- TD-RAIL-004: age key extracted via awk — fragile (medium/impl)
- TD-RAIL-005: etcd snapshot retention uncoordinated (low/impl)

Dashboard (T08 + T10):
- Extract API URL and POLL to src/components/config.js; all 15 pages
  now import from the shared module (contributions/goals keep custom POLL)
- Shared .kpi-infobox, .filter-bar, .filter-search/.filter-owner CSS
  moved to observablehq.config.js head <style> block; removed from 9 pages
- Build: 0 errors, 0 warnings

API (T09):
- progress.py: limit param now Query(100, le=1000) — prevents unbounded
  list requests; closes TD-CUST-004 for the only endpoint that had limit

CUST-WP-0004 marked completed (all 10 tasks done).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 01:40:52 +01:00
parent 7b665a5d66
commit 9f744dd7f3
18 changed files with 27 additions and 76 deletions

View File

@@ -3,8 +3,7 @@ title: Decisions
---
```js
const API = "http://127.0.0.1:8000";
const POLL = 15_000;
import {API, POLL} from "./components/config.js";
```
```js
@@ -392,25 +391,6 @@ if (escalated.length > 0) {
margin-bottom: 0.75rem;
}
/* ── KPI infobox ──────────────────────────────────────────────────────────── */
.kpi-infobox {
background: var(--theme-background-alt, #f9f9f9);
border: 1px solid var(--theme-foreground-faint, #e0e0e0);
border-radius: 10px;
padding: 0.75rem 1rem;
position: relative;
box-shadow: 0 1px 6px rgba(0,0,0,0.07);
margin-bottom: 1.25rem;
}
.kpi-infobox-title {
font-size: 0.68rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--theme-foreground-muted, #888);
margin-bottom: 0.55rem;
padding-right: 1.6rem; /* room for ? button */
}
.kpi-row {
display: flex;
justify-content: space-between;
@@ -445,10 +425,6 @@ if (escalated.length > 0) {
/* ── Utility ──────────────────────────────────────────────────────────────── */
.dim { color: gray; font-style: italic; }
/* ── Filter bar ───────────────────────────────────────────────────────────── */
.filter-bar { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 1rem; }
.filter-search { display: flex; align-items: center; }
.filter-search input { height: 30px; font-size: 0.85rem; padding: 0.25rem 0.5rem; border-radius: 6px; border: 1px solid var(--theme-foreground-faint, #ccc); background: var(--theme-background, #fff); font-family: inherit; color: inherit; }
/* ── Decision list ────────────────────────────────────────────────────────── */
.dec-list { display: flex; flex-direction: column; gap: 0.5rem; }