generated from coulomb/repo-seed
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.
This commit is contained in:
340
docs/prs/personal-dashboard-prs.md
Normal file
340
docs/prs/personal-dashboard-prs.md
Normal file
@@ -0,0 +1,340 @@
|
||||
# Personal Dashboard Framework PRS
|
||||
|
||||
**Workplan:** IHUB-WP-0020
|
||||
**Date:** 2026-06-16
|
||||
**Status:** Product requirements for follow-on FDD and implementation planning
|
||||
**Research input:** `docs/research/personal-dashboard-current-state.md`
|
||||
|
||||
## 1. Problem Statement
|
||||
|
||||
Authenticated inter-hub users currently land on the Hubs list after login. That
|
||||
list is a useful management table, but it does not answer the daily operating
|
||||
questions users bring to inter-hub:
|
||||
|
||||
- What changed recently?
|
||||
- Which candidates or governance items need attention?
|
||||
- Which hubs are unhealthy or blocked?
|
||||
- Which learning or institutional knowledge signals should I notice today?
|
||||
- Where should I go next?
|
||||
|
||||
Inter-hub already has many specialized dashboards, but they are scattered across
|
||||
hub-level and platform-level routes. Users must know which surface to visit and
|
||||
manually stitch together recent activity, open work, health, governance, and
|
||||
learning signals.
|
||||
|
||||
The personal dashboard should become the authenticated landing surface that
|
||||
summarizes the most relevant existing signals and links users to the source
|
||||
dashboards for detail. It should be persistent, configurable, server-rendered,
|
||||
and governed by the same IHF widget, annotation, and interaction-event model as
|
||||
the rest of the application.
|
||||
|
||||
## 2. Users and Personas
|
||||
|
||||
### Hub Operator
|
||||
|
||||
Owns or watches one or more hubs. Needs quick visibility into recent events,
|
||||
open requirement candidates, hub health, active bottlenecks, and regressions.
|
||||
|
||||
Primary questions:
|
||||
|
||||
- Which hubs need attention now?
|
||||
- What happened since the last session?
|
||||
- Which candidates are still open?
|
||||
- Are any bottlenecks or health drops visible?
|
||||
|
||||
### Governance Reviewer
|
||||
|
||||
Triages candidates, reviews decisions, checks policy coverage, and follows
|
||||
traceability from observations to implementation outcomes.
|
||||
|
||||
Primary questions:
|
||||
|
||||
- Which candidates are waiting for triage?
|
||||
- Which decisions or requirements changed recently?
|
||||
- Which panels need annotation or review?
|
||||
- Are governance signals visible without visiting every hub?
|
||||
|
||||
### AI Orchestrator
|
||||
|
||||
Monitors agent proposals, review outcomes, learning signals, and institutional
|
||||
knowledge that may affect future AI-assisted work.
|
||||
|
||||
Primary questions:
|
||||
|
||||
- Which agent proposals or reviews need attention?
|
||||
- What learning insights were generated recently?
|
||||
- Which knowledge entries should inform the next work session?
|
||||
- Are there patterns of repeated friction or successful reuse?
|
||||
|
||||
### Platform Admin
|
||||
|
||||
Watches the inter-hub platform itself: API consumers, hub registry health,
|
||||
manifests, policy overlays, marketplace activity, and cross-hub propagation.
|
||||
|
||||
Primary questions:
|
||||
|
||||
- Are API consumers active and healthy?
|
||||
- Are hub manifests and registry views coherent?
|
||||
- Are cross-hub governance or propagation signals emerging?
|
||||
- Which operational panels should be promoted into a shared view later?
|
||||
|
||||
## 3. Product Goals
|
||||
|
||||
- Replace the authenticated post-login Hubs table as the daily landing surface.
|
||||
- Provide a compact, configurable overview of existing inter-hub signals.
|
||||
- Preserve the existing specialized dashboards as source-of-truth detail views.
|
||||
- Make every saved panel a governed IHF interaction artifact.
|
||||
- Keep the first implementation simple enough to deliver without a broad
|
||||
dashboard refactor.
|
||||
|
||||
## 4. Non-Goals
|
||||
|
||||
- Do not build a drag-and-drop report builder.
|
||||
- Do not add external datasource connectors.
|
||||
- Do not introduce a client-side data fetching framework.
|
||||
- Do not refactor all existing dashboards into reusable panel modules in the
|
||||
first slice.
|
||||
- Do not add a full role/permission system.
|
||||
- Do not make shared/team dashboards part of the first implementation.
|
||||
- Do not change public root, tutorial, capabilities, or extension-guide routes.
|
||||
|
||||
## 5. Core Requirements
|
||||
|
||||
### Must
|
||||
|
||||
- Provide an authenticated personal dashboard route.
|
||||
- Redirect successful login to the personal dashboard instead of `HubsAction`.
|
||||
- Preserve public root behavior for unauthenticated and documentation users.
|
||||
- Persist at least one dashboard per user.
|
||||
- Seed a default dashboard on first visit.
|
||||
- Persist panel instances, layout position, and panel config.
|
||||
- Render all first-slice panels server-side through IHP/HSX.
|
||||
- Use a server-side panel catalogue with stable panel keys.
|
||||
- Bound every panel query by limit and, where relevant, hub/status/time filters.
|
||||
- Decode JSONB panel config into explicit Haskell config types before querying.
|
||||
- Create or reference stable `Widget` records for saved panel instances.
|
||||
- Wrap rendered panels with `widgetEnvelope`.
|
||||
- Preserve annotation and interaction-event identity across sessions.
|
||||
- Link each panel to its existing source dashboard or source entity list.
|
||||
- Provide a simple edit mode for adding, removing, and reordering panels through
|
||||
normal IHP forms.
|
||||
|
||||
### Should
|
||||
|
||||
- Support hub filters for panels backed by hub-owned data.
|
||||
- Support simple time-range filters where the underlying table has timestamps.
|
||||
- Support limit/display-mode settings for panels with list content.
|
||||
- Refresh recent activity, triage, health, and learning panels using the
|
||||
existing `autoRefresh` style.
|
||||
- Keep forms keyboard accessible and understandable without custom JavaScript.
|
||||
- Render a neutral empty state when a panel has no data.
|
||||
- Provide safe fallback behavior for invalid panel config.
|
||||
- Keep first paint sub-second for a seeded dashboard with default panels.
|
||||
- Use existing Tailwind/card/table visual conventions.
|
||||
|
||||
### Could
|
||||
|
||||
- Add saved watched-hub sets.
|
||||
- Add multiple named dashboards per user.
|
||||
- Add dashboard templates.
|
||||
- Add shared/team dashboards.
|
||||
- Add more panel types after the first framework slice is proven.
|
||||
- Add finer-grained panel refresh routes later.
|
||||
- Add user-selected default landing dashboard later.
|
||||
|
||||
### Won't for First Implementation
|
||||
|
||||
- Drag-and-drop layout editing.
|
||||
- Mobile-native layout editor.
|
||||
- Client-side data fetching.
|
||||
- External dashboard or BI embedding.
|
||||
- External datasource credentials.
|
||||
- Role-based access control beyond existing authenticated controller guards.
|
||||
- Complex visual charting library integration.
|
||||
|
||||
## 6. First-Slice Panel Catalogue
|
||||
|
||||
The first implementation should prove the framework with a small panel set.
|
||||
|
||||
| Panel key | Label | Purpose | Default behavior |
|
||||
|---|---|---|---|
|
||||
| `watched-hubs` | Watched Hubs | Show hub list plus latest health hint | All hubs, limit 12 |
|
||||
| `recent-interactions` | Recent Activity | Show latest interaction events with hub/widget context | Last 24h, limit 25 |
|
||||
| `triage-queue` | Triage Queue | Show open requirement candidates | Open status, oldest first, limit 10 |
|
||||
| `recent-decisions` | Recent Decisions | Show recent governance decisions | Last 30 days, newest first, limit 10 |
|
||||
| `hub-health` | Hub Health | Show latest health snapshot and active blockers | Latest per hub, limit 12 |
|
||||
| `learning-digest` | Learning Digest | Show latest insights and knowledge highlights | Latest insights and entries, limit 5 each |
|
||||
|
||||
Deferred panel catalogue candidates:
|
||||
|
||||
- `agent-proposals`
|
||||
- `api-usage`
|
||||
- `marketplace-trending`
|
||||
- `my-annotations`
|
||||
- `policy-compliance`
|
||||
- `adapter-compatibility`
|
||||
- `cross-hub-propagations`
|
||||
|
||||
## 7. Functional Requirements
|
||||
|
||||
### Dashboard Route
|
||||
|
||||
- Add a `PersonalDashboardsController` or similarly named controller.
|
||||
- Add a show action for the current user's default dashboard.
|
||||
- Add edit/update/add/remove actions for panel management.
|
||||
- Register routes in `Web.Routes` and `Web.FrontController`.
|
||||
- Add a sidebar link labelled `Dashboard`.
|
||||
|
||||
### Dashboard Persistence
|
||||
|
||||
- Store dashboard ownership by `users.id`.
|
||||
- Support at least one default dashboard per user.
|
||||
- Store panel order and grid layout.
|
||||
- Store panel config in JSONB.
|
||||
- Store a linked panel widget id for governance.
|
||||
- Keep panel deletion non-destructive with respect to historical events and
|
||||
annotations.
|
||||
|
||||
### Default Seeding
|
||||
|
||||
- On first visit, create a default dashboard for the authenticated user.
|
||||
- Seed the first-slice panels with safe default config.
|
||||
- Do not require a `users.role` column.
|
||||
- Best-effort hub relevance may use active `stewardship_roles.assigned_to`
|
||||
matching user email or name, but the neutral default must work without it.
|
||||
|
||||
### Panel Rendering
|
||||
|
||||
- Dispatch panels by stable catalogue key.
|
||||
- Decode and validate config before querying.
|
||||
- Use bounded queries.
|
||||
- Render empty states and config warnings without crashing the whole dashboard.
|
||||
- Wrap every rendered panel in `widgetEnvelope`.
|
||||
- Link to source dashboards for deeper work.
|
||||
|
||||
### Edit Mode
|
||||
|
||||
- List current panels in layout order.
|
||||
- Allow adding a panel from active panel types.
|
||||
- Allow removing a panel from the dashboard.
|
||||
- Allow editing column, row, span, limit, hub filter, time range, and display
|
||||
mode where supported.
|
||||
- Validate layout spans and config values server-side.
|
||||
- Keep forms usable without custom JavaScript.
|
||||
|
||||
### Governance and Event Capture
|
||||
|
||||
- Saved panels must use stable `Widget` rows.
|
||||
- Panel widgets should use the existing `panel` widget type.
|
||||
- Panel widget `view_context` must be non-empty.
|
||||
- Panel annotations must attach to the panel widget id.
|
||||
- Panel interaction capture should use existing event types where possible.
|
||||
- Adding/removing/reconfiguring panels should not mutate historical
|
||||
interaction events.
|
||||
|
||||
## 8. Non-Functional Requirements
|
||||
|
||||
### Performance
|
||||
|
||||
- Default dashboard first paint target: under 1 second in local development
|
||||
with seeded fixtures.
|
||||
- Each panel query should have a default row limit.
|
||||
- Any aggregate query decoded as `Int` must cast `COUNT(*)` to integer or
|
||||
decode as `Int64`.
|
||||
- Avoid N+1 patterns where a simple join or batched fetch is practical.
|
||||
- Use existing indexes where available; document new index needs in the FDD.
|
||||
|
||||
### Reliability
|
||||
|
||||
- Invalid panel config should not break the whole dashboard.
|
||||
- Missing source data should render an empty state.
|
||||
- Missing linked widget should be repaired or reported by the controller before
|
||||
rendering.
|
||||
- Dashboard seeding should be idempotent.
|
||||
- Login redirect should fall back gracefully if dashboard seeding fails.
|
||||
|
||||
### Security and Privacy
|
||||
|
||||
- Dashboard routes require authenticated users.
|
||||
- Users can view and edit only their own personal dashboard in the first slice.
|
||||
- No secrets, API keys, or token values may be shown in dashboard panels.
|
||||
- API usage panels must show only non-secret consumer metadata.
|
||||
- Panel config must not become an arbitrary SQL or route execution surface.
|
||||
|
||||
### Accessibility and Usability
|
||||
|
||||
- Use semantic headings for panels.
|
||||
- Use tables/lists for scan-heavy operational data.
|
||||
- Use form labels for all edit inputs.
|
||||
- Keep navigation links clear and predictable.
|
||||
- Do not rely on hover-only controls for essential edits.
|
||||
|
||||
### Maintainability
|
||||
|
||||
- Put renderer dispatch and config decoding in a focused helper/module.
|
||||
- Keep panel renderer functions small and testable.
|
||||
- Avoid moving existing dashboard code unless required.
|
||||
- Prefer additive schema migrations.
|
||||
- Keep first implementation tasks small enough for separate Codex sessions.
|
||||
|
||||
## 9. Acceptance Criteria
|
||||
|
||||
The product design is acceptable when the FDD can specify:
|
||||
|
||||
- Exact schema tables and fields.
|
||||
- Exact controller/action names.
|
||||
- Exact default panel seed set.
|
||||
- Exact panel config types and defaults.
|
||||
- Exact first-slice panel query shapes.
|
||||
- Exact governance identity lifecycle for panel widgets.
|
||||
- Exact smoke tests for login, dashboard seeding, editing, annotation, and
|
||||
source dashboard link-outs.
|
||||
|
||||
The implementation will be acceptable when:
|
||||
|
||||
- A new authenticated user lands on a seeded personal dashboard after login.
|
||||
- The seeded dashboard renders all first-slice panels.
|
||||
- The user can add, remove, and adjust panels through server-rendered forms.
|
||||
- Panel layout persists across sessions.
|
||||
- Each panel is wrapped in `widgetEnvelope`.
|
||||
- Annotating a panel opens the existing widget annotation flow.
|
||||
- Existing Hubs and specialized dashboard routes still load.
|
||||
- Focused tests or smoke checks cover seeding, config validation, route access,
|
||||
and bounded query behavior.
|
||||
|
||||
## 10. Risks and Mitigations
|
||||
|
||||
| Risk | Mitigation |
|
||||
|---|---|
|
||||
| Scope grows into report builder | Limit first slice to six panel types and server-rendered forms |
|
||||
| Existing dashboards are hard-coded | Extract only needed query/render fragments into new panel renderers |
|
||||
| Panel config becomes unsafe JSON | Decode into Haskell ADTs and validate before querying |
|
||||
| Role-aware defaults require missing schema | Use neutral default first; only best-effort stewardship hints |
|
||||
| AutoRefresh refreshes too much | Bound all queries; defer per-panel refresh unless needed |
|
||||
| Panel annotations lack stable identity | Require `dashboard_panels.widget_id` and `widgetEnvelope` |
|
||||
| COUNT decode errors recur | Cast aggregate counts or decode as `Int64` in implementation |
|
||||
|
||||
## 11. Open Questions for FDD
|
||||
|
||||
1. Should table names use `personal_dashboards`/`dashboard_panels`, or a more
|
||||
explicit `user_dashboards` prefix?
|
||||
2. Should removed panels archive their linked widgets or mark them deprecated?
|
||||
3. Should panel widgets be owned by the framework hub, or by the source hub when
|
||||
a panel is hub-specific?
|
||||
4. Should the first implementation allow multiple dashboards per user, or only
|
||||
one default dashboard with schema ready for multiples?
|
||||
5. Should `autoRefresh` wrap the whole dashboard action initially, or should
|
||||
live panel fragments get their own actions?
|
||||
6. Should watched hubs be a separate table in the first slice, or represented
|
||||
as dashboard panel config only?
|
||||
|
||||
## 12. Recommendation
|
||||
|
||||
Proceed to FDD with a small, governed, server-rendered personal dashboard:
|
||||
|
||||
- One default dashboard per user, schema ready for multiples.
|
||||
- Six first-slice panel types.
|
||||
- `dashboard_panels.widget_id` as the governance anchor.
|
||||
- Existing `panel` widget type for saved panel widgets.
|
||||
- Whole-page `autoRefresh` initially, with bounded queries.
|
||||
- Simple edit forms and no custom client runtime.
|
||||
Reference in New Issue
Block a user