Skip to content

Develop#11

Merged
ucswift merged 3 commits intomasterfrom
develop
May 1, 2026
Merged

Develop#11
ucswift merged 3 commits intomasterfrom
develop

Conversation

@ucswift
Copy link
Copy Markdown
Member

@ucswift ucswift commented Apr 30, 2026

Summary by CodeRabbit

  • New Features

    • Added support for system API key authentication and multiple grant types for API access.
    • Added department-scoped operations for hosted/multi-tenant deployments.
    • Added dispatch code resolution with optional Redis caching for improved lookup performance.
    • Extended dispatch types to include group messages and distribution lists.
  • Configuration

    • Updated environment variable naming scheme from RELAY_ to RESGRID__RELAY__.
    • Added comprehensive configuration validation with detailed error messages.
    • Introduced configurable domain routing for different dispatch code types.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

Warning

Rate limit exceeded

@ucswift has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 50 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 69876f04-c781-424e-bcd8-b6dd82db3b7f

📥 Commits

Reviewing files that changed from the base of the PR and between a436118 and dd6f5af.

📒 Files selected for processing (10)
  • Dockerfile
  • Providers/Resgrid.Providers.ApiClient/V4/DispatchListBuilder.cs
  • Resgrid.Audio.Relay.Console/Program.cs
  • Resgrid.Audio.Relay.Console/Smtp/RedisDispatchLookupCache.cs
  • Resgrid.Audio.Relay.Console/Smtp/SmtpDispatchAddressParser.cs
  • Resgrid.Audio.Relay.Console/Smtp/SmtpRelayInfrastructure.cs
  • Resgrid.Audio.Relay.Console/Smtp/SmtpTelemetry.cs
  • Resgrid.Audio.Tests/DispatchListBuilderTests.cs
  • Resgrid.Audio.Tests/SmtpDispatchAddressParserTests.cs
  • Resgrid.Audio.Tests/SmtpRelayTelemetryTests.cs
📝 Walkthrough

Walkthrough

The PR extends the Resgrid Audio Relay system to support hosted multi-department scenarios with system API key authentication, dispatch code resolution via lookups with optional Redis caching, and new dispatch code types (GroupMessage, DistributionList). Configuration migrates from RELAY_* to RESGRID__RELAY__* environment variables, and SMTP address parsing extracts department context from email domains.

Changes

Cohort / File(s) Summary
Docker Configuration
Dockerfile, docker-entrypoint.sh
Replaces RELAY_* environment variable prefix with RESGRID__RELAY__*; adds Resgrid API, SMTP, hosted-mode, and optional Redis configuration blocks; validates required config before startup and adjusts LocalXpose tunnel port references.
API Client Authentication & Options
Providers/Resgrid.Providers.ApiClient/V4/ResgridApiClientOptions.cs, Providers/Resgrid.Providers.ApiClient/V4/ResgridV4ApiClient.cs
Introduces ResgridAuthGrantType enum with RefreshToken, ClientCredentials, and SystemApiKey modes; adds SystemApiKey and DepartmentId properties; implements system-API-key header injection, grant-type-dependent validation, and CurrentUserId derivation from department context.
API Client Calls & Models
Providers/Resgrid.Providers.ApiClient/V4/CallsApi.cs, Providers/Resgrid.Providers.ApiClient/V4/Models/CallModels.cs
Adds optional departmentId parameter to GetCallAsync; adds DepartmentId property to NewCallInput and SaveCallFileInput for hosted multi-department scoping.
Dispatch Code & Lookup APIs
Providers/Resgrid.Providers.ApiClient/V4/DispatchListBuilder.cs, Providers/Resgrid.Providers.ApiClient/V4/LookupsApi.cs, Providers/Resgrid.Providers.ApiClient/V4/Models/LookupModels.cs
Adds GroupMessage and DistributionList dispatch code types; extends DispatchCode with ResolvedId and computed properties; refactors DispatchListBuilder to accept DispatchCode objects and filter Department/DistributionList types; introduces new lookup API methods and response models for resolving codes/names to numeric IDs.
Cache Layer
Resgrid.Audio.Relay.Console/Smtp/IDispatchLookupCache.cs, Resgrid.Audio.Relay.Console/Smtp/NullDispatchLookupCache.cs, Resgrid.Audio.Relay.Console/Smtp/RedisDispatchLookupCache.cs, Resgrid.Audio.Relay.Console/Smtp/CachedLookupsService.cs
Introduces caching contract with Get/Set methods for dispatch and role lookups scoped by department; provides no-op null cache implementation; implements Redis-backed cache with camelCase JSON serialization, TTL support, and graceful fallback on Redis failures; wraps LookupsApi with cache-aware async lookups.
Relay Configuration & Startup
Resgrid.Audio.Relay.Console/Configuration/RelayHostOptions.cs, Resgrid.Audio.Relay.Console/Program.cs, Resgrid.Audio.Relay.Console/appsettings.json
Expands SmtpRelayOptions with domain routing arrays, hosted-mode flags, dispatch code resolution toggle, and Redis cache configuration; adds startup configuration validation for required API credentials and grant-type-dependent fields; updates appsettings with new configuration structure.
SMTP Relay Core Logic
Resgrid.Audio.Relay.Console/Smtp/SmtpDispatchAddressParser.cs, Resgrid.Audio.Relay.Console/Smtp/SmtpRelayInfrastructure.cs, Resgrid.Audio.Relay.Console/Smtp/SmtpTelemetry.cs
Refactors address parser to return DispatchParseResult with extracted DepartmentId from domains; implements domain-based dispatch code type detection (Department, Group, GroupMessage, DistributionList); extends relay infrastructure to resolve dispatch codes via lookups, pass DepartmentId to API calls, and handle new dispatch types; adds telemetry counters for GroupMessage and DistributionList dispatches.
Dependencies & Tests
Resgrid.Audio.Relay.Console/Resgrid.Audio.Relay.Console.csproj, Resgrid.Audio.Tests/DispatchListBuilderTests.cs, Resgrid.Audio.Tests/SmtpDispatchAddressParserTests.cs
Adds StackExchange.Redis NuGet dependency; updates DispatchListBuilder tests to verify exclusion of Department/DistributionList types and preference for ResolvedId; expands parser tests to cover domain-based type detection and hosted-mode department extraction.

Sequence Diagram(s)

sequenceDiagram
    participant Relay as SMTP Relay Engine
    participant Parser as SmtpDispatchAddressParser
    participant Cache as CachedLookupsService
    participant Redis as Redis Cache
    participant API as LookupsApi
    participant Resgrid as Resgrid API

    Relay->>Parser: ParseRecipients(addresses)
    Parser->>Parser: Extract DepartmentId from domains
    Parser->>Parser: Detect DispatchCode types
    Parser-->>Relay: DispatchParseResult

    alt ResolveDispatchCodes enabled
        Relay->>Cache: LookupGroupByDispatchCodeAsync(code)
        Cache->>Redis: Get dispatch code mapping
        alt Cache Hit
            Redis-->>Cache: Cached result
        else Cache Miss
            Cache->>API: LookupGroupByDispatchCodeAsync
            API->>Resgrid: GET /api/v4/lookups/groups/dispatch-code
            Resgrid-->>API: Group numeric ID
            API-->>Cache: Result
            Cache->>Redis: Store result with TTL
            Redis-->>Cache: Stored
        end
        Cache-->>Relay: GroupLookupResult
        Relay->>Relay: Update DispatchCode.ResolvedId
    end

    Relay->>Relay: Build dispatch tokens using ResolvedId
    Relay->>Resgrid: POST /api/v4/calls (with DepartmentId)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Develop #7: Introduces initial v4 API client infrastructure (CallsApi, ResgridV4ApiClient, DispatchListBuilder, SmtpDispatchAddressParser) that this PR extends significantly with dispatch code resolution, authentication refactoring, and caching capabilities.

Poem

🐰 Hops through email realms with glee,
Dispatch codes resolved by ID,
Redis caches swift and sure,
Multi-tenant departments pure,
Relays hop from hop to hop! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Develop' is vague and generic, providing no meaningful information about the changeset's primary purpose. Replace with a descriptive title that summarizes the main change, such as 'Add dispatch code resolution and multi-department support' or similar.
✅ Passed checks (3 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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

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
Review rate limit: 0/1 reviews remaining, refill in 9 minutes and 50 seconds.

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

Copy link
Copy Markdown

@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: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Providers/Resgrid.Providers.ApiClient/V4/ResgridApiClientOptions.cs (1)

74-100: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't require OAuth client credentials in SystemApiKey mode.

ResgridV4ApiClient skips token acquisition entirely for SystemApiKey and only sends X-Resgrid-SystemApiKey, so the unconditional ClientId/ClientSecret checks reject a configuration the runtime can otherwise use. Program.ValidateOptions mirrors the same assumption, so both validators need to be relaxed together.

Suggested fix
-			if (String.IsNullOrWhiteSpace(ClientId))
-				throw new InvalidOperationException("A Resgrid API client id is required.");
-
-			if (String.IsNullOrWhiteSpace(ClientSecret))
-				throw new InvalidOperationException("A Resgrid API client secret is required.");
-
 			switch (GrantType)
 			{
 				case ResgridAuthGrantType.RefreshToken:
+					if (String.IsNullOrWhiteSpace(ClientId))
+						throw new InvalidOperationException("A Resgrid API client id is required.");
+					if (String.IsNullOrWhiteSpace(ClientSecret))
+						throw new InvalidOperationException("A Resgrid API client secret is required.");
+
 					if (String.IsNullOrWhiteSpace(RefreshToken) && String.IsNullOrWhiteSpace(TokenCachePath))
 						throw new InvalidOperationException(
 							"A refresh token or token cache path is required when using the refresh_token grant type.");
 					break;
 
 				case ResgridAuthGrantType.ClientCredentials:
-					// Only ClientId and ClientSecret are required — already validated above.
+					if (String.IsNullOrWhiteSpace(ClientId))
+						throw new InvalidOperationException("A Resgrid API client id is required.");
+					if (String.IsNullOrWhiteSpace(ClientSecret))
+						throw new InvalidOperationException("A Resgrid API client secret is required.");
 					break;
 
 				case ResgridAuthGrantType.SystemApiKey:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Providers/Resgrid.Providers.ApiClient/V4/ResgridApiClientOptions.cs` around
lines 74 - 100, The current validation in ResgridApiClientOptions always
enforces ClientId and ClientSecret even when GrantType ==
ResgridAuthGrantType.SystemApiKey; update the validator so that the checks for
ClientId and ClientSecret are skipped when GrantType is SystemApiKey (aligning
with ResgridV4ApiClient behavior), and ensure Program.ValidateOptions is changed
similarly so both validators allow configurations that use SystemApiKey without
requiring OAuth client credentials.
🧹 Nitpick comments (1)
Providers/Resgrid.Providers.ApiClient/V4/DispatchListBuilder.cs (1)

18-39: ⚡ Quick win

Make the explicit enum values match the documented pipeline IDs.

The XML docs say DistributionList = 2, Group = 3, and GroupMessage = 4, but the assigned values are Group = 2, GroupMessage = 3, DistributionList = 4. If these ever cross a boundary as integers, they will be misclassified; even if they do not, the docs are now lying. Please either realign the numeric assignments or remove the type-number claims from the comments.

One way to realign the enum
-		Group = 2,
+		DistributionList = 2,
 
 		/// <summary>
-		/// Group message email (Type 4 in the Postmark pipeline).
+		/// Group dispatch email (Type 3 in the Postmark pipeline).
+		/// The local-part is the dispatch email code stored in
+		/// DepartmentGroups.DispatchEmail. It resolves to a single numeric
+		/// group ID via the lookup API.
+		/// </summary>
+		Group = 3,
+
+		/// <summary>
+		/// Group message email (Type 4 in the Postmark pipeline).
 		/// The local-part is the message email code stored in
 		/// DepartmentGroups.MessageEmail. Results in a group message,
 		/// not a call.
 		/// </summary>
-		GroupMessage = 3,
-
-		/// <summary>
-		/// Distribution list email (Type 2 in the Postmark pipeline).
-		/// The local-part is the list address stored in
-		/// DistributionLists.EmailAddress. Results in list forwarding.
-		/// </summary>
 		DistributionList = 4
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Providers/Resgrid.Providers.ApiClient/V4/DispatchListBuilder.cs` around lines
18 - 39, The enum explicit values for DistributionList, Group, and GroupMessage
in DispatchListBuilder.cs do not match their XML docs (docs claim
DistributionList=2, Group=3, GroupMessage=4) which causes misclassification;
update the enum numeric assignments so DistributionList = 2, Group = 3,
GroupMessage = 4 (or alternatively remove the hard-coded numeric values and
adjust the XML comments to not claim specific pipeline IDs) and ensure the enum
declarations for Group, GroupMessage, and DistributionList reflect the corrected
mapping to keep code and docs consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfile`:
- Around line 54-63: The ENV lines for the Resgrid relay variables (e.g.
RESGRID__RELAY__Resgrid__BaseUrl, RESGRID__RELAY__Resgrid__ApiVersion,
RESGRID__RELAY__Resgrid__ClientId, RESGRID__RELAY__Resgrid__ClientSecret,
RESGRID__RELAY__Resgrid__RefreshToken, RESGRID__RELAY__Resgrid__Scope,
RESGRID__RELAY__Resgrid__TokenCachePath, RESGRID__RELAY__Resgrid__GrantType,
RESGRID__RELAY__Resgrid__SystemApiKey, RESGRID__RELAY__Resgrid__DepartmentId)
currently include inline “#” comments which become part of the variable values;
remove those inline comments, place any explanatory text on separate comment
lines above each ENV (use e.g. ## or #), and set empty/required variables to
explicit empty strings (e.g. RESGRID__RELAY__Resgrid__BaseUrl="" and
RESGRID__RELAY__Resgrid__ClientId="") so values are unambiguous; repeat the same
change for the other commented ENV blocks (e.g. the block around lines 95–99) to
prevent configuration binding failures.

In `@Providers/Resgrid.Providers.ApiClient/V4/DispatchListBuilder.cs`:
- Around line 94-102: The Build method in DispatchListBuilder
(Build(IEnumerable<DispatchCode> dispatchCodes, string departmentDispatchPrefix
= "G")) is including DispatchCodeType.GroupMessage recipients; update the LINQ
filter to also exclude x.Type == DispatchCodeType.GroupMessage so group-message
targets are not formatted or included in the returned tokens (i.e., add a
condition like && x.Type != DispatchCodeType.GroupMessage to the Where clause
before Select/Distinct); keep using Format(x, departmentDispatchPrefix) and the
existing Distinct behavior after the filter.

In `@Resgrid.Audio.Relay.Console/Program.cs`:
- Around line 106-110: The configuration builder currently only adds environment
variables with the "RESGRID__RELAY__" prefix so legacy RELAY_* env vars are
ignored; update the ConfigurationBuilder that produces the configuration
variable to also call AddEnvironmentVariables("RELAY_") before the RESGRID call
so existing RELAY_* variables are picked up but are overridden by
RESGRID__RELAY__ when present; locate the ConfigurationBuilder block in
Program.cs (the variable named configuration) and add the legacy
AddEnvironmentVariables("RELAY_") call immediately before the existing
AddEnvironmentVariables("RESGRID__RELAY__") call.
- Around line 151-160: When SMTP mode is selected add a startup validation that
if options.Smtp.RedisCache.Enabled is true but
options.Smtp.RedisCache.ConnectionString (or equivalent) is null/empty, you
should add an error to errors (same collection used for domain validation) and
prevent startup; specifically update the SMTP validation block around
options.Mode == "smtp" to check options.Smtp.RedisCache.Enabled and
string.IsNullOrWhiteSpace(options.Smtp.RedisCache.ConnectionString) and push a
clear message like "Redis cache enabled but
RESGRID__RELAY__Smtp__RedisCache__ConnectionString is not set" so
RedisDispatchLookupCache won't repeatedly attempt ConnectAsync at runtime.

In `@Resgrid.Audio.Relay.Console/Smtp/RedisDispatchLookupCache.cs`:
- Around line 36-43: Concurrent callers of GetDatabaseAsync can race past the
_db != null check and each call ConnectionMultiplexer.ConnectAsync, leaking
sockets; serialize connection creation by introducing an async lock (e.g., a
private SemaphoreSlim or AsyncLock) and use double-checked locking inside
GetDatabaseAsync: if _db != null return it, otherwise await the lock, check _db
again, then call ConnectionMultiplexer.ConnectAsync(_options.ConnectionString)
and set _redis and _db only once (and finally release the lock); reference the
GetDatabaseAsync method and the fields _db, _redis,
ConnectionMultiplexer.ConnectAsync and _options.ConnectionString when making
this change.

In `@Resgrid.Audio.Relay.Console/Smtp/SmtpDispatchAddressParser.cs`:
- Around line 42-48: The loop that adds parsed recipients collapses entries by
dispatchCode.Code only and stores a single result.DepartmentId, causing
cross-department/Type collisions; update the logic in the block that calls
TryParse (and mutates result.DispatchCodes and result.DepartmentId) to enforce
uniqueness on the tuple (departmentId, dispatchCode.Type, dispatchCode.Code)
instead of Code alone, and if result.DepartmentId is already set and a new
parsed departmentId differs, reject the input (or return an error) when only a
single department is allowed. Locate TryParse, the local variables dispatchCode
and departmentId, and the places writing result.DispatchCodes and
result.DepartmentId to implement the tuple-based comparison and the
mixed-department rejection.

In `@Resgrid.Audio.Relay.Console/Smtp/SmtpRelayInfrastructure.cs`:
- Around line 187-198: The current branches that check
dispatchResult.HasGroupMessageTargets and
dispatchResult.HasDistributionListTargets call
_telemetry.MessageProcessingStarted which later conflicts with
_telemetry.UnroutableMessage when there are no call targets; change these to
emit a dedicated unsupported-target signal (e.g., add/invoke
_telemetry.UnsupportedTarget(context, messageSummary) or similar) instead of
_telemetry.MessageProcessingStarted, or alternatively defer the single
_telemetry.MessageProcessingStarted call until after you confirm
dispatchResult.HasCallTargets is true; update references to
dispatchResult.HasGroupMessageTargets,
dispatchResult.HasDistributionListTargets, _telemetry.MessageProcessingStarted,
_telemetry.UnroutableMessage, HasCallTargets, messageSummary and context
accordingly.

---

Outside diff comments:
In `@Providers/Resgrid.Providers.ApiClient/V4/ResgridApiClientOptions.cs`:
- Around line 74-100: The current validation in ResgridApiClientOptions always
enforces ClientId and ClientSecret even when GrantType ==
ResgridAuthGrantType.SystemApiKey; update the validator so that the checks for
ClientId and ClientSecret are skipped when GrantType is SystemApiKey (aligning
with ResgridV4ApiClient behavior), and ensure Program.ValidateOptions is changed
similarly so both validators allow configurations that use SystemApiKey without
requiring OAuth client credentials.

---

Nitpick comments:
In `@Providers/Resgrid.Providers.ApiClient/V4/DispatchListBuilder.cs`:
- Around line 18-39: The enum explicit values for DistributionList, Group, and
GroupMessage in DispatchListBuilder.cs do not match their XML docs (docs claim
DistributionList=2, Group=3, GroupMessage=4) which causes misclassification;
update the enum numeric assignments so DistributionList = 2, Group = 3,
GroupMessage = 4 (or alternatively remove the hard-coded numeric values and
adjust the XML comments to not claim specific pipeline IDs) and ensure the enum
declarations for Group, GroupMessage, and DistributionList reflect the corrected
mapping to keep code and docs consistent.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7cbbbc46-1fa8-4b46-be06-e68cfa770a60

📥 Commits

Reviewing files that changed from the base of the PR and between bce535a and a436118.

📒 Files selected for processing (22)
  • Dockerfile
  • Providers/Resgrid.Providers.ApiClient/V4/CallsApi.cs
  • Providers/Resgrid.Providers.ApiClient/V4/DispatchListBuilder.cs
  • Providers/Resgrid.Providers.ApiClient/V4/LookupsApi.cs
  • Providers/Resgrid.Providers.ApiClient/V4/Models/CallModels.cs
  • Providers/Resgrid.Providers.ApiClient/V4/Models/LookupModels.cs
  • Providers/Resgrid.Providers.ApiClient/V4/ResgridApiClientOptions.cs
  • Providers/Resgrid.Providers.ApiClient/V4/ResgridV4ApiClient.cs
  • Resgrid.Audio.Relay.Console/Configuration/RelayHostOptions.cs
  • Resgrid.Audio.Relay.Console/Program.cs
  • Resgrid.Audio.Relay.Console/Resgrid.Audio.Relay.Console.csproj
  • Resgrid.Audio.Relay.Console/Smtp/CachedLookupsService.cs
  • Resgrid.Audio.Relay.Console/Smtp/IDispatchLookupCache.cs
  • Resgrid.Audio.Relay.Console/Smtp/NullDispatchLookupCache.cs
  • Resgrid.Audio.Relay.Console/Smtp/RedisDispatchLookupCache.cs
  • Resgrid.Audio.Relay.Console/Smtp/SmtpDispatchAddressParser.cs
  • Resgrid.Audio.Relay.Console/Smtp/SmtpRelayInfrastructure.cs
  • Resgrid.Audio.Relay.Console/Smtp/SmtpTelemetry.cs
  • Resgrid.Audio.Relay.Console/appsettings.json
  • Resgrid.Audio.Tests/DispatchListBuilderTests.cs
  • Resgrid.Audio.Tests/SmtpDispatchAddressParserTests.cs
  • docker-entrypoint.sh

Comment thread Dockerfile Outdated
Comment thread Providers/Resgrid.Providers.ApiClient/V4/DispatchListBuilder.cs
Comment on lines 106 to 110
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: true)
.AddEnvironmentVariables("RELAY_")
.AddEnvironmentVariables("RESGRID__RELAY__")
.Build();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the legacy RELAY_ binding during the migration.

This drops the prefix the live worker has been using, so existing deployments that still inject RELAY_* will silently fall back to defaults or fail validation. Bind both prefixes and let RESGRID__RELAY__* win while configs migrate.

Suggested fix
 			var configuration = new ConfigurationBuilder()
 				.SetBasePath(AppContext.BaseDirectory)
 				.AddJsonFile("appsettings.json", optional: true)
+				.AddEnvironmentVariables("RELAY_")
 				.AddEnvironmentVariables("RESGRID__RELAY__")
 				.Build();

Based on learnings: Program.cs in Resgrid.Audio.Relay.Console is the live worker entrypoint that selects smtp or audio mode, loads appsettings.json plus RELAY_ environment variables into RelayHostOptions, and resolves relative paths from AppContext.BaseDirectory.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resgrid.Audio.Relay.Console/Program.cs` around lines 106 - 110, The
configuration builder currently only adds environment variables with the
"RESGRID__RELAY__" prefix so legacy RELAY_* env vars are ignored; update the
ConfigurationBuilder that produces the configuration variable to also call
AddEnvironmentVariables("RELAY_") before the RESGRID call so existing RELAY_*
variables are picked up but are overridden by RESGRID__RELAY__ when present;
locate the ConfigurationBuilder block in Program.cs (the variable named
configuration) and add the legacy AddEnvironmentVariables("RELAY_") call
immediately before the existing AddEnvironmentVariables("RESGRID__RELAY__")
call.

Comment thread Resgrid.Audio.Relay.Console/Program.cs
Comment thread Resgrid.Audio.Relay.Console/Smtp/RedisDispatchLookupCache.cs Outdated
Comment thread Resgrid.Audio.Relay.Console/Smtp/SmtpDispatchAddressParser.cs Outdated
Comment thread Resgrid.Audio.Relay.Console/Smtp/SmtpRelayInfrastructure.cs
@ucswift
Copy link
Copy Markdown
Member Author

ucswift commented Apr 30, 2026

Approve

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

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 3f0fb8a into master May 1, 2026
8 checks passed
@ucswift ucswift deployed to BuildEnv May 1, 2026 05:48 — with GitHub Actions Active
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.

1 participant