Files
inter-hub/workplans/IHUB-WP-0020-personal-dashboard-framework.md
tegwick d6b655a5cf docs: complete personal dashboard framework and implementation plan
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.
2026-06-21 16:11:37 +02:00

17 KiB

id, type, title, domain, repo, status, owner, topic_slug, created, updated, phase, state_hub_workstream_id
id type title domain repo status owner topic_slug created updated phase state_hub_workstream_id
IHUB-WP-0020 workplan Personal Dashboard Framework inter_hub inter-hub finished tegwick inter_hub 2026-05-03 2026-06-16 13 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

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

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

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:

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:
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

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.