From 2cd061c1d13313d1f400ad25850c750b24294e6a Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 11 Mar 2026 01:40:52 +0100 Subject: [PATCH] feat(ep-td+dashboard): complete CUST-WP-0004 EP/TD tracking workstream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 `, footer: "Custodian State Hub — local-first, append-only, sovereignty-preserving.", }; diff --git a/state-hub/dashboard/src/components/config.js b/state-hub/dashboard/src/components/config.js new file mode 100644 index 0000000..e84e170 --- /dev/null +++ b/state-hub/dashboard/src/components/config.js @@ -0,0 +1,2 @@ +export const API = "http://127.0.0.1:8000"; +export const POLL = 15_000; diff --git a/state-hub/dashboard/src/contributions.md b/state-hub/dashboard/src/contributions.md index 0915195..0bfa3ca 100644 --- a/state-hub/dashboard/src/contributions.md +++ b/state-hub/dashboard/src/contributions.md @@ -3,7 +3,7 @@ title: Contributions --- ```js -const API = "http://127.0.0.1:8000"; +import {API} from "./components/config.js"; const POLL = 30_000; ``` diff --git a/state-hub/dashboard/src/decisions.md b/state-hub/dashboard/src/decisions.md index c5ae0c7..77ad493 100644 --- a/state-hub/dashboard/src/decisions.md +++ b/state-hub/dashboard/src/decisions.md @@ -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; } diff --git a/state-hub/dashboard/src/dependencies.md b/state-hub/dashboard/src/dependencies.md index 8c15fde..f047d59 100644 --- a/state-hub/dashboard/src/dependencies.md +++ b/state-hub/dashboard/src/dependencies.md @@ -3,8 +3,7 @@ title: Dependencies --- ```js -const API = "http://127.0.0.1:8000"; -const POLL = 15_000; +import {API, POLL} from "./components/config.js"; ``` ```js @@ -136,8 +135,6 @@ if (edges.length === 0) { .live-indicator { font-size: 0.8rem; color: gray; position: relative; padding: 0.55rem 1.8rem 0.55rem 0.7rem; 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; } .kpi-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.3rem 0; } .kpi-row + .kpi-row { border-top: 1px solid var(--theme-foreground-faint, #eee); } .kpi-row-label { font-size: 0.8rem; color: var(--theme-foreground-muted, #666); white-space: nowrap; } diff --git a/state-hub/dashboard/src/domains.md b/state-hub/dashboard/src/domains.md index 6f31c04..a004378 100644 --- a/state-hub/dashboard/src/domains.md +++ b/state-hub/dashboard/src/domains.md @@ -3,8 +3,7 @@ title: Domains --- ```js -const API = "http://127.0.0.1:8000"; -const POLL = 15_000; +import {API, POLL} from "./components/config.js"; ``` ```js diff --git a/state-hub/dashboard/src/extensions.md b/state-hub/dashboard/src/extensions.md index 9563089..fdc7245 100644 --- a/state-hub/dashboard/src/extensions.md +++ b/state-hub/dashboard/src/extensions.md @@ -3,8 +3,7 @@ title: Extension Points --- ```js -const API = "http://127.0.0.1:8000"; -const POLL = 15_000; +import {API, POLL} from "./components/config.js"; ``` ```js @@ -210,8 +209,6 @@ display(html`
${filtered.map(ep => html` .live-indicator { font-size: 0.8rem; color: gray; position: relative; padding: 0.55rem 1.8rem 0.55rem 0.7rem; 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; } .kpi-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.3rem 0; border-top: 1px solid var(--theme-foreground-faint, #eee); } .kpi-row:first-of-type { border-top: none; } .kpi-row-label { font-size: 0.8rem; color: var(--theme-foreground-muted, #666); } @@ -225,7 +222,6 @@ display(html`
${filtered.map(ep => html` .chart-row { display: flex; flex-wrap: wrap; gap: 1.5rem; align-items: flex-start; } /* ── Filters ──────────────────────────────────────────────────────────────── */ -.filter-bar { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 1rem; } /* ── EP list ──────────────────────────────────────────────────────────────── */ .ep-list { display: flex; flex-direction: column; gap: 0.5rem; } diff --git a/state-hub/dashboard/src/goals.md b/state-hub/dashboard/src/goals.md index d3eba71..c109537 100644 --- a/state-hub/dashboard/src/goals.md +++ b/state-hub/dashboard/src/goals.md @@ -3,7 +3,7 @@ title: Goals --- ```js -const API = "http://127.0.0.1:8000"; +import {API} from "./components/config.js"; const POLL = 20_000; ``` @@ -253,8 +253,6 @@ if (unlinkedRepoGoals.length > 0) { .live-indicator { font-size: 0.8rem; color: gray; position: relative; padding: 0.55rem 1.8rem 0.55rem 0.7rem; 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; } .kpi-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.3rem 0; } .kpi-row + .kpi-row { border-top: 1px solid var(--theme-foreground-faint, #eee); } .kpi-row-label { font-size: 0.8rem; color: var(--theme-foreground-muted, #666); white-space: nowrap; } diff --git a/state-hub/dashboard/src/index.md b/state-hub/dashboard/src/index.md index c180c28..be14899 100644 --- a/state-hub/dashboard/src/index.md +++ b/state-hub/dashboard/src/index.md @@ -3,8 +3,7 @@ title: Overview --- ```js -const API = "http://127.0.0.1:8000"; -const POLL = 15_000; +import {API, POLL} from "./components/config.js"; ``` ```js diff --git a/state-hub/dashboard/src/interventions.md b/state-hub/dashboard/src/interventions.md index dad9da1..c450ccd 100644 --- a/state-hub/dashboard/src/interventions.md +++ b/state-hub/dashboard/src/interventions.md @@ -3,8 +3,7 @@ title: Interventions --- ```js -const API = "http://127.0.0.1:8000"; -const POLL = 15_000; +import {API, POLL} from "./components/config.js"; ``` ```js @@ -193,8 +192,6 @@ if (closed.length === 0) { .live-indicator { font-size: 0.8rem; color: gray; position: relative; padding: 0.55rem 1.8rem 0.55rem 0.7rem; 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; } .kpi-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.3rem 0; } .kpi-row + .kpi-row { border-top: 1px solid var(--theme-foreground-faint, #eee); } .kpi-row-label { font-size: 0.8rem; color: var(--theme-foreground-muted, #666); white-space: nowrap; } diff --git a/state-hub/dashboard/src/progress.md b/state-hub/dashboard/src/progress.md index 3b5e5ed..8394032 100644 --- a/state-hub/dashboard/src/progress.md +++ b/state-hub/dashboard/src/progress.md @@ -3,8 +3,7 @@ title: Progress --- ```js -const API = "http://127.0.0.1:8000"; -const POLL = 15_000; +import {API, POLL} from "./components/config.js"; ``` ```js diff --git a/state-hub/dashboard/src/repos.md b/state-hub/dashboard/src/repos.md index 051975c..a130c8f 100644 --- a/state-hub/dashboard/src/repos.md +++ b/state-hub/dashboard/src/repos.md @@ -3,7 +3,7 @@ title: Repos --- ```js -const API = "http://127.0.0.1:8000"; +import {API} from "./components/config.js"; ``` ```js diff --git a/state-hub/dashboard/src/sbom.md b/state-hub/dashboard/src/sbom.md index 824343f..8603988 100644 --- a/state-hub/dashboard/src/sbom.md +++ b/state-hub/dashboard/src/sbom.md @@ -3,7 +3,7 @@ title: SBOM --- ```js -const API = "http://127.0.0.1:8000"; +import {API} from "./components/config.js"; ``` ```js diff --git a/state-hub/dashboard/src/tasks.md b/state-hub/dashboard/src/tasks.md index 9c8e9a6..1578402 100644 --- a/state-hub/dashboard/src/tasks.md +++ b/state-hub/dashboard/src/tasks.md @@ -3,8 +3,7 @@ title: Tasks --- ```js -const API = "http://127.0.0.1:8000"; -const POLL = 15_000; +import {API, POLL} from "./components/config.js"; ``` ```js @@ -235,8 +234,6 @@ display(buildEntityTable( .live-indicator { font-size: 0.8rem; color: gray; position: relative; padding: 0.55rem 1.8rem 0.55rem 0.7rem; 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; } .kpi-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.3rem 0; } .kpi-row + .kpi-row { border-top: 1px solid var(--theme-foreground-faint, #eee); } .kpi-row-label { font-size: 0.8rem; color: var(--theme-foreground-muted, #666); white-space: nowrap; } @@ -245,9 +242,6 @@ display(buildEntityTable( .kpi-row-sub { font-size: 0.68rem; color: var(--theme-foreground-faint, #aaa); line-height: 1.2; } /* ── Filters ──────────────────────────────────────────────────────────────── */ -.filter-bar { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 1rem; } -.filter-owner { display: flex; align-items: center; } -.filter-owner 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; } /* ── Blocked task cards ───────────────────────────────────────────────────── */ .task-blocked-list { display: flex; flex-direction: column; gap: 0.5rem; } diff --git a/state-hub/dashboard/src/techdept.md b/state-hub/dashboard/src/techdept.md index 0fa2ef6..f2545ec 100644 --- a/state-hub/dashboard/src/techdept.md +++ b/state-hub/dashboard/src/techdept.md @@ -3,8 +3,7 @@ title: Technical Debt --- ```js -const API = "http://127.0.0.1:8000"; -const POLL = 15_000; +import {API, POLL} from "./components/config.js"; ``` ```js @@ -246,8 +245,6 @@ display(html`
${filtered.map(t => html` .live-indicator { font-size: 0.8rem; color: gray; position: relative; padding: 0.55rem 1.8rem 0.55rem 0.7rem; 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; } .kpi-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.3rem 0; border-top: 1px solid var(--theme-foreground-faint, #eee); } .kpi-row:first-of-type { border-top: none; } .kpi-row-label { font-size: 0.8rem; color: var(--theme-foreground-muted, #666); } @@ -259,7 +256,6 @@ display(html`
${filtered.map(t => html` .chart-row { display: flex; flex-wrap: wrap; gap: 1.5rem; align-items: flex-start; } /* ── Filters ──────────────────────────────────────────────────────────────── */ -.filter-bar { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 1rem; } /* ── TD list ──────────────────────────────────────────────────────────────── */ .td-list { display: flex; flex-direction: column; gap: 0.5rem; } diff --git a/state-hub/dashboard/src/todo.md b/state-hub/dashboard/src/todo.md index 769b182..b02e13c 100644 --- a/state-hub/dashboard/src/todo.md +++ b/state-hub/dashboard/src/todo.md @@ -3,8 +3,7 @@ title: Todo --- ```js -const API = "http://127.0.0.1:8000"; -const POLL = 15_000; +import {API, POLL} from "./components/config.js"; const THIS_REPO = "the-custodian"; ``` @@ -204,8 +203,6 @@ if (thirdParty.length === 0) { .live-indicator { font-size: 0.8rem; color: gray; position: relative; padding: 0.55rem 1.8rem 0.55rem 0.7rem; 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; } .kpi-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.3rem 0; } .kpi-row + .kpi-row { border-top: 1px solid var(--theme-foreground-faint, #eee); } .kpi-row-label { font-size: 0.8rem; color: var(--theme-foreground-muted, #666); white-space: nowrap; } diff --git a/state-hub/dashboard/src/workstreams.md b/state-hub/dashboard/src/workstreams.md index b6b8f12..3576ede 100644 --- a/state-hub/dashboard/src/workstreams.md +++ b/state-hub/dashboard/src/workstreams.md @@ -3,8 +3,7 @@ title: Workstreams --- ```js -const API = "http://127.0.0.1:8000"; -const POLL = 15_000; +import {API, POLL} from "./components/config.js"; ``` ```js @@ -330,8 +329,6 @@ if (wsWithDeps.length === 0) { .live-indicator { font-size: 0.8rem; color: gray; position: relative; padding: 0.55rem 1.8rem 0.55rem 0.7rem; margin-bottom: 0.75rem; } /* ── KPI infobox base (shared) ───────────────────────────────────────────── */ -.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; } .kpi-row { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 0.3rem 0; } .kpi-muted { color: var(--theme-foreground-faint, #aaa); font-style: italic; font-size: 0.8rem; } @@ -352,9 +349,6 @@ if (wsWithDeps.length === 0) { .whi-domain-name { flex: 1; font-size: 0.75rem; color: var(--theme-foreground-muted, #666); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .whi-domain-score { font-variant-numeric: tabular-nums; font-weight: 600; font-size: 0.75rem; } .dim { color: gray; font-style: italic; } -.filter-bar { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 1rem; } -.filter-owner { display: flex; align-items: center; } -.filter-owner 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; } .dep-grid { display: flex; flex-direction: column; gap: 0.75rem; } .dep-card { border: 1px solid #e0e0e0; border-radius: 6px; padding: 0.75rem 1rem; background: var(--theme-background-alt, #fafafa); } .dep-title { font-weight: 600; margin-bottom: 0.25rem; } diff --git a/workplans/CUST-WP-0004-ep-td-tracking.md b/workplans/CUST-WP-0004-ep-td-tracking.md index 4e582c8..d8e9ead 100644 --- a/workplans/CUST-WP-0004-ep-td-tracking.md +++ b/workplans/CUST-WP-0004-ep-td-tracking.md @@ -3,12 +3,13 @@ id: CUST-WP-0004 type: workplan title: "Extension Points & Technical Debt Tracking" domain: custodian -status: active +status: completed owner: custodian topic_slug: custodian state_hub_workstream_id: e84ecd70-b276-4a93-a298-1ef1299b7c22 created: "2026-02-27" -updated: "2026-02-28" +updated: "2026-03-11" +completed: "2026-03-11" --- # Extension Points & Technical Debt Tracking @@ -87,7 +88,7 @@ endpoints). ```task id: CUST-WP-0004-T05 state_hub_task_id: 00492d87-3bb7-4df9-8f12-a06da0307fbc -status: todo +status: done priority: medium ``` @@ -99,7 +100,7 @@ Register findings as `TD-RAIL-xxx` items via the `/technical-debt/` API. ```task id: CUST-WP-0004-T06 state_hub_task_id: 3069aa1d-3d5f-4b9f-be8b-dfa0ffe690fe -status: todo +status: done priority: medium ``` @@ -112,7 +113,7 @@ gaps, integration opportunities. ```task id: CUST-WP-0004-T07 state_hub_task_id: 3a355a74-237f-4572-af05-683eceb32694 -status: todo +status: done priority: low ``` @@ -123,7 +124,7 @@ Identify and register extension points in railiance as `EP-RAIL-xxx` items. ```task id: CUST-WP-0004-T08 state_hub_task_id: a9b5d39e-706b-4f71-8f5d-ce4f927b3e4c -status: todo +status: done priority: high ``` @@ -136,7 +137,7 @@ variable. ```task id: CUST-WP-0004-T09 state_hub_task_id: 7050eb96-964d-4c06-a9f5-6d49db6b9c98 -status: todo +status: done priority: high ``` @@ -149,7 +150,7 @@ technical_debt) to prevent memory exhaustion. ```task id: CUST-WP-0004-T10 state_hub_task_id: c54553be-d947-4b8d-9c16-eb1a0e9ae3a0 -status: todo +status: done priority: medium ```