Skip to content

CodeQL 3: fix: close CodeQL correctness alerts#191

Open
rlorenzo wants to merge 3 commits into
mainfrom
codeql/3-correctness
Open

CodeQL 3: fix: close CodeQL correctness alerts#191
rlorenzo wants to merge 3 commits into
mainfrom
codeql/3-correctness

Conversation

@rlorenzo
Copy link
Copy Markdown
Contributor

@rlorenzo rlorenzo commented May 13, 2026

Summary

Closes ~15 CodeQL alerts across three correctness rule families. Each fix needs per-site judgment, so they're consolidated here rather than split — the reviewer mental model is the same throughout.

Note: this PR was originally drafted with ~30 fixes; about half landed in main first via #176/#190 (b9266fe was an explicit pre-merge to keep the two branches from conflicting). The remaining fixes are described below.

cs/virtual-call-in-constructor

Safety check: not inherited from in C#, not Substitute.For<...> in tests, and there is no UseLazyLoadingProxies() call anywhere in the project so EF doesn't need it non-sealed.

A RoleTemplateSimplified alert in the same family is closed in commit 2dd08d8 by dropping virtual from the Roles property — a smaller change than sealing, which keeps the public constructor surface intact. New unit tests in test/RAPS/RoleTemplateSimplifiedTests.cs lock in the constructor mapping (RoleTemplateId, TemplateName, Description, and Roles projection) so future regressions surface.

cs/unsafe-year-construction

cs/constant-condition

Removed redundant null-propagation that the analyzer can already prove dead:

Context

Third in the CodeQL N: cleanup series (after #189, #190).

Test plan

  • npm run test — backend + frontend passing
  • npm run verify:build — clean (0 errors)
  • npm run lint — passing on changed files
  • CodeQL workflow on this PR shows the listed alerts closed

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

PR hardens null-safety by consolidating nullable-conditional patterns into explicit non-null assertions where control flow guarantees non-nullability. Also seals model classes, removes EF virtual modifiers, adopts factory-method pattern for RoleTemplateSimplified, changes CompetencyController duplicate-detection behavior to include the current competency, and improves validation logic in services and utilities.

Changes

Null-safety assertions and code quality improvements

Layer / File(s) Summary
Test and assertion null-safety hardening
test/CTS/AssessmentControllerTest.cs, web/Areas/CTS/Controllers/AssessmentController.cs
Test assertion and early validation patterns made non-null-safe where control flow guarantees non-nullability.
Controller method null-safety refactoring
web/Controllers/HomeController.cs, web/Areas/RAPS/Controllers/RAPSController.cs
HomeController methods replace nullable-propagation with explicit non-null assertions; RAPSController refactors index-checking using pattern matching.
Model visibility and structure updates
web/Areas/CMS/Models/CMSFile.cs, web/Models/Students/StudentClassYear.cs
CMSFile and StudentClassYear are sealed; StudentClassYear navigation properties remove virtual modifiers to disable EF lazy-loading.
CompetencyController duplicate detection logic change
web/Areas/CTS/Controllers/CompetencyController.cs
Request payload CompetencyId validation removed; duplicate-detection no longer excludes the current competency from the duplicate set.
Factory pattern adoption and view simplification
web/Areas/RAPS/Models/RoleTemplateSimplified.cs, web/Areas/RAPS/Controllers/RoleTemplatesController.cs
RoleTemplateSimplified converts from constructor to static FromRoleTemplate factory; callers updated and GetRoleTemplateApplyPreview removes placeholder fallback values.
Service null-safety and validation improvements
web/Areas/CTS/Models/AuditRow.cs, web/Areas/Effort/Services/PercentageService.cs, web/Areas/RAPS/Services/RAPSAuditService.cs
AuditRow, PercentageService, and RAPSAuditService replace nullable-conditional access with direct property access or null-forgiving operators.
Utility improvements and parameter validation
web/Areas/Effort/Services/PercentRolloverService.cs, web/Classes/Utilities/AcademicYearHelper.cs, web/Program.cs
PercentRolloverService adds year range validation; AcademicYearHelper refactors July anchor computation; Program.cs simplifies AWS credential parsing with local variables and reflection.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title accurately summarizes the main change: closing CodeQL correctness alerts across multiple files. It's specific and directly reflects the PR's primary purpose.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description clearly relates to the changeset: it explains the CodeQL alerts being closed, provides context for the three rule families (virtual-call-in-constructor, unsafe-year-construction, constant-condition), and details the changes in each modified file.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codeql/3-correctness

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 and usage tips.

Comment thread web/Areas/RAPS/Controllers/RAPSController.cs Fixed
Comment thread web/Program.cs Fixed
@codecov-commenter
Copy link
Copy Markdown

Bundle Report

Bundle size has no change ✅

Comment thread web/Areas/RAPS/Controllers/RAPSController.cs Fixed
Comment thread web/Program.cs Fixed
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 13, 2026

Codecov Report

❌ Patch coverage is 19.35484% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 43.08%. Comparing base (ed1f48b) to head (5a244d0).

Files with missing lines Patch % Lines
web/Areas/RAPS/Controllers/RAPSController.cs 0.00% 9 Missing ⚠️
.../Areas/RAPS/Controllers/RoleTemplatesController.cs 0.00% 5 Missing ⚠️
web/Models/Students/StudentClassYear.cs 0.00% 4 Missing ⚠️
web/Areas/CTS/Models/AuditRow.cs 0.00% 3 Missing ⚠️
web/Areas/RAPS/Services/RAPSAuditService.cs 0.00% 3 Missing ⚠️
web/Controllers/HomeController.cs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #191      +/-   ##
==========================================
+ Coverage   43.02%   43.08%   +0.05%     
==========================================
  Files         881      881              
  Lines       51437    51439       +2     
  Branches     4812     4808       -4     
==========================================
+ Hits        22131    22160      +29     
+ Misses      28780    28752      -28     
- Partials      526      527       +1     
Flag Coverage Δ
backend 43.15% <19.35%> (+0.05%) ⬆️
frontend 41.47% <ø> (ø)

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

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

@rlorenzo
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

✅ Actions performed

Review triggered.

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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/RAPS/Controllers/RoleTemplatesController.cs`:
- Around line 45-49: Replace the explicit loop and mutable list plumbing by
projecting dbRoleTemplates into the simplified DTO: use a LINQ Select that calls
RoleTemplateSimplified.FromRoleTemplate for each rt on dbRoleTemplates and
materialize to a List (assign to roleTemplates) instead of creating
roleTemplates and using foreach + Add.

In `@web/Areas/RAPS/Models/RoleTemplateSimplified.cs`:
- Around line 22-31: Replace the manual mapping inside
RoleTemplateSimplified.FromRoleTemplate by delegating to a Mapperly-generated
mapper: change the implementation to call
RoleTemplateSimplifiedMapper.ToSimplified(rt), and add a new static partial
mapper type named RoleTemplateSimplifiedMapper decorated with
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.None)] that declares a
partial method ToSimplified(RoleTemplate source) returning
RoleTemplateSimplified so Mapperly can generate the mapping.

In `@web/Program.cs`:
- Around line 558-565: The lookup can return null for unknown names; replace the
reflection-based lookup with RegionEndpoint.GetBySystemName(regionValue) (or try
both regionValue and a PascalCase variant) and if that returns null either set
profile.Region = RegionEndpoint.USWest1 as a safe default or throw a
FormatException; update the code around regionValue/profile.Region to use
RegionEndpoint.GetBySystemName(regionValue) and handle a null result explicitly
(throwing FormatException or assigning the default).
🪄 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: 501d2df3-d7b5-44d5-a105-53874a3f7b1b

📥 Commits

Reviewing files that changed from the base of the PR and between 5949e52 and 53b6eef.

📒 Files selected for processing (15)
  • test/CTS/AssessmentControllerTest.cs
  • web/Areas/CMS/Models/CMSFile.cs
  • web/Areas/CTS/Controllers/AssessmentController.cs
  • web/Areas/CTS/Controllers/CompetencyController.cs
  • web/Areas/CTS/Models/AuditRow.cs
  • web/Areas/Effort/Services/PercentRolloverService.cs
  • web/Areas/Effort/Services/PercentageService.cs
  • web/Areas/RAPS/Controllers/RAPSController.cs
  • web/Areas/RAPS/Controllers/RoleTemplatesController.cs
  • web/Areas/RAPS/Models/RoleTemplateSimplified.cs
  • web/Areas/RAPS/Services/RAPSAuditService.cs
  • web/Classes/Utilities/AcademicYearHelper.cs
  • web/Controllers/HomeController.cs
  • web/Models/Students/StudentClassYear.cs
  • web/Program.cs
💤 Files with no reviewable changes (1)
  • web/Areas/CTS/Controllers/CompetencyController.cs

Comment thread web/Areas/RAPS/Controllers/RoleTemplatesController.cs Outdated
Comment thread web/Areas/RAPS/Models/RoleTemplateSimplified.cs Outdated
Comment thread web/Program.cs Outdated
@rlorenzo rlorenzo force-pushed the codeql/3-correctness branch 7 times, most recently from d915095 to 9743d93 Compare May 13, 2026 20:59
@rlorenzo rlorenzo force-pushed the codeql/3-correctness branch from 9743d93 to df971c6 Compare May 21, 2026 07:41
rlorenzo added 3 commits May 27, 2026 17:21
Three rule families consolidated into one PR because each fix needs
per-site judgment rather than mechanical replacement.

cs/virtual-call-in-constructor (5): seal CMSFile and StudentClassYear -
neither is inherited from in C#, neither is mocked, and the project
has no UseLazyLoadingProxies so EF does not need them non-sealed.
Drops `virtual` on properties newly declared inside the now-sealed
classes. For RoleTemplateSimplified the same alert is closed by
dropping `virtual` from the Roles property, which is a smaller change
than sealing and keeps the public constructor surface intact.

cs/unsafe-year-construction (4): in PercentRolloverService, bound the
HTTP-derived year parameter with ArgumentOutOfRangeException and use
.AddYears(1) instead of `new DateTime(year+1, ...)` for the target
end date. In AcademicYearHelper.GetAcademicYearStart, build the July
date first then .AddYears(-1) instead of subtracting from .Year before
constructing.

cs/constant-condition (21): remove redundant null-propagation that
the analyzer can already prove dead - `?.` chains after `!= null`
guards, an unreachable CompetencyId range check after the FindAsync
record-existence check, and a duplicated `RegionEndpoint` element
lookup in SetAwsCredentials. RAPSController null-flow was restructured
to lift the path null check up.

The SetAwsCredentials region lookup also gets hardened to truly
close the alert: trim the value, look it up with
BindingFlags.IgnoreCase, and fall back to USWest1 when the name is
non-empty but does not match any known region (previously left
profile.Region as null).
These were flagged by the ReSharper PR-scoped gate as new warnings on
lines my CodeQL 3 fix touched:

- CMSFile.cs: drop redundant 'partial' modifier (PartialTypeWithSinglePart)
- RAPSController.cs: 'is int idx' on int? -> 'is { } idx'
  (ConvertTypeCheckPatternToNullCheck)
- RoleTemplatesController.cs: drop '??' fallbacks; both properties are
  declared non-null (NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract)

Also folds in the controller cleanup from CodeRabbit on the same lines:
replace foreach + Add with .Select(...).ToList() to match the project's
LINQ conventions.
Two unit tests for the constructor that drives the GetRoleTemplates
projection:

- Constructor_MapsScalarsAndFlattensRoles: verifies the scalar
  properties and the nested RoleTemplateRoles -> Roles flattening
  via Role.RoleId / Role.FriendlyName.
- Constructor_EmptyRoles_ReturnsEmptyCollection: ensures the Roles
  initializer does not depend on a non-empty source collection.

Pins the constructor's mapping behavior so the cs/virtual-call-in-
constructor fix (dropping `virtual` from Roles) does not silently
regress the projection.
@rlorenzo rlorenzo force-pushed the codeql/3-correctness branch from df971c6 to 5a244d0 Compare May 28, 2026 00:32
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