Skip to content

feat(executive): executive view on the redesign layout (#903) - #928

Merged
alex-dembele merged 4 commits into
masterfrom
feat/903-executive
Oct 9, 2026
Merged

alex-dembele merged 4 commits into
masterfrom
feat/903-executive

Conversation

@alex-dembele

Copy link
Copy Markdown
Member

Fourth screen of the redesign epic (#899). Stacked on #927 (action center): the base is feat/902-action-center, so the diff shows only this issue.

What changes for the user

The executive view is now the one-page committee summary from the mockup: "Comité des risques · T4 2026", Copier le lien and Exporter le rapport, four headline figures with their movement since last quarter, the five largest exposures (inherent and targeted residual bars), compliance by framework with the counting footnote, and the decisions the committee owes, each with Reporter and Approuver.

Backend

  • POST /governance/approvals/:id/defer (migration 0071): a dated "deferred to the next committee" note; the request stays pending at the same step. Only someone eligible to sign the open step may defer, so it is never a way round maker-checker. Audit event defer.
  • The daily score snapshot also keeps ALE, live critical risks and average compliance (migration 0072). /score/history returns quarter_baseline, the last snapshot before the current quarter, or null.
  • The financial summary's top risks carry ale_after.
  • Fix found in the live pass: UpdateRequest wrote a fixed column list without deferrals. The API answered 200, the audit said one deferral, the row stayed empty. Repository test added.

Frontend

  • features/analytics/ExecutiveDashboard.tsx rewritten; the old executiveService / useExecutive are removed (nothing else imported them).
  • With no snapshot before the quarter, a tile says "pas encore de relevé au trimestre précédent" rather than printing a movement nobody measured.
  • Approve and Defer are optimistic, roll back on refusal, and do not retry. The app-wide mutation policy (retry: 3) sent a refused signature four times.
  • A request's own description is its sub-line when present, else type and requester.

Verified

  • go test ./...: all packages pass, including the new TestUpdateRequest_PersistsDeferrals (failed before the fix).
  • npx tsc -b --noEmit clean, eslint clean on the touched files, npx vitest run 112 files / 1013 tests (two clean runs; one earlier run right after go test had 23 timeouts across 8 unrelated files and did not reproduce).
  • New committeeDecisions.test.tsx: optimistic defer, rollback, a refused signature sent once (fails if retry: false is removed), approved state.
  • Live on Postgres with the parity dataset at 1440×900, dark and light, side by side with the design: Reporter persisted and survived a reload ("Reportée le 9 oct.", moved last); Approuver on someone else's request → approved; on one's own → "Vous ne pouvez pas signer cette étape.", one request sent; Copier le lien wrote the page URL; Exporter le rapport generated the board report and opened /reports/board.

Deliberate differences from the mockup

  • Risk ids read #84cb6560, not R-0142: risks have no human reference yet, and the register shows the same form.
  • The compliance footnote says "Contrôles mis en œuvre sur contrôles applicables · hors non applicables". The mockup's "partiel compté pour moitié" is not how coverage is computed, so the page does not claim it.
  • Exposure keeps its direction (D-067): lower is better, so "−4 pts" is green.

Not done here

  • 414 px could not be checked: the headed browser will not go below 517 px. At 517 there is no horizontal scroll (the dashboard behaves the same).
  • GET /analytics/executive remains on the backend with no frontend caller left. Removing it is a separate cleanup.

Closes #903

The redesigned executive view offers "Reporter" next to "Approuver" on
each decision the committee owes. The approval engine only knows approve
and reject, and the owner chose a dated note rather than a new engine
state: POST /governance/approvals/:id/defer appends who deferred, when
and why to a new deferrals list (migration 0071) and writes a 'defer'
audit event. The request stays pending at the same step; quorum,
four-eyes and delegations read the decisions only and do not see it.

Only someone eligible to sign the open step may defer, so a deferral is
never a way round the maker-checker rule. Tests cover success (circuit
untouched, approval still works after), not found, the maker, an
ineligible role and another tenant.

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
The executive view says how each headline moved since last quarter
("+4 pts depuis le T3"), and only the score had a past. The daily
snapshot now also keeps the annualised exposure, the live critical risks
and the average compliance coverage (migration 0072), each read on its
own so one failing source leaves only its figure empty. /score/history
returns quarter_baseline: the last snapshot before the current quarter
began, or null when none exists, so no delta is ever invented.

The financial summary's top risks also carry ale_after, the exposure
targeted once mitigations are in place, which the view draws next to the
inherent ALE.

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
UpdateRequest writes a fixed set of columns and deferrals was not among
them. POST /governance/approvals/:id/defer answered 200 and the audit
trail recorded one deferral, but the row kept an empty list, so the
executive view never showed "Reportée le …" after a reload. The use-case
tests ran on a fake repository and could not see it; a repository test
now saves a deferral and reads it back.

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
…ign (#903)

The page a risk committee reads, laid out as the mockup: eyebrow with the
committee and quarter, Copier le lien and Exporter le rapport (board
report, then the reports page), four headline figures with their
movement since last quarter, the five largest exposures with inherent
and targeted residual bars, compliance by framework, and the decisions
the committee owes.

Deltas compare today with the last daily snapshot before the quarter
began; with none, the tile says there is no reading yet instead of
inventing a movement. Decisions are the tenant's pending approvals.
Approuver signs the open step, Reporter adds a dated note and moves the
request to the bottom. Both are optimistic and roll back on refusal, and
neither retries: a refused signature is final, and the app-wide mutation
retry sent it four times. A request's own summary is its sub-line when
the requester wrote one.

Every block has its skeleton, error with retry and empty state. The old
analytics service this page used is removed; nothing else imported it.

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
Base automatically changed from feat/902-action-center to master October 9, 2026 08:58
@alex-dembele alex-dembele self-assigned this Oct 9, 2026
@alex-dembele alex-dembele reopened this Oct 9, 2026
@alex-dembele
alex-dembele merged commit 6999958 into master Oct 9, 2026
13 of 25 checks passed
@alex-dembele
alex-dembele deleted the feat/903-executive branch October 9, 2026 09:03
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): executive view on the redesign layout

1 participant