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.
341 lines
14 KiB
Markdown
341 lines
14 KiB
Markdown
# 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.
|