Skip to content

Refactor UI service layer and dashboard: dedupe, typed status, consistent error/API contracts - #2203

Merged
rodoHasArrived merged 4 commits into
mainfrom
claude/dashboard-service-ui-refactor-e07q5o
Jul 7, 2026
Merged

Refactor UI service layer and dashboard: dedupe, typed status, consistent error/API contracts#2203
rodoHasArrived merged 4 commits into
mainfrom
claude/dashboard-service-ui-refactor-e07q5o

Conversation

@rodoHasArrived

Copy link
Copy Markdown
Owner

Summary

Targeted maintainability fixes across Meridian.Ui.Services, Meridian.Ui.Shared, and the browser dashboard. All changes preserve observable behavior.

Backend (Meridian.Ui.Services / Meridian.Ui.Shared)

  • deps(docker)(deps): bump dotnet/aspnet from 9.0-alpine to 10.0-alpine in /deploy/docker #1 ApiClientService duplication — extracted SendAsync<T>, SendWithResponseAsync<T>, and CreateJsonContent helpers; the near-identical try/catch/wrap logic that was repeated across five methods (GetAsync, GetWithResponseAsync, PostAsync, PostWithResponseAsync, DeleteWithResponseAsync) now lives in one place. Serialization still happens inside the try block, so error handling is unchanged.
  • deps(docker)(deps): bump dotnet/sdk from 9.0-alpine to 10.0-alpine in /deploy/docker #2 Inconsistent "service not registered" statusCoveredCallEndpoints now returns 501 (matching the convention used by every other UI endpoint) instead of 503 when ICoveredCallBacktestService is not registered. The genuine ConfigurationException path keeps its 503, and .Produces(...) declarations were updated accordingly.
  • deps(benchmarks): Bump Npgsql from 9.0.3 to 10.0.2 #3 Knowingly-duplicated resilience policiesHttpClientConfiguration now delegates retry/circuit-breaker to the single SharedResiliencePolicies definition in Meridian.Infrastructure. Both this project and the WPF app already reference Infrastructure directly, so the "keep in sync" comment was stale; the byte-identical private copies were removed. Local timeouts are retained because the desktop backfill client keeps its 60-minute LongTimeout (Infrastructure's LongTimeout is 60 seconds).
  • ci(actions)(deps): bump actions/setup-node from 4 to 6 #5 Hardcoded partial index constituent list — the curated offline fallback lists in PortfolioImportService moved into a documented, data-driven IndexConstituentCatalog (canonical ids + alias map). The lists are clearly labeled partial samples and easy to extend without touching import logic; behavior is identical.
  • deps(nuget): Bump the microsoft-aspnetcore group with 1 update #6 Backfill status compared as raw stringsBackfillService now uses the existing BackfillJobStatus / SymbolBackfillStatus contract constants instead of scattered "Running"/"Paused"/"Completed" literals.
  • ci(actions)(deps): bump stefanzweifel/git-auto-commit-action from 5 to 7 #8 Silent no-op NotificationService — the default notification service now traces each discarded notification via Debug.WriteLine (matching NotificationServiceBase), so a host that forgets to wire a real notification surface gets a diagnostic signal instead of silent loss.

Dashboard (src/Meridian.Ui/dashboard)

Deferred (documented, not in this PR)

These items are large, cross-cutting, or contract-level refactors that cannot be done as a safe, behavior-preserving change in one pass and warrant their own scoped work:

Reason

Addresses a maintainability/consistency review of the UI service and dashboard layers: duplicated logic, contract inconsistencies (status codes, raw status strings), a silent failure mode, an optimistic-update race, and duplicated/divergent constants and error-state UX.

Testing performed

  • bash scripts/ci.sh completed successfully — not run: no .NET SDK is available in this environment; C# changes rely on the GitHub quality-gate.
  • Relevant unit tests were verified — dashboard: typecheck:strict clean; security-details-tracker, accounting-screen (47), trial-balance-screen (component + view-model), w4-acceptance-parity, and design-system-contract tests all pass; ESLint on touched files shows only pre-existing warnings.
  • Relevant integration tests were added or updated — n/a (behavior-preserving).
  • GitHub Actions quality-gate passed — pending CI.

Safety review

  • This pull request targets main
  • No direct push to main was performed
  • No tests were disabled or bypassed
  • No secrets or credentials were committed
  • No unrelated changes were included

Governance changes

  • No governance files changed

🤖 Generated with Claude Code

https://claude.ai/code/session_01GqmPtfK56LqvGdk5vhZodA


Generated by Claude Code

claude added 3 commits July 7, 2026 20:22
…501 convention, notification tracing

- ApiClientService: extract shared SendAsync/SendWithResponseAsync/CreateJsonContent
  helpers, removing near-identical try/catch/wrap logic across five methods (#1).
- CoveredCallEndpoints: return 501 (not 503) when the backtest service is not
  registered, matching the shared not-registered convention; keep 503 only for the
  genuine ConfigurationException path (#2).
- BackfillService: replace raw status string literals with the existing
  BackfillJobStatus / SymbolBackfillStatus contract constants (#6).
- NotificationService: trace discarded notifications when no real surface is wired,
  instead of silently dropping them (#8).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GqmPtfK56LqvGdk5vhZodA
- security-details-tracker: serialize optimistic override patches with a generation
  guard so a stale or failed earlier patch cannot clobber a newer edit, and roll the
  optimistic value back to the last-known-good state when the server rejects it (#11).
- trial-balance-screen / accounting-screen: replace two divergently-named local
  row-count thresholds (both 40) with the shared DENSE_VIRTUALIZATION_THRESHOLD (#12).
- accounting-screen: render error states through the shared StatusBanner instead of
  bare danger divs, matching the error-state UX used elsewhere (#16).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GqmPtfK56LqvGdk5vhZodA
- HttpClientConfiguration: delegate retry/circuit-breaker to the single
  SharedResiliencePolicies definition in Meridian.Infrastructure instead of maintaining
  a byte-identical private copy. Both this project and the WPF app already reference
  Infrastructure, so the 'keep in sync' comment was stale; timeouts stay local because
  the desktop backfill client keeps its 60-minute LongTimeout (#3).
- PortfolioImportService: move the curated offline index-constituent fallback lists into
  a documented, data-driven IndexConstituentCatalog (canonical ids + alias map), so the
  partial samples are easy to extend without editing import logic; behaviour unchanged (#5).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GqmPtfK56LqvGdk5vhZodA
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

Satisfies the dotnet format whitespace gate (one collection element per line),
which was failing verify-fast/verify-dotnet/quality-gate before the build and
tests could run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GqmPtfK56LqvGdk5vhZodA
@rodoHasArrived
rodoHasArrived marked this pull request as ready for review July 7, 2026 21:08
@rodoHasArrived
rodoHasArrived merged commit 719286f into main Jul 7, 2026
20 checks passed
@rodoHasArrived
rodoHasArrived deleted the claude/dashboard-service-ui-refactor-e07q5o branch July 17, 2026 03:39
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.

2 participants