Files
inter-hub/workplans/IHUB-WP-0021-personal-dashboard-implementation.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

624 lines
16 KiB
Markdown

---
id: IHUB-WP-0021
type: workplan
title: "Personal Dashboard Implementation"
domain: inter_hub
repo: inter-hub
status: ready
owner: codex
topic_slug: inter_hub
created: "2026-06-16"
updated: "2026-06-16"
phase: 13
depends_on: IHUB-WP-0020
related_docs:
- docs/research/personal-dashboard-current-state.md
- docs/prs/personal-dashboard-prs.md
- docs/fdd/personal-dashboard-fdd.md
state_hub_workstream_id: "79f72176-fb3f-4d59-9678-d42f5ff1e679"
---
# Personal Dashboard Implementation
## Goal
Implement the personal dashboard framework designed in IHUB-WP-0020: a
server-rendered authenticated landing page with persisted per-user panels,
governed panel widget identity, default dashboard seeding, simple edit forms,
and six first-slice panel renderers.
## Inputs
- `docs/research/personal-dashboard-current-state.md`
- `docs/prs/personal-dashboard-prs.md`
- `docs/fdd/personal-dashboard-fdd.md`
- Existing dashboard surfaces in `Web/Controller/Hubs.hs`,
`Web/Controller/LearningDashboard.hs`, `Web/Controller/ApiDashboard.hs`,
`Web/Controller/MarketplaceDashboard.hs`, and federated governance
controllers.
## Constraints
- Keep implementation additive.
- Preserve public root/static routes.
- Do not refactor all existing dashboards.
- No client-side data fetching framework.
- No drag-and-drop layout in this workplan.
- Every saved dashboard panel must have stable `Widget` identity and render
through `widgetEnvelope`.
- Bound every panel query.
- Cast aggregate `COUNT(*)` queries when decoding as `Int`, or decode as
`Int64`.
## Tasks
### T01 - Add personal dashboard schema
```task
id: IHUB-WP-0021-T01
status: todo
priority: high
state_hub_task_id: "bb7366a3-78ec-42d8-9f16-b7ed4979ec53"
```
Add the schema from the FDD:
- `personal_dashboards`
- `dashboard_panel_types`
- `dashboard_panels`
Implementation notes:
- Add an `Application/Migration/<timestamp>-personal-dashboard-framework.sql`
migration.
- Update `Application/Schema.sql` consistently with the migration.
- Use `panel_key`, not `key`, on `dashboard_panel_types`.
- Include `removed_at` on `dashboard_panels`.
- Include indexes and layout CHECK constraints from the FDD.
Entry criteria:
- IHUB-WP-0020 is done.
- FDD exists and is reviewed enough for implementation.
Exit criteria:
- Schema files contain the three new tables and indexes.
- `rg "personal_dashboards|dashboard_panel_types|dashboard_panels" Application`
finds the expected migration/schema entries.
- No existing table or route behavior is changed.
Verification:
- Run `git diff --check`.
- If the IHP dev environment is available, run the repo compile/schema check
used by prior inter-hub workplans.
Rollback notes:
- Before production data exists, rollback is removing the migration/schema
additions.
- After production data exists, rollback requires preserving linked `widgets`
and `interaction_events`; do not delete panel widgets casually.
---
### T02 - Seed panel types and framework panel vocabulary
```task
id: IHUB-WP-0021-T02
status: todo
priority: high
depends_on: T01
state_hub_task_id: "d298eab2-736d-48ed-b6d4-84afa1604de9"
```
Add idempotent seed data for:
- framework hub with slug `inter-hub` and `hub_kind = 'framework'` if absent;
- active widget type `panel` if absent;
- six first-slice `dashboard_panel_types`:
- `watched-hubs`
- `recent-interactions`
- `triage-queue`
- `recent-decisions`
- `hub-health`
- `learning-digest`
Entry criteria:
- T01 schema exists.
Exit criteria:
- Seed SQL or helper is idempotent.
- Re-running seeds does not create duplicate framework hubs, widget types, or
panel types.
- Default configs match the FDD.
Verification:
- Inspect seed SQL for `ON CONFLICT DO NOTHING` or equivalent idempotency.
- If DB is available, run a local seed twice and confirm row counts stay stable.
Rollback notes:
- Panel type seed rows are additive. If rollback is needed before use, remove
only the new dashboard panel type rows and any framework hub created solely
for this feature.
---
### T03 - Add controller skeleton, routes, and default dashboard helper
```task
id: IHUB-WP-0021-T03
status: todo
priority: high
depends_on: T02
state_hub_task_id: "8a171c71-3762-46c7-88d7-10ffb87fc78a"
```
Add:
- `PersonalDashboardsController` to `Web/Types.hs`;
- `Web/Controller/PersonalDashboards.hs`;
- `Web/View/PersonalDashboards/Show.hs`;
- `Web/View/PersonalDashboards/Edit.hs` placeholder or minimal views;
- route registration in `Web/Routes.hs`;
- controller import and parser registration in `Web/FrontController.hs`;
- helper module `Application/Helper/PersonalDashboard.hs`.
Implement:
- `ensureDefaultDashboard :: User -> IO PersonalDashboard`;
- dashboard lookup scoped to current user;
- idempotent default seeding with six panel rows;
- linked `Widget` creation for each seeded panel;
- initial `WidgetVersion` creation for panel widgets.
Entry criteria:
- T01/T02 complete.
Exit criteria:
- Authenticated user can hit `PersonalDashboardAction`.
- First visit creates a default dashboard with six active panels.
- A second visit does not duplicate panels.
- Controller denies unauthenticated access through `ensureIsUser`.
Verification:
- Compile if environment is available.
- Add or run focused helper tests if existing test harness supports it.
Rollback notes:
- Remove route/controller/helper additions if skeleton must be reverted.
- Keep seeded widgets/events if any user interactions already happened.
---
### T04 - Implement first three panel view models/renderers
```task
id: IHUB-WP-0021-T04
status: todo
priority: high
depends_on: T03
state_hub_task_id: "012dcd2a-d3e0-48ba-966b-f4c7afa51dad"
```
Implement typed config decoding and view-model builders for:
- `watched-hubs`
- `recent-interactions`
- `triage-queue`
Requirements:
- Query from controller/helper, not from HSX views.
- Clamp configured limits.
- Apply optional hub filters.
- Render empty states.
- Include source links:
- watched hub rows link to `ShowHubAction`;
- recent interaction rows link to widget or hub context where available;
- triage rows link to `ShowRequirementCandidateAction`.
Entry criteria:
- T03 controller/helper skeleton exists.
Exit criteria:
- The three panels render in the dashboard show action.
- Invalid config falls back to defaults and records a warning in the panel view
model.
- Queries are bounded.
Verification:
- Compile if environment is available.
- Manual smoke with empty DB and seeded fixture data if possible.
Rollback notes:
- Renderer additions are isolated to helper/view modules and can be reverted
without dropping schema.
---
### T05 - Implement dashboard show view and responsive grid
```task
id: IHUB-WP-0021-T05
status: todo
priority: high
depends_on: T04
state_hub_task_id: "b4c4de39-147b-45a0-954d-9bafad4aafa1"
```
Build the dashboard show view:
- title and edit link;
- responsive grid;
- panel cards using row/col/span config;
- panel title fallback to panel type label;
- warning display for invalid config or unsupported panel;
- source link area;
- `widgetEnvelope` around every panel.
Implementation notes:
- Use current Tailwind and HSX conventions.
- Add a small CSS helper in `static/app.css` only if needed for responsive
collapse.
- Keep text compact and operational.
Entry criteria:
- At least three panel view models exist.
Exit criteria:
- Seeded dashboard is usable as an authenticated landing surface.
- Panels do not overlap at desktop or narrow widths.
- Panel layout persists in the order defined by `row`, `col`, and `sort_order`.
Verification:
- Compile if environment is available.
- Browser/manual smoke if a dev server is running.
Rollback notes:
- Show view changes can be reverted independently of schema/controller work.
---
### T06 - Implement remaining first-slice panel view models/renderers
```task
id: IHUB-WP-0021-T06
status: todo
priority: high
depends_on: T05
state_hub_task_id: "8d0bd046-17b3-48d9-a945-8b2e9c001123"
```
Implement:
- `recent-decisions`
- `hub-health`
- `learning-digest`
Requirements:
- Recent decisions: bounded by time range and limit; link to
`ShowDecisionRecordAction`.
- Hub health: latest snapshot per hub plus active bottleneck count; use
aggregate count casting or `Int64`.
- Learning digest: recent `learning_insights` and
`institutional_knowledge_entries`; link to knowledge entries where possible.
Entry criteria:
- T05 show view can render panel view models.
Exit criteria:
- All six first-slice panels render.
- All panel queries are bounded.
- Empty states are sane for all six panels.
Verification:
- Compile if environment is available.
- `git diff --check`.
Rollback notes:
- Each renderer should be separable so a single broken panel can be reverted
without removing the framework.
---
### T07 - Implement edit flow
```task
id: IHUB-WP-0021-T07
status: todo
priority: high
depends_on: T06
state_hub_task_id: "51a72b56-5c23-4baa-892f-4ab89fd8495c"
```
Implement:
- `EditPersonalDashboardAction`;
- `UpdatePersonalDashboardAction`;
- `AddDashboardPanelAction`;
- `UpdateDashboardPanelAction`;
- `RemoveDashboardPanelAction`.
Edit view capabilities:
- show existing panels in layout order;
- edit row, col, col span, row span, title, and sort order;
- edit supported config fields such as limit, time range, display mode, and
hub filter;
- add active panel type;
- remove panel.
Entry criteria:
- All six panels render on show view.
Exit criteria:
- User can modify layout and config through server-rendered forms.
- User can add a panel and remove a panel.
- Invalid layout/config re-renders edit view with an error.
- A user cannot edit another user's dashboard/panel.
Verification:
- Manual edit smoke.
- Focused authorization/config tests if available.
Rollback notes:
- If edit flow is unstable, keep show-only dashboard and disable edit links
until fixed.
---
### T08 - Complete governed panel widget lifecycle
```task
id: IHUB-WP-0021-T08
status: todo
priority: high
depends_on: T07
state_hub_task_id: "ca70b76d-766f-4e6e-84f1-19943c0a347c"
```
Harden widget lifecycle behavior:
- create panel widget on panel add/seed;
- create initial `WidgetVersion` snapshot;
- create a new `WidgetVersion` snapshot when material panel config changes;
- render every panel through `widgetEnvelope`;
- preserve annotations/events when panels are removed;
- archive/deprecate linked widget on panel removal.
Entry criteria:
- Edit flow can add/remove/update panels.
Exit criteria:
- Every active dashboard panel has a linked active `Widget`.
- Every linked widget has non-empty `view_context`.
- Annotate link opens the existing widget annotation flow.
- Removing a panel does not delete widget history.
Verification:
- Manual smoke: add panel, annotate panel, remove panel, confirm widget/event
history is not deleted.
- Inspect generated HTML for expected `data-widget-*` attributes.
Rollback notes:
- Do not delete existing `widgets`, `annotations`, or `interaction_events`.
Disable dashboard rendering if needed while preserving history.
---
### T09 - Redirect login and add navigation
```task
id: IHUB-WP-0021-T09
status: todo
priority: medium
depends_on: T08
state_hub_task_id: "2fd1041b-9135-49e4-a9d1-e5d0b67d8fd7"
```
Update:
- `Web/Controller/Sessions.hs` to redirect successful login to
`PersonalDashboardAction`;
- `Web/FrontController.hs` sidebar to include `Dashboard`;
- any relevant public page management links only if they should point to the
dashboard rather than Hubs.
Do not change:
- public root route;
- `LandingAction`;
- capabilities/tutorial/extension guide pages;
- `HubsAction` availability.
Entry criteria:
- Dashboard show route is stable and governed panel lifecycle is complete.
Exit criteria:
- Successful login lands on personal dashboard.
- Hubs remain reachable from sidebar.
- Public pages still render without login.
Verification:
- Manual login smoke.
- Route smoke for `/`, Hubs, dashboard, Learning, API Dashboard, Marketplace.
Rollback notes:
- If dashboard redirect fails, revert only the login redirect and keep
dashboard accessible from sidebar.
---
### T10 - Add AutoRefresh and query hardening pass
```task
id: IHUB-WP-0021-T10
status: todo
priority: medium
depends_on: T09
state_hub_task_id: "e19c06e7-ec95-40ca-8087-df669b575f86"
```
Wrap `PersonalDashboardAction` in `autoRefresh do` and audit all six panel
queries:
- every query is bounded;
- optional hub filter is applied before broad fetches where practical;
- aggregate counts decode safely;
- no secrets are selected or displayed;
- dashboard refresh remains acceptable with default seed data.
Entry criteria:
- Dashboard route, renderers, edit flow, and login redirect exist.
Exit criteria:
- Dashboard updates using existing IHP AutoRefresh behavior.
- Query review notes are either captured in code comments or tests where useful.
- No known `COUNT(*)` as `Int` decode hazard remains in dashboard code.
Verification:
- Compile if environment is available.
- Manual refresh smoke by adding an interaction/candidate and observing the
dashboard update, when a dev DB is available.
Rollback notes:
- Remove `autoRefresh` wrapper if it causes unacceptable behavior; keep static
dashboard route.
---
### T11 - Add focused tests
```task
id: IHUB-WP-0021-T11
status: todo
priority: medium
depends_on: T10
state_hub_task_id: "32b4f55e-ede6-4830-a171-b0785afe88e1"
```
Add focused tests where the current harness supports them:
- default dashboard seeding is idempotent;
- seeded dashboard has six active panels;
- each active panel has linked widget identity;
- config decoder clamps limits and rejects unknown values safely;
- remove action soft-removes panel and archives widget;
- users cannot edit another user's dashboard;
- aggregate counts in dashboard helpers decode safely.
Entry criteria:
- T10 implementation is stable enough to test.
Exit criteria:
- Relevant test files exist or a documented reason explains why the current
harness cannot cover a case.
- Tests pass where runnable in the local environment.
Verification:
- Run available test command.
- If unavailable, record exact blocker in this workplan before closing T11.
Rollback notes:
- Do not weaken production behavior to satisfy a brittle test; adjust the test
to match the intended FDD contract.
---
### T12 - Manual smoke and closeout
```task
id: IHUB-WP-0021-T12
status: todo
priority: high
depends_on: T11
state_hub_task_id: "8c6648ae-d33e-48f6-9d56-ee557f367d80"
```
Run a manual smoke pass:
1. Log in as an existing admin user.
2. Confirm redirect lands on personal dashboard.
3. Confirm all six seeded panels render.
4. Click source links from watched hubs, triage queue, and learning digest.
5. Open Annotate for one panel.
6. Edit layout and save.
7. Sign out/in and confirm layout persists.
8. Add and remove a panel.
9. Confirm Hubs, Hub show, Ops Review, Federation, Learning, API Dashboard,
Hub Registry, and Marketplace still load.
10. Run `git diff --check`.
Entry criteria:
- T01 through T11 complete or have explicit accepted caveats.
Exit criteria:
- Smoke evidence is recorded in this workplan or a short docs/evidence note.
- WP-0021 tasks reflect final status.
- State Hub progress note is logged.
- Operator is reminded to run `make fix-consistency REPO=inter-hub` from
`~/state-hub` after workplan/status changes.
Rollback notes:
- If smoke fails after login redirect, first rollback is reverting the login
redirect while keeping dashboard route available for debugging.
## Workplan Exit Criteria
- Personal dashboard schema, seeds, controller, views, helper, and route are
implemented.
- Successful login reaches the personal dashboard.
- Default dashboard seeding is idempotent.
- Six first-slice panels render with bounded queries.
- Panel edit flow works.
- Every panel has governed widget identity.
- Existing source dashboards remain functional.
- Checks/smoke evidence is recorded.