Skip to content

RG-T135 Fixing Setup Wizard and Setup Report Issue - #532

Merged
ucswift merged 1 commit into
masterfrom
develop
Sep 26, 2026
Merged

ucswift merged 1 commit into
masterfrom
develop

Conversation

@ucswift

@ucswift ucswift commented Sep 26, 2026 •

Copy link
Copy Markdown
Member

Summary

Fixes Admin Assist setup and reporting issues by correcting API localization registration, tightening feature-flag requirements, and updating navigation and setup prompt visibility.

Changes

  • Registered ASP.NET Core localization services in the API startup so controllers that depend on IStringLocalizer<T>—including Admin Assist—can be constructed successfully instead of returning HTTP 500 errors.
  • Updated Admin Assist workspace availability:
    • The workspace now requires both Admin.Assist and Ai.AdminAssist feature flags.
    • Missing or unavailable flags fail closed.
    • Existing field help, previews, digests, and operating-profile configuration continue to use their existing Admin Assist/Setup flags.
  • Protected Admin Assist pages and print reports from access unless the workspace feature requirements are met.
  • Updated the top navigation:
    • Added a dedicated Admin Assist menu containing the Admin Assist workspace, Setup Wizard, and Setup Report links.
    • Removed these links from the general Help menu.
    • The Admin Assist workspace link now requires both Admin Assist and AI availability.
  • Restricted the Setup Wizard banner to department administrators and ensured members do not trigger feature-flag or workspace reads.
  • Standardized the Admin Assist title from “Resgrid Admin Assist” to “Admin Assist” across all supported localization resources.
  • Added coverage for:
    • Independent Setup and Admin Assist feature flags.
    • AI-gated workspace launch behavior.
    • Fail-closed behavior when feature flags are missing or unavailable.
    • Setup prompt visibility for administrators versus members.
    • API localization registration and localized Admin Assist catalog resolution.

@request-info

request-info Bot commented Sep 26, 2026

Copy link
Copy Markdown

Thanks for opening this, but we'd appreciate a little more information. Could you update it with more details?

@Resgrid-Bot

Resgrid-Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug ✅
Performance ❌
Security ✅
Business Logic ❌

Access your configuration settings here.

​

@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: Resgrid/Core/.coderabbit.yaml

Review profile: CHILL

Plan: Essentials

Run ID: 036fdd95-c6b8-4373-992e-31be659c4147

📥 Commits

Reviewing files that changed from the base of the PR and between 1ffe728 and 2eda51e.

⛔ Files ignored due to path filters (14)
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.ar.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.de.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.el.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.en.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.es.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.fr.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.it.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.pl.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.sv.resx is excluded by !**/*.resx
  • Core/Resgrid.Localization/Areas/User/AdminAssist/AdminAssist.uk.resx is excluded by !**/*.resx
  • Tests/Resgrid.Tests/AdminAssist/FeatureToggleTests.cs is excluded by !**/Tests/**
  • Tests/Resgrid.Tests/AdminAssist/SetupPromptVisibilityTests.cs is excluded by !**/Tests/**
  • Tests/Resgrid.Tests/Web/ApiLocalizationRegistrationTests.cs is excluded by !**/Tests/**
📒 Files selected for processing (5)
  • Core/Resgrid.Services/AdminAssist/AdminAssistFeatureAvailability.cs
  • Web/Resgrid.Web.Services/Startup.cs
  • Web/Resgrid.Web/Areas/User/Controllers/AdminAssistController.cs
  • Web/Resgrid.Web/Areas/User/Views/Shared/_TopNavbar.cshtml
  • Web/Resgrid.Web/ViewComponents/AdminAssistSetupPromptViewComponent.cs

Included review availability: This review used your included allowance. 2 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour. Your free on-demand review promotion remains active until October 9, 2026 at 6:00 PM UTC.


📝 Walkthrough

Walkthrough

Admin Assist workspace availability now requires both Admin Assist feature flags. Non-setup pages check workspace availability, and navigation displays Admin Assist and setup links in a top-level dropdown.

Changes

Admin Assist workspace

Layer / File(s) Summary
Feature availability rules
Core/Resgrid.Services/AdminAssist/AdminAssistFeatureAvailability.cs
Flag evaluation is shared. Workspace availability requires both Admin Assist flags. Invalid department IDs and non-cancellation evaluation failures return false; requested cancellation propagates. The operating profile rule is unchanged.
Workspace route and prompt checks
Web/Resgrid.Web/Areas/User/Controllers/AdminAssistController.cs, Web/Resgrid.Web/ViewComponents/AdminAssistSetupPromptViewComponent.cs
Non-setup controller actions return NotFound() when the workspace is disabled. Setup pages bypass this workspace check. The setup prompt exits before creating an actor for users who are not department administrators.
Top-level Admin Assist navigation
Web/Resgrid.Web.Services/Startup.cs, Web/Resgrid.Web/Areas/User/Views/Shared/_TopNavbar.cshtml
The top-level Admin Assist dropdown appears when Admin Assist or setup is visible. Localization services are registered, and Admin Assist and setup links are removed from the department and help menus.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant AdminAssistController
  participant AdminAssistFeatureAvailability
  participant IFeatureToggleService
  AdminAssistController->>AdminAssistFeatureAvailability: Check workspace availability
  AdminAssistFeatureAvailability->>IFeatureToggleService: Evaluate Admin Assist flags
  IFeatureToggleService-->>AdminAssistFeatureAvailability: Return flag states
  AdminAssistFeatureAvailability-->>AdminAssistController: Return workspace availability
  AdminAssistController-->>AdminAssistController: Return NotFound when disabled
Loading

Merge Risk: ⚪ Minimal · up to 2eda5

Admin Assist pages and links now follow the workspace flags, while setup remains separately available to eligible admins. No concrete failure in the changed behavior presents a PR-specific merge blocker.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 4 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.
Title check ✅ Passed The title clearly identifies the main change: fixing the Admin Assist setup wizard and setup report issue. It is concise and directly related to the changeset.
Full details: Docstring Coverage

Explanation

Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 4 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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

localized.Should().Contain("AdminAssistController");

var startup = File.ReadAllText(FindRepositoryFile("Web/Resgrid.Web.Services/Startup.cs"));
Regex.IsMatch(startup, @"^\s*services\.AddLocalization\(", RegexOptions.Multiline)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-review Kody Rules high

Regular expression processing without a timeout in Regex.IsMatch can allow untrusted input to trigger denial-of-service (DoS) attacks. Define a timeout for the regular expression.

Kody rule violation: Specify Timeout for Regular Expressions

Prompt for LLM

File Tests/Resgrid.Tests/Web/ApiLocalizationRegistrationTests.cs:

Line 35:

Regular expression processing without a timeout in `Regex.IsMatch` can allow untrusted input to trigger denial-of-service (DoS) attacks. Define a timeout for the regular expression.

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

​

​

Comment on lines +26 to +31
var localized = typeof(Resgrid.Web.Services.Controllers.v4.AdminAssistController).Assembly.GetTypes()
.Where(t => typeof(ControllerBase).IsAssignableFrom(t) && !t.IsAbstract)
.Where(t => t.GetConstructors().Any(c => c.GetParameters().Any(p => p.ParameterType.IsGenericType &&
p.ParameterType.GetGenericTypeDefinition() == typeof(IStringLocalizer<>))))
.Select(t => t.Name)
.ToList();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-review Kody Rules high

The long LINQ chain obscures the separate filtering and projection steps for controllers and localized. Store the controller filter in a named intermediate query before applying the localization filter and projection.

Kody rule violation: Limit Lengthy LINQ Chains

var controllers = typeof(Resgrid.Web.Services.Controllers.v4.AdminAssistController).Assembly.GetTypes()
				.Where(t => typeof(ControllerBase).IsAssignableFrom(t) && !t.IsAbstract);
			var localized = controllers
				.Where(t => t.GetConstructors().Any(c => c.GetParameters().Any(p => p.ParameterType.IsGenericType &&
					p.ParameterType.GetGenericTypeDefinition() == typeof(IStringLocalizer<>))))
				.Select(t => t.Name)
				.ToList();
Prompt for LLM

File Tests/Resgrid.Tests/Web/ApiLocalizationRegistrationTests.cs:

Line 26 to 31:

The long LINQ chain obscures the separate filtering and projection steps for `controllers` and `localized`. Store the controller filter in a named intermediate query before applying the localization filter and projection.

Suggested Code:

var controllers = typeof(Resgrid.Web.Services.Controllers.v4.AdminAssistController).Assembly.GetTypes()
				.Where(t => typeof(ControllerBase).IsAssignableFrom(t) && !t.IsAbstract);
			var localized = controllers
				.Where(t => t.GetConstructors().Any(c => c.GetParameters().Any(p => p.ParameterType.IsGenericType &&
					p.ParameterType.GetGenericTypeDefinition() == typeof(IStringLocalizer<>))))
				.Select(t => t.Name)
				.ToList();

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

​

​

.ToList();
localized.Should().Contain("AdminAssistController");

var startup = File.ReadAllText(FindRepositoryFile("Web/Resgrid.Web.Services/Startup.cs"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-review Kody Rules high

An IOException from File.ReadAllText(FindRepositoryFile("Web/Resgrid.Web.Services/Startup.cs")) currently lacks contextual reporting when Startup.cs cannot be read. Wrap the file-system read in try/catch and call Assert.Fail with the exception message.

Kody rule violation: Add try-catch blocks for external calls

string startup;
try
{
	startup = File.ReadAllText(FindRepositoryFile("Web/Resgrid.Web.Services/Startup.cs"));
}
catch (IOException exception)
{
	Assert.Fail($"Unable to read Startup.cs: {exception.Message}");
	throw;
}
Prompt for LLM

File Tests/Resgrid.Tests/Web/ApiLocalizationRegistrationTests.cs:

Line 34:

An `IOException` from `File.ReadAllText(FindRepositoryFile("Web/Resgrid.Web.Services/Startup.cs"))` currently lacks contextual reporting when `Startup.cs` cannot be read. Wrap the file-system read in `try`/`catch` and call `Assert.Fail` with the exception message.

Suggested Code:

string startup;
try
{
	startup = File.ReadAllText(FindRepositoryFile("Web/Resgrid.Web.Services/Startup.cs"));
}
catch (IOException exception)
{
	Assert.Fail($"Unable to read Startup.cs: {exception.Message}");
	throw;
}

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

​

​

// The workspace launches after Setup Wizard and Setup Report: it also needs Ai.AdminAssist, not just Admin.Assist.
var adminAssistVisible = ClaimsAuthorizationHelper.IsUserDepartmentAdmin() &&
await Resgrid.Services.AdminAssist.AdminAssistFeatureAvailability.IsEnabledAsync(featureToggleService, ClaimsAuthorizationHelper.GetDepartmentId(), false, Context.RequestAborted);
await Resgrid.Services.AdminAssist.AdminAssistFeatureAvailability.IsWorkspaceEnabledAsync(featureToggleService, ClaimsAuthorizationHelper.GetDepartmentId(), Context.RequestAborted);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-review Kody Rules high

Unhandled task rejection from AdminAssistFeatureAvailability.IsWorkspaceEnabledAsync can escape the awaited feature-availability operation without logging or a safe fallback. Guard the operation with try/catch, log the failure with operation and department context, and set adminAssistVisible to false; the same issue occurs in Core/Resgrid.Services/AdminAssist/AdminAssistFeatureAvailability.cs:20-20, Web/Resgrid.Web/Areas/User/Controllers/AdminAssistController.cs:80-80, Core/Resgrid.Services/AdminAssist/AdminAssistFeatureAvailability.cs:23-23, Tests/Resgrid.Tests/AdminAssist/FeatureToggleTests.cs:49-49, Tests/Resgrid.Tests/AdminAssist/SetupPromptVisibilityTests.cs:45-45, Tests/Resgrid.Tests/AdminAssist/SetupPromptVisibilityTests.cs:59-59, Tests/Resgrid.Tests/AdminAssist/SetupPromptVisibilityTests.cs:70-70, Tests/Resgrid.Tests/AdminAssist/FeatureToggleTests.cs:59-59, Tests/Resgrid.Tests/AdminAssist/FeatureToggleTests.cs:57-57, Tests/Resgrid.Tests/AdminAssist/SetupPromptVisibilityTests.cs:88-88, and Tests/Resgrid.Tests/AdminAssist/FeatureToggleTests.cs:51-51.

Kody rule violation: Handle async operations with proper error handling

try
{
    adminAssistVisible = ClaimsAuthorizationHelper.IsUserDepartmentAdmin() &&
        await Resgrid.Services.AdminAssist.AdminAssistFeatureAvailability.IsWorkspaceEnabledAsync(featureToggleService, ClaimsAuthorizationHelper.GetDepartmentId(), Context.RequestAborted);
}
catch (Exception ex)
{
    logger.LogError(ex, "Failed to determine Admin Assist workspace availability for department {DepartmentId}", ClaimsAuthorizationHelper.GetDepartmentId());
    adminAssistVisible = false;
}
Prompt for LLM

File Web/Resgrid.Web/Areas/User/Views/Shared/_TopNavbar.cshtml:

Line 9:

Unhandled task rejection from `AdminAssistFeatureAvailability.IsWorkspaceEnabledAsync` can escape the awaited feature-availability operation without logging or a safe fallback. Guard the operation with `try`/`catch`, log the failure with operation and department context, and set `adminAssistVisible` to `false`; the same issue occurs in `Core/Resgrid.Services/AdminAssist/AdminAssistFeatureAvailability.cs:20-20`, `Web/Resgrid.Web/Areas/User/Controllers/AdminAssistController.cs:80-80`, `Core/Resgrid.Services/AdminAssist/AdminAssistFeatureAvailability.cs:23-23`, `Tests/Resgrid.Tests/AdminAssist/FeatureToggleTests.cs:49-49`, `Tests/Resgrid.Tests/AdminAssist/SetupPromptVisibilityTests.cs:45-45`, `Tests/Resgrid.Tests/AdminAssist/SetupPromptVisibilityTests.cs:59-59`, `Tests/Resgrid.Tests/AdminAssist/SetupPromptVisibilityTests.cs:70-70`, `Tests/Resgrid.Tests/AdminAssist/FeatureToggleTests.cs:59-59`, `Tests/Resgrid.Tests/AdminAssist/FeatureToggleTests.cs:57-57`, `Tests/Resgrid.Tests/AdminAssist/SetupPromptVisibilityTests.cs:88-88`, and `Tests/Resgrid.Tests/AdminAssist/FeatureToggleTests.cs:51-51`.

Suggested Code:

        try
        {
            adminAssistVisible = ClaimsAuthorizationHelper.IsUserDepartmentAdmin() &&
                await Resgrid.Services.AdminAssist.AdminAssistFeatureAvailability.IsWorkspaceEnabledAsync(featureToggleService, ClaimsAuthorizationHelper.GetDepartmentId(), Context.RequestAborted);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Failed to determine Admin Assist workspace availability for department {DepartmentId}", ClaimsAuthorizationHelper.GetDepartmentId());
            adminAssistVisible = false;
        }

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

​

​

@ucswift

ucswift commented Sep 26, 2026

Copy link
Copy Markdown
Member Author

Approve

@github-actions github-actions Bot 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.

This PR is approved.

@ucswift
ucswift merged commit 1c217ae into master Sep 26, 2026
18 of 19 checks passed
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