.NET Environment System Cleanup¶
The .NET services have accumulated configuration complexity and inconsistencies that should be addressed in a dedicated cleanup effort.
1. Unify environment resolution¶
Problem: The services use a custom ActiveEnvironment config key (read from appsettings.json and overridden via --ActiveEnvironment=<env> command-line arg) instead of the standard ASPNETCORE_ENVIRONMENT variable. This is confusing — developers expect ASPNETCORE_ENVIRONMENT to work, but it's silently ignored because HostExtensions.GetEnvironmentName() reads ActiveEnvironment from its own config pipeline.
Current behaviour:
- GetEnvironmentName() in HostExtensions.cs builds a separate ConfigurationBuilder reading appsettings.json + SYRF: env vars + command-line args
- It reads the ActiveEnvironment key and calls UseEnvironment() to override the ASP.NET Core environment
- ASPNETCORE_ENVIRONMENT has no effect
Desired state: Align with the standard ASP.NET Core convention. Either:
- Use ASPNETCORE_ENVIRONMENT directly and remove ActiveEnvironment entirely
- Or make ActiveEnvironment a documented alias that falls back to ASPNETCORE_ENVIRONMENT if not set
Impact: All services (API, PM, Quartz) use the shared HostExtensions.cs, so the fix is centralised.
2. Environment-specific CORS allowed origins¶
Problem: Localhost origins are hardcoded in every service's CORS policy regardless of environment:
.WithOrigins(uiUrl, "https://localhost:4200", "http://localhost:4200",
"https://local-syrf.org.uk:4200", "https://local-syrf.org.uk:4300")
This is present in API (Program.cs:201), PM (Program.cs:235), and Quartz (QuartzServiceCollectionExtensions.cs:114).
While not actively exploitable (an attacker would need local code execution on port 4200), it's unnecessary attack surface in production.
Desired state: Localhost and local development origins should only be included in Development and E2ETest environments. Production and Staging should only allow the real UI domain.
Approach: Read allowed origins from appsettings.{Environment}.json rather than hardcoding. Each environment config specifies its own allowed origins list.
3. User secrets loading¶
Problem (now partially fixed): User secrets were previously loaded unconditionally in all environments, meaning local developer credentials could override E2ETest, Staging, or Production config. This has been fixed in the current branch (guarded behind IsDevelopment() checks), but should be verified as part of any environment cleanup.
Status: Fixed in HostExtensions.cs — three call sites now guard AddUserSecrets behind environment checks.
4. Launch profile vs command-line argument conflicts¶
Problem: launchSettings.json sets SYRF__Urls and applicationUrl which override --urls passed on the command line. This causes port conflicts when running multiple services locally (e.g. API binds to 8081 instead of the requested 8080).
Workaround: Use --no-launch-profile when running outside of IDE launch profiles.
Desired state: Consider whether launchSettings.json should set SYRF__Urls at all, or whether URL binding should come exclusively from environment-specific config or command-line arguments.
5. Duplicated CORS configuration¶
Problem: The CORS policy setup is copy-pasted across API, PM, and Quartz Program.cs files with slight variations. This makes it easy for configurations to drift and harder to audit.
Desired state: Centralise CORS configuration in the shared WebHostConfig.Common library, reading allowed origins from configuration. Each service would call a single method rather than duplicating the policy builder.
6. Elastic APM environment reporting¶
Problem: The Elastic APM environment field is derived via GetGitVersionAndRuntimeEnvironment() which has its own config reading path. In the logs, this can show development even when ActiveEnvironment=E2ETest is correctly set, due to ordering of config sources.
Desired state: APM environment should consistently reflect the active environment, derived from a single authoritative source.
Scope¶
All items are in src/libs/webhostconfig/SyRF.WebHostConfig.Common/ and the three service Program.cs files. No database or deployment changes required.