Skip to content

feat(dashboard): dashboard from the October 2026 redesign (#901) - #926

Merged
alex-dembele merged 5 commits into
masterfrom
feat/901-dashboard
Oct 9, 2026
Merged

alex-dembele merged 5 commits into
masterfrom
feat/901-dashboard

Conversation

@alex-dembele

Copy link
Copy Markdown
Member

Second screen of the redesign epic (#899). Stacked on #925 (the shell): the base is feat/900-console-shell, so this diff shows only the dashboard. Retarget to master once #925 is merged.

What the page does

One layout for every member, as drawn: the open critical or high incident with its running time and a link into its war room, the exposure score with its four factors and 30-day movement, the annualised exposure split by band with the residual and the simulated P95, four counters, the score over twelve months next to the 5x5 matrix, then the top priorities and the recent activity.

The business role picks which four counters and which priorities show, which is how the design's RSSI / risk manager / auditor / executive views map onto real accounts. There is no switch on screen (owner decision).

Backend added for it

  • GET /score/history?months=12 and tenant_score_snapshots (migration 0069): the tenant score had no stored past, so there was nothing to draw a year with. One snapshot per tenant per day, written by the endpoint and by a six-hourly sweep. Declared in the authz and isolation registries, with cross-tenant tests at the repository and use-case level.
  • /stats gains live_risks, critical_live, without_mitigation, reviews_due_30d. Existing fields are unchanged; a test covers the closed / cancelled-plan / foreign-tenant-plan cases.
  • The Monte Carlo reports P95 next to P10/P50/P90. Same samples, one more percentile.

Choices worth a look

  • The score keeps its exposure direction (owner decision, recorded as D-067). The card is labelled "Score d'exposition", a drop shows green, and the factor bars are pressures coloured from /score/model's own bands.
  • The period control is gone. Nothing on the redesigned page is period-scoped, so it would have filtered nothing.
  • The five persona dashboards, the action-center panel and the score-card tilt (D-063) are removed. The panel's link safety (no unresolved or off-origin row) now guards the priority list, and its tests were ported.
  • The executive view's 4th counter, risk appetite, shows "—" with a pointer to the financial page until feat(frontend): financial quantification on the redesign layout #904 makes appetite a tenant setting.

Verified

  • go test ./...: all packages pass, including the authz and isolation route ratchets.
  • npx tsc -b --noEmit clean, npx vitest run 110 files / 1000 tests passed, lint ceiling lowered to 96.
  • Live against a Postgres seeded with the design's dataset (12 assets, 14 risks, 10 CVEs, 5 incidents, 4 frameworks): side by side with the mockup at 1440 in dark and light, /score/history read back from Postgres, column types identical between the SQL migration and AutoMigrate, 414 px without horizontal overflow, axe on main with 0 serious or critical issues in both themes.

Not done here

  • The action center returns nothing on a tenant where nothing is assigned to the caller, so the priority list is empty on the seeded tenant. Widening its sources (vulnerability SLAs, vendors, unassessed controls) is feat(frontend): action center on the redesign layout #902.
  • The recent-activity lines are the feed's raw wording ("create incident …"). Turning them into sentences is the Activity page's work (feat(frontend): activity feed on the redesign layout #905), and this block picks it up automatically.
  • The four views were checked with unit tests, not live: the throwaway environment has no account per business role.

Closes #901

The redesigned dashboard quotes a worst plausible year (P95) beside the
annualised exposure. The Monte Carlo already sorts its samples, so P95 is
one more percentile read off them, added to the risk and portfolio
distributions and to their currency-aware presentation. No input,
sampling or seed changes.

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
The tenant score is computed live and nothing kept its past values, so the
redesigned dashboard had no way to draw its 12-month line or say how far
the score moved in 30 days.

- tenant_score_snapshots (migration 0069): one row per tenant per UTC day,
  a later computation on the same day replaces it. Unmeasured days store
  nothing and show as gaps, never as zero.
- GET /score/history?months=12: the month-by-month closing value, today's
  value and the 30-day delta (null until a snapshot is 30 days old). It
  records today first, so the line always ends on the live figure.
- A sweep records every tenant every six hours, so a quiet tenant's line
  stays continuous.

The formula is untouched; this stores what /score already returns.
Session-sufficient like /score, declared in the authz and isolation
registries with its cross-tenant tests.

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
The redesigned dashboard counts the risks still alive, which the stock
counters cannot answer because they include closed risks so they
reconcile with the full register. /stats gains four fields, the existing
ones are unchanged:

- live_risks: not closed
- critical_live: critical band, still open or in treatment
- without_mitigation: live risks with no plan other than cancelled ones,
  matched on the risk's own tenant
- reviews_due_30d: next review within 30 days, overdue included

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
…901)

One layout for every member: the open critical or high incident with its
running time and the way into its war room, the exposure score with its
four factors and 30-day movement, the annualised exposure split by band
with the residual and the simulated P95, four counters, the score over
twelve months beside the 5x5 matrix, then the top priorities and the
recent activity.

The business role picks which four counters and which priorities show
(RSSI, risk manager, auditor, executive), as the design's four views do;
there is no switch on screen, per the owner. Each block fetches its own
tenant-scoped source and renders its own loading, error and empty state.

The score keeps its exposure direction (owner decision): it is labelled
"Score d'exposition", a falling value shows green, factor bars are
pressures coloured from the served band table, no threshold in the
client. The matrix tint is a grid legend; the binning is the server's
CEIL(p x 5), CEIL(i / 2).

The period control is gone: no block of the redesigned page is
period-scoped, so it would filter nothing. The five persona dashboards,
the action-center panel and their helpers are removed; the panel's link
safety (no unresolved or off-origin row) now guards the priority list,
with its tests ported. The register opens on its matrix with ?view=matrix,
which the dashboard links to.

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
)

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(frontend): dashboard on the redesign layout

1 participant