Skip to content

chore(warnings): resolve 25 analyzer quick wins and fix RAPS bugs#261

Open
rlorenzo wants to merge 6 commits into
mainfrom
chore/warning-quick-wins
Open

chore(warnings): resolve 25 analyzer quick wins and fix RAPS bugs#261
rlorenzo wants to merge 6 commits into
mainfrom
chore/warning-quick-wins

Conversation

@rlorenzo

Copy link
Copy Markdown
Contributor

Summary

First branch of the .NET warnings cleanup plan: closes 25 of 44 code-analysis warnings via low-risk fixes and justified suppressions, plus four real bugs found along the way (three in RAPS, one latent test hazard). Six single-purpose commits.

Warning cleanup (25 closed)

Rule Fix
S6967 x11 ModelState guards on 8 RAPS view actions (bad params now 400 instead of proceeding with defaults); justified suppressions on the 2 nav filter overrides; [NonAction] on RAPSController.Nav removes an unintended endpoint
S6964 x5 .editorconfig suppression for ApiPagination (never model-bound, always constructed server-side); GroupAddEdit.GroupId made nullable
CA1505 x3 .editorconfig suppression for scaffolded EF *Context.cs, following the existing S3251 precedent
S6932 x3 Justified suppression (nav filter reads query params for left-nav context only; model binding unavailable in a filter)
S6672 CMS logger created via ILoggerFactory for Data.CMS; log category unchanged
S6931 Directory route prefix moved to controller-level [Route]; all 5 URLs provably unchanged
CA1502 Test ctor mock factories extracted in ServiceLayerIntegrationTest

Bug fixes (behavior changes to note)

  • AdGroupsController.UpdateGroup: missing return meant a PUT with a mismatched group ID fell through and updated the group anyway; now 400. Regression test added (the group-edit UI always sends a matching ID, so normal use is unaffected).
  • RAPS nav member lookup: SingleAsync 500ed every RAPS page when ?memberId= matched no user; now SingleOrDefaultAsync with the existing null handling.
  • RAPS action pipeline ran twice: OnActionExecutionAsync awaited both the AreaController base (which already invokes next()) and next() again.
  • GroupSync background sync: fire-and-forget task captured the request-scoped RAPSContext (disposed when the response returns); now resolves a fresh context from IServiceScopeFactory and logs failures.

Verification

  • Clean verify:build: all 25 targeted warnings gone, no new ones; the 19 remaining warnings match the plan's deferred list exactly
  • Full backend suite green (2,141 tests) on every commit via pre-commit hooks
  • Playwright smoke on dev: RAPS pages incl. bogus deep-links (?roleId=abc 400, nonexistent ?memberId= 200), mismatched-ID group PUT 400, all 5 Directory endpoints, CTS index
  • Reviewed via code-review-loop (editor: claude, reviewer: antigravity), closed clean in 1 cycle

Not merged to Development yet; that follows after review.

rlorenzo added 3 commits July 17, 2026 00:00
- suppress CA1505 for scaffolded EF contexts and S6964 for
  ApiPagination, which is never model-bound (editorconfig precedent)
- create the Data.CMS logger via ILoggerFactory so the logger
  category matches its consumer (S6672)
- move the Directory route prefix to the controller, URLs unchanged
  (S6931)
- return 400 from RAPS view actions when model binding fails instead
  of proceeding with defaulted params (S6967)
- suppress S6967/S6932 on the RAPS and CTS nav filter overrides with
  justification; mark RAPSController.Nav [NonAction] to remove an
  unintended endpoint
- make GroupAddEdit.GroupId nullable to reflect create semantics
  (S6964)
Splits the two large NSubstitute fakes out of
ServiceLayerIntegrationTest constructor (CA1502); behavior unchanged.
The BadRequest result was discarded, so a PUT whose body groupId did
not match the route fell through and updated the group anyway. Add a
regression test asserting the 400 and that the group is unchanged.
@rlorenzo

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@codecov-commenter

Copy link
Copy Markdown

Bundle Report

Bundle size has no change ✅

@codecov-commenter

codecov-commenter commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 4.34783% with 44 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.32%. Comparing base (0c5ab2b) to head (9c1af27).

Files with missing lines Patch % Lines
web/Areas/RAPS/Controllers/RAPSController.cs 0.00% 42 Missing ⚠️
web/Areas/CMS/Controllers/CMSController.cs 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #261      +/-   ##
==========================================
+ Coverage   45.29%   45.32%   +0.02%     
==========================================
  Files         897      897              
  Lines       51928    51965      +37     
  Branches     4878     4886       +8     
==========================================
+ Hits        23523    23551      +28     
- Misses      27803    27810       +7     
- Partials      602      604       +2     
Flag Coverage Δ
backend 45.41% <4.34%> (+0.02%) ⬆️
frontend 43.41% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/warning-quick-wins

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/Areas/Directory/Controllers/DirectoryController.cs`:
- Line 35: Update the Directory home action route in DirectoryController to
preserve the trailing slash, using an area-root route that resolves to
/Directory/; alternatively, add a redirect from /Directory to /Directory/.
Ensure relative "nav" requests continue resolving under the Directory path.

In `@web/Areas/RAPS/Controllers/RAPSController.cs`:
- Around line 94-99: Update the read-only queries in Nav, specifically the
TblRoles, TblPermissions, and VwAaudUser lookups, to use AsNoTracking() before
execution while preserving their existing filters and null-handling behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b12c4003-6bfe-4fe7-9c83-98cd8619e44c

📥 Commits

Reviewing files that changed from the base of the PR and between 0c5ab2b and 0375aea.

📒 Files selected for processing (9)
  • .editorconfig
  • test/ClinicalScheduler/Integration/ServiceLayerIntegrationTest.cs
  • test/RAPS/AdGroupsControllerTests.cs
  • web/Areas/CMS/Controllers/CMSController.cs
  • web/Areas/CTS/Controllers/CTSController.cs
  • web/Areas/Directory/Controllers/DirectoryController.cs
  • web/Areas/RAPS/Controllers/AdGroupsController.cs
  • web/Areas/RAPS/Controllers/RAPSController.cs
  • web/Areas/RAPS/Models/GroupAddEdit.cs

Comment thread web/Areas/Directory/Controllers/DirectoryController.cs
Comment thread web/Areas/RAPS/Controllers/RAPSController.cs Outdated
rlorenzo added 2 commits July 17, 2026 00:26
SingleAsync threw on every RAPS page when the memberId query param
matched no user; the nav already handles the null case.
OnActionExecutionAsync awaited both the AreaController base, which
already invokes next(), and next() again, so every RAPS action ran
its pipeline twice.
@rlorenzo
rlorenzo force-pushed the chore/warning-quick-wins branch from 0375aea to bd4a19f Compare July 17, 2026 07:26
@rlorenzo

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@rlorenzo
rlorenzo requested a review from Copilot July 17, 2026 07:42
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR is the first tranche of the .NET analyzer-warning cleanup plan for VIPER’s ASP.NET backend, combining low-risk warning fixes/suppressions with a few behavior-correctness fixes discovered during the cleanup (notably in RAPS and one API bug).

Changes:

  • Fixes several real behavior bugs (e.g., AdGroups PUT ID mismatch fallthrough; RAPS SingleAsync -> SingleOrDefaultAsync; RAPS action pipeline double-execution; request-scoped DbContext capture in background sync).
  • Adds ModelState guards to multiple RAPS actions and uses targeted analyzer suppressions/[NonAction] where appropriate.
  • Refactors a test constructor to reduce complexity and adds a regression test for the AdGroups update bug.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
web/Areas/RAPS/Models/GroupAddEdit.cs Makes GroupId nullable to better represent “new group” semantics and satisfy analyzer guidance.
web/Areas/RAPS/Controllers/RAPSController.cs Fixes filter pipeline double-execution, hardens nav member lookup, and moves OU sync to a background scope.
web/Areas/RAPS/Controllers/AdGroupsController.cs Fixes missing return on mismatched PUT ID to prevent unintended updates.
web/Areas/Directory/Controllers/DirectoryController.cs Consolidates route prefix at controller level while keeping endpoints consistent.
web/Areas/CTS/Controllers/CTSController.cs Adds targeted analyzer suppression for filter override.
web/Areas/CMS/Controllers/CMSController.cs Uses ILoggerFactory to create a Data.CMS-category logger without triggering the analyzer.
test/RAPS/AdGroupsControllerTests.cs Adds regression coverage for the mismatched group ID PUT bug.
test/ClinicalScheduler/Integration/ServiceLayerIntegrationTest.cs Extracts mock factories to reduce constructor complexity.
.editorconfig Adds/extends justified suppressions for generated contexts and non-bound model types.

Comment on lines +618 to +630
using var scope = _scopeFactory.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<RAPSContext>();
try
{
await new OuGroupService(context).Sync(groupId, groupName);
}
catch (Exception ex) when (ex is DbUpdateException or InvalidOperationException
or System.DirectoryServices.Protocols.LdapException
or System.DirectoryServices.Protocols.DirectoryOperationException
or HttpRequestException)
{
LogManager.GetCurrentClassLogger().Error(ex, "Group sync failed for group {GroupId}", groupId);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First point applied in 9c1af27: CreateScope()/GetRequiredService<RAPSContext>() now resolve inside the try, and ObjectDisposedException was added to the filter for the host-shutdown race, so nothing can escape the fire-and-forget task unobserved.

On log injection: groupId here is a model-bound int (guarded by the new ModelState.IsValid check), so it cannot carry CRLF or any injection payload. The codebase convention (LogSanitizer.SanitizeId) only accepts strings and is applied to user-supplied string identifiers; CLAUDE.md scopes the rule to user-supplied string input. Leaving the int as-is.

The fire-and-forget sync captured the request-scoped RAPSContext,
which is disposed once the response returns, faulting the background
task. Resolve a fresh context from IServiceScopeFactory and log
failures instead of leaving them unobserved.
@rlorenzo
rlorenzo force-pushed the chore/warning-quick-wins branch from bd4a19f to 9c1af27 Compare July 17, 2026 07:51
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.

3 participants