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.
624 lines
16 KiB
Markdown
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.
|