generated from coulomb/repo-seed
Finish IHUB-WP-0020 design work (status finished, all design tasks done) and add IHUB-WP-0021 with the 12-task implementation workplan plus research, PRs, and FDD deliverables produced during the 2026-06-16 review.
416 lines
17 KiB
Markdown
416 lines
17 KiB
Markdown
---
|
|
id: IHUB-WP-0020
|
|
type: workplan
|
|
title: "Personal Dashboard Framework"
|
|
domain: inter_hub
|
|
repo: inter-hub
|
|
status: finished
|
|
owner: tegwick
|
|
topic_slug: inter_hub
|
|
created: "2026-05-03"
|
|
updated: "2026-06-16"
|
|
phase: 13
|
|
state_hub_workstream_id: "72fc022b-0196-492a-aaba-3475f8768f06"
|
|
---
|
|
|
|
# Personal Dashboard Framework
|
|
|
|
## Goal
|
|
|
|
Design the first personal dashboard layer for inter-hub: an authenticated,
|
|
per-user landing surface that composes the most important existing hub,
|
|
governance, API, marketplace, and learning signals into a configurable daily
|
|
operator view.
|
|
|
|
This workplan is now a design and implementation-planning workplan. It should
|
|
produce the current-state audit, product requirements, functional design, and
|
|
follow-on implementation workplan needed to build the feature safely.
|
|
|
|
## Review Update: 2026-06-15
|
|
|
|
This workplan was reviewed against the current repository state and updated
|
|
from `backlog` to `ready`.
|
|
|
|
The original version assumed inter-hub mainly had a raw Hubs list and needed a
|
|
greenfield dashboard framework. That assumption is outdated. The repo now has
|
|
many dashboard-like surfaces and governed interaction primitives that should be
|
|
reused instead of bypassed:
|
|
|
|
- Public root/intro pages exist from IHUB-WP-0015; the authenticated login flow
|
|
still redirects to `HubsAction`.
|
|
- Hub-level dashboard actions already exist in `Web.Controller.Hubs`, including
|
|
hub show, triage, governance, antifragility, agent audit, adapter
|
|
compatibility, friction heatmap, bottleneck, hub health history, and the
|
|
operational review board.
|
|
- Cross-hub and platform dashboards already exist: federated governance, policy
|
|
compliance, API usage, marketplace, and learning dashboard.
|
|
- The governed interaction substrate is mature: `widgets`, `widget_versions`,
|
|
`interaction_events`, `annotations`, type registries, hub manifests,
|
|
ownership/routing, API request logs, hub health snapshots, learning insights,
|
|
and institutional knowledge are all present.
|
|
- There is no personal dashboard schema, controller, saved panel catalogue,
|
|
user preference model, or role-aware default layout yet.
|
|
- Existing dashboards are mostly hard-coded controller queries plus HSX view
|
|
fragments. They are useful source material, but they are not yet reusable
|
|
panel renderers.
|
|
- The `users` table has no role column. `stewardship_roles.assigned_to` is text
|
|
and hub-scoped, so role-aware defaults must be designed carefully instead of
|
|
assuming a user-role foreign key exists.
|
|
|
|
The updated scope is therefore integration-first: define a personal dashboard
|
|
contract that reuses existing data sources and view patterns, then introduce a
|
|
small panel renderer abstraction only where it removes real duplication.
|
|
|
|
## Scope
|
|
|
|
### In Scope
|
|
|
|
- Authenticated personal dashboard route and post-login redirect design.
|
|
- Per-user saved dashboard record with ordered panel instances.
|
|
- A server-rendered panel catalogue backed by existing inter-hub models.
|
|
- Simple layout editing through IHP forms; no drag-and-drop in the first slice.
|
|
- Hub/time filters for panels where the underlying queries already support
|
|
bounded data.
|
|
- Panel-level governance: each rendered saved panel must be annotatable and
|
|
event-capturable through the existing `widgetEnvelope` convention.
|
|
- A migration path that reuses current dashboard queries before attempting broad
|
|
refactors.
|
|
|
|
### Out of Scope for the First Implementation Workplan
|
|
|
|
- Client-side dashboard frameworks or client-side data fetching.
|
|
- External datasource connectors.
|
|
- Shared/team dashboards.
|
|
- Mobile-native layout editing.
|
|
- Drag-and-drop layout editing.
|
|
- A general purpose report builder.
|
|
- Rewriting every existing dashboard into panel renderers.
|
|
|
|
## Current Design Constraints
|
|
|
|
- Server-rendered IHP views remain the default. `autoRefresh` is acceptable for
|
|
panels that already use live refresh patterns.
|
|
- Tailwind and existing HSX view conventions should be reused.
|
|
- Runtime panel config may be stored as JSONB, but renderer code should decode
|
|
into explicit Haskell config types before use.
|
|
- Do not create an ungoverned visual component layer. A saved dashboard panel
|
|
must either reference or create a `Widget` row, most likely using the existing
|
|
framework-level `panel` widget type, so annotations and interaction events
|
|
remain first-class IHF artifacts.
|
|
- Avoid adding a `users.role` column unless the PRS/FDD proves it is needed.
|
|
Prefer defaults derived from current user identity, stewardship assignments,
|
|
selected watched hubs, or explicit dashboard template choice.
|
|
|
|
## Proposed First-Slice Panel Catalogue
|
|
|
|
The initial catalogue should be limited to panels that can be built from
|
|
existing tables and controllers:
|
|
|
|
| Panel key | Label | Source surface/data | Live? |
|
|
|---|---|---|---|
|
|
| `watched-hubs` | Watched Hubs | `hubs`, `hub_health_snapshots`, optional saved hub filter | No |
|
|
| `recent-interactions` | Recent Activity | `interaction_events` plus `widgets` and `hubs` | Yes |
|
|
| `triage-queue` | Triage Queue | open `requirement_candidates` | Yes |
|
|
| `recent-decisions` | Recent Decisions | `decision_records`, requirements, candidates | No |
|
|
| `hub-health` | Hub Health | latest `hub_health_snapshots`, bottlenecks | Yes |
|
|
| `agent-proposals` | Agent Proposals | `agent_proposals`, `agent_review_records` | No |
|
|
| `api-usage` | API Usage | `api_consumers`, `api_request_log` | Yes |
|
|
| `marketplace-trending` | Marketplace Trending | `widget_patterns`, adoptions, templates | No |
|
|
| `learning-digest` | Learning Digest | `learning_insights`, `institutional_knowledge_entries` | Yes |
|
|
| `my-annotations` | My Annotations | `annotations` filtered by current user when available | No |
|
|
|
|
The implementation workplan should start with a smaller subset if needed:
|
|
`watched-hubs`, `recent-interactions`, `triage-queue`, `recent-decisions`,
|
|
`hub-health`, and `learning-digest` are enough to prove the framework.
|
|
|
|
## Tasks
|
|
|
|
### T01 - Current-state audit and dashboard pattern research
|
|
|
|
```task
|
|
id: IHUB-WP-0020-T01
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "6074f195-636b-4517-b6d1-eb3c57394a82"
|
|
```
|
|
|
|
Produce a short research note that starts with the current inter-hub codebase,
|
|
then uses external dashboard systems only for secondary inspiration.
|
|
|
|
Required current-state inventory:
|
|
|
|
- Existing routes and views that behave like dashboards.
|
|
- Existing `autoRefresh` usage and query patterns that are safe to reuse.
|
|
- Existing type registry, `Widget`, `widgetEnvelope`, annotation, and event
|
|
capture constraints.
|
|
- Existing tables that can power first-slice personal panels.
|
|
- Gaps: personal dashboard persistence, panel catalogue, saved filters, layout
|
|
model, and user preference/defaulting model.
|
|
|
|
External systems may still be sampled, but the output should focus on patterns
|
|
that are practical in IHP/HSX/Tailwind:
|
|
|
|
| System | What to extract |
|
|
|---|---|
|
|
| Grafana | Panel/grid layout model, dashboard variables, bounded refresh |
|
|
| Kibana dashboards | Saved-search panels, time range filters, role visibility |
|
|
| Retool/Appsmith | Widget catalogue and data binding concepts, not their client runtime |
|
|
| Linear home view | Flat "my work" aggregation across entities |
|
|
| Notion linked databases | Saved filters/sorts as user-facing views |
|
|
| Metabase | Question-as-unit model and governed saved queries |
|
|
| Streamlit | Declarative layout vocabulary suitable for server rendering |
|
|
|
|
Questions to answer:
|
|
|
|
1. Which existing inter-hub dashboard fragments can become first-slice panel
|
|
renderers without broad refactoring?
|
|
2. Which panel configs must exist on day one: hub filter, time range, limit,
|
|
display mode, or sort order?
|
|
3. Which panels need live refresh, and which should stay static per request?
|
|
4. How should each saved panel map to a governed `Widget` row?
|
|
5. What should be explicitly deferred to avoid building a report builder?
|
|
|
|
Exit criteria: `docs/research/personal-dashboard-current-state.md` exists and
|
|
has enough evidence to drive the PRS.
|
|
|
|
Completion note (2026-06-16): added
|
|
`docs/research/personal-dashboard-current-state.md`, covering the current
|
|
dashboard inventory, AutoRefresh/query patterns, governed widget constraints,
|
|
first-slice panel candidates, external pattern extraction, and T02/T03
|
|
recommendations.
|
|
|
|
---
|
|
|
|
### T02 - Product Requirements Specification
|
|
|
|
```task
|
|
id: IHUB-WP-0020-T02
|
|
status: done
|
|
priority: high
|
|
depends_on: T01
|
|
state_hub_task_id: "698304bc-b91a-42e2-a617-b3ddbf749174"
|
|
```
|
|
|
|
Produce a formal PRS based on T01 and the current implementation.
|
|
|
|
Required sections:
|
|
|
|
1. Problem statement: authenticated users currently land on the Hubs list and
|
|
must manually navigate to specialized dashboards to answer daily operating
|
|
questions.
|
|
2. Personas:
|
|
- Hub operator: watches hub health, recent events, candidates, and
|
|
bottlenecks.
|
|
- Governance reviewer: triages candidates, decisions, policy coverage, and
|
|
annotations.
|
|
- AI orchestrator: watches agent proposals, review outcomes, and learning
|
|
signals.
|
|
- Platform admin: watches API usage, hub registry health, manifests, and
|
|
cross-hub propagation.
|
|
3. Core requirements using MoSCoW:
|
|
- Must: per-user saved dashboard, seeded default dashboard, panel catalogue,
|
|
server-rendered panels, persisted layout, governed panel widget identity,
|
|
post-login route design, bounded panel queries.
|
|
- Should: hub/time filters, simple edit mode, live refresh on selected
|
|
panels, keyboard-accessible forms, link-outs to existing source
|
|
dashboards.
|
|
- Could: dashboard templates, saved watched-hub sets, shared dashboards,
|
|
richer display modes.
|
|
- Won't: drag-and-drop, external datasources, client-side fetching, mobile
|
|
layout editor, complete refactor of existing dashboards.
|
|
4. Non-functional requirements:
|
|
- First paint target remains sub-second for seeded dashboards with bounded
|
|
panel queries.
|
|
- Panel queries must use limits and existing indexes or propose new indexes.
|
|
- Dashboard save/load must be simple transactional IHP controller work.
|
|
- No new JS framework.
|
|
5. Governance fit:
|
|
- Saved panel instances are governed IHF widgets or reference governed
|
|
widgets.
|
|
- Panel views use `widgetEnvelope`.
|
|
- Panel interactions emit existing event types where possible.
|
|
- Annotations attach to the panel widget identity, not to a transient DOM
|
|
block.
|
|
|
|
Exit criteria: `docs/prs/personal-dashboard-prs.md` exists and is ready for
|
|
FDD work.
|
|
|
|
Completion note (2026-06-16): added
|
|
`docs/prs/personal-dashboard-prs.md`, defining the problem statement,
|
|
personas, MoSCoW requirements, first-slice panel catalogue, governance
|
|
requirements, acceptance criteria, risks, and FDD open questions.
|
|
|
|
---
|
|
|
|
### T03 - Functional Design Document
|
|
|
|
```task
|
|
id: IHUB-WP-0020-T03
|
|
status: done
|
|
priority: high
|
|
depends_on: T02
|
|
state_hub_task_id: "438e5771-a043-4f26-a1ce-994ed478a760"
|
|
```
|
|
|
|
Translate the PRS into a concrete FDD covering schema, controller actions,
|
|
panel renderer contract, layout, seed/default behavior, and migration strategy.
|
|
|
|
The FDD must update the old greenfield schema sketch. A likely shape is:
|
|
|
|
```sql
|
|
CREATE TABLE personal_dashboards (
|
|
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
|
user_id UUID NOT NULL REFERENCES users(id),
|
|
name TEXT NOT NULL,
|
|
is_default BOOLEAN NOT NULL DEFAULT FALSE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE dashboard_panel_types (
|
|
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
|
key TEXT NOT NULL UNIQUE,
|
|
label TEXT NOT NULL,
|
|
description TEXT,
|
|
default_config JSONB NOT NULL DEFAULT '{}',
|
|
default_col_span INT NOT NULL DEFAULT 4,
|
|
default_row_span INT NOT NULL DEFAULT 1,
|
|
live_update BOOLEAN NOT NULL DEFAULT FALSE,
|
|
status TEXT NOT NULL DEFAULT 'active'
|
|
);
|
|
|
|
CREATE TABLE dashboard_panels (
|
|
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
|
|
dashboard_id UUID NOT NULL REFERENCES personal_dashboards(id) ON DELETE CASCADE,
|
|
panel_type_id UUID NOT NULL REFERENCES dashboard_panel_types(id),
|
|
widget_id UUID NOT NULL REFERENCES widgets(id),
|
|
config JSONB NOT NULL DEFAULT '{}',
|
|
col INT NOT NULL DEFAULT 0,
|
|
row INT NOT NULL DEFAULT 0,
|
|
col_span INT NOT NULL DEFAULT 4,
|
|
row_span INT NOT NULL DEFAULT 1,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
```
|
|
|
|
The FDD must also resolve:
|
|
|
|
- Naming: whether tables should use `personal_dashboards` or another prefix to
|
|
avoid confusing them with existing dashboard actions.
|
|
- Panel config: JSONB storage plus explicit Haskell ADT decoding and validation.
|
|
- Governance identity: how `dashboard_panels.widget_id` is created, versioned,
|
|
and named.
|
|
- Renderer contract:
|
|
|
|
```haskell
|
|
data DashboardPanelConfig
|
|
= WatchedHubsConfig WatchedHubsOptions
|
|
| RecentInteractionsConfig RecentInteractionsOptions
|
|
| TriageQueueConfig TriageQueueOptions
|
|
| RecentDecisionsConfig RecentDecisionsOptions
|
|
| HubHealthConfig HubHealthOptions
|
|
| LearningDigestConfig LearningDigestOptions
|
|
|
|
renderDashboardPanel
|
|
:: DashboardPanelType
|
|
-> DashboardPanel
|
|
-> DashboardPanelConfig
|
|
-> ModelContext
|
|
-> IO Html
|
|
```
|
|
|
|
- Layout: 12-column grid on desktop, single-column below the existing Tailwind
|
|
breakpoint, stable row/span constraints, no drag-and-drop in the first slice.
|
|
- Routes/actions:
|
|
- `PersonalDashboardAction`
|
|
- `EditPersonalDashboardAction`
|
|
- `UpdatePersonalDashboardAction`
|
|
- `AddDashboardPanelAction`
|
|
- `UpdateDashboardPanelAction`
|
|
- `RemoveDashboardPanelAction`
|
|
- Login behavior: `CreateSessionAction` should redirect to the personal
|
|
dashboard after authentication, while public root pages remain unchanged.
|
|
- Defaulting model: seed a default dashboard on first visit without requiring a
|
|
`users.role` column.
|
|
- Query safety: each panel query must be bounded, indexed, and compatible with
|
|
current PostgreSQL type decoding practices such as casting `COUNT(*)` to
|
|
integer when read as `Int`.
|
|
- Tests and smoke checks needed for the follow-on implementation workplan.
|
|
|
|
Exit criteria: `docs/fdd/personal-dashboard-fdd.md` exists, schema decisions
|
|
are concrete enough to implement, and open questions are explicitly listed.
|
|
|
|
Completion note (2026-06-16): added
|
|
`docs/fdd/personal-dashboard-fdd.md`, resolving schema names, panel config
|
|
typing, renderer/view-model shape, default seeding, governed panel widget
|
|
lifecycle, query constraints, routes, layout, tests, and handoff shape for
|
|
IHUB-WP-0021.
|
|
|
|
---
|
|
|
|
### T04 - Implementation workplan
|
|
|
|
```task
|
|
id: IHUB-WP-0020-T04
|
|
status: done
|
|
priority: medium
|
|
depends_on: T03
|
|
state_hub_task_id: "970aa221-7e17-4500-8b37-9c98676280b1"
|
|
```
|
|
|
|
Create the execution workplan for implementation as `IHUB-WP-0021`.
|
|
|
|
Expected task structure for `IHUB-WP-0021`:
|
|
|
|
| Task | Focus |
|
|
|---|---|
|
|
| T01 | Schema migration for personal dashboards, panel types, and panel instances |
|
|
| T02 | Seed dashboard panel types and any required framework `panel` widgets/type vocabulary |
|
|
| T03 | Add controller/action/route skeleton and default dashboard lookup/seed helper |
|
|
| T04 | Implement first three renderers: watched hubs, recent interactions, triage queue |
|
|
| T05 | Implement dashboard show view and responsive CSS grid |
|
|
| T06 | Implement remaining first-slice renderers: recent decisions, hub health, learning digest |
|
|
| T07 | Implement edit flow: reorder/update layout, add/remove panels, validate config |
|
|
| T08 | Add governed widget identity creation and `widgetEnvelope` wrapping for panels |
|
|
| T09 | Redirect successful login to the personal dashboard |
|
|
| T10 | Add `autoRefresh` only around selected live panels or the whole page if finer wrapping is not practical |
|
|
| T11 | Add focused tests for seeding, panel config validation, route access, and bounded queries |
|
|
| T12 | Manual smoke: login, seeded dashboard, edit layout, annotate a panel, verify source dashboards still load |
|
|
|
|
Each task must have entry criteria, exit criteria, rollback notes, and the
|
|
smallest reasonable test/smoke requirement. Keep implementation slices small
|
|
enough for Codex sessions to finish without broad refactors.
|
|
|
|
Exit criteria: `workplans/IHUB-WP-0021-personal-dashboard-implementation.md`
|
|
exists with all tasks in `todo` state and enough detail to start implementation.
|
|
|
|
Completion note (2026-06-16): added
|
|
`workplans/IHUB-WP-0021-personal-dashboard-implementation.md` with twelve
|
|
sequenced implementation tasks covering schema, seeds, controller skeleton,
|
|
panel renderers, show/edit views, governed panel widget lifecycle, login
|
|
redirect, AutoRefresh/query hardening, tests, and manual smoke.
|
|
|
|
## Exit Criteria Summary
|
|
|
|
| Task | Deliverable | Status |
|
|
|---|---|---|
|
|
| T01 | `docs/research/personal-dashboard-current-state.md` | done |
|
|
| T02 | `docs/prs/personal-dashboard-prs.md` | done |
|
|
| T03 | `docs/fdd/personal-dashboard-fdd.md` | done |
|
|
| T04 | `workplans/IHUB-WP-0021-personal-dashboard-implementation.md` | done |
|
|
|
|
## Binding Design Principles
|
|
|
|
- Server-first: every panel renders on the server in the normal IHP request
|
|
lifecycle.
|
|
- Integration-first: reuse current dashboard query patterns before extracting
|
|
shared abstractions.
|
|
- Governed panels: saved panel instances have stable IHF widget identity and
|
|
use `widgetEnvelope`.
|
|
- Type-safe runtime config: JSONB is storage, not the unchecked runtime API.
|
|
- Bounded queries: every panel limits rows and uses existing indexes or proposes
|
|
a specific migration.
|
|
- Minimal JS: no framework and no client-side data fetch loop.
|
|
- Tailwind only: use existing view style and responsive grid conventions.
|