Set up repository with legacy .NET Framework 4.8 source (OLD/), new .NET 10 Blazor solution (NEW/), OpenSpec specifications, documentation, and project configuration.
8.2 KiB
Web API and Authentication - Migration Deltas
Purpose
This document specifies requirements ADDED or MODIFIED for the .NET 10 migration of the Web API and authentication layer. These requirements extend the base specification at openspec/specs/web-api-auth/spec.md.
ADDED Requirements
Requirement: Cross-Platform LDAP Support
The system SHALL use System.DirectoryServices.Protocols for LDAP authentication to ensure cross-platform compatibility.
Business Rules
- The system SHALL NOT use
System.DirectoryServices.DirectoryEntryorSystem.DirectoryServices.DirectorySearcher(Windows-only APIs) - The system SHALL use
LdapConnectionfromSystem.DirectoryServices.Protocols - The system SHALL use asynchronous patterns with
Task.Run()for LDAP operations (the LDAP API is synchronous) - The system SHALL dispose
LdapConnectionafter each operation
Scenario: LDAP authentication on Linux
- WHEN the application runs on Linux with LDAP configuration
- THEN the system authenticates successfully using
System.DirectoryServices.Protocols
Requirement: ClosedXML for Excel Operations
The system SHALL use ClosedXML library for Excel file parsing in the File API.
Business Rules
- The system SHALL NOT use EPPlus (commercial license required in v7+)
- The system SHALL use
XLWorkbookfrom ClosedXML for reading uploaded Excel files - The system SHALL use 1-indexed row/column access matching ClosedXML conventions
- The system SHALL handle empty worksheets gracefully using
LastRowUsed()?.RowNumber()
Scenario: Parse Excel upload with ClosedXML
- WHEN a user uploads an Excel file to any file upload endpoint
- THEN the system parses the file using ClosedXML and returns matching data
Requirement: OpenAPI Documentation
The system SHALL provide OpenAPI/Swagger documentation for all API endpoints.
Business Rules
- The system SHALL use Swashbuckle.AspNetCore for OpenAPI generation
- The system SHALL expose Swagger UI at
/swaggerin development mode - The system SHALL document all endpoints with correct HTTP methods and response types
- The system SHALL document authentication requirements for protected endpoints
Scenario: Developer accesses API documentation
- WHEN a developer navigates to
/swaggerin development mode - THEN the system displays interactive API documentation for all endpoints
Requirement: JSON Serialization with System.Text.Json
The system SHALL use System.Text.Json for all JSON serialization.
Business Rules
- The system SHALL NOT use Newtonsoft.Json (legacy)
- The system SHALL use
JsonStringEnumConverterfor enum serialization - The system SHALL configure JSON options via
AddControllers().AddJsonOptions() - The system SHALL return JSON responses (not redirects) for all API errors
Scenario: Enum serialization in API response
- WHEN an API endpoint returns a model with an enum property
- THEN the system serializes the enum as a string (e.g., "Submitted" not 1)
Requirement: IHubContext Dependency Injection
The system SHALL use IHubContext<StatusHub> for publishing SignalR updates from outside the hub.
Business Rules
- The system SHALL NOT use static
GlobalHost.ConnectionManagerpattern (legacy) - The system SHALL inject
IHubContext<StatusHub>into controllers and services - The system SHALL use
Clients.All.SendAsync()for broadcasting - The system SHALL handle SignalR publish failures gracefully (log and continue)
Scenario: Controller publishes search update
- WHEN SearchController creates a new search
- THEN the system uses injected
IHubContext<StatusHub>to broadcast the update
Requirement: Async-First Pattern
The system SHALL use async/await patterns for all I/O operations.
Business Rules
- All controller actions SHALL be async with
CancellationTokenparameter - All service methods SHALL be async with
CancellationTokenparameter - The system SHALL use
IAsyncEnumerablefor streaming scenarios where applicable - The system SHALL propagate
CancellationTokento all downstream async calls
Scenario: Cancellation during long-running operation
- WHEN a client cancels a request during LDAP authentication
- THEN the system throws
OperationCanceledExceptionand stops the operation
Requirement: Structured Logging
The system SHALL use ILogger<T> for structured logging.
Business Rules
- The system SHALL NOT use NLog directly (legacy)
- The system SHALL inject
ILogger<T>into all controllers and services - The system SHALL use structured logging with named parameters:
_logger.LogWarning("Failed to authenticate {Username}", username) - The system SHALL log at appropriate levels (Information, Warning, Error)
Scenario: Failed LDAP authentication logged
- WHEN LDAP authentication fails
- THEN the system logs a warning with structured username and error details
Requirement: Options Pattern Configuration
The system SHALL use IOptions<T> for strongly-typed configuration.
Business Rules
- The system SHALL NOT use
ConfigurationManagerorWebConfigurationManager(legacy) - The system SHALL bind
LdapOptionsfromLdapconfiguration section - The system SHALL bind
AuthOptionsfromAuthconfiguration section - The system SHALL inject
IOptions<T>orIOptionsSnapshot<T>as needed
Scenario: Configuration changes without restart
- WHEN configuration values change in appsettings.json
- THEN the system can use
IOptionsSnapshot<T>to read updated values
MODIFIED Requirements
Requirement: Cookie Authentication Events (Modified)
The system SHALL suppress cookie authentication redirects and return HTTP status codes for Blazor WASM compatibility.
Modified Business Rules
- The system SHALL configure
OnRedirectToLoginto return HTTP 401 instead of redirect - The system SHALL configure
OnRedirectToAccessDeniedto return HTTP 403 instead of redirect - The system SHALL return JSON error responses (not HTML) for authentication failures
Scenario: Unauthenticated API request from Blazor
- WHEN an unauthenticated Blazor WASM client requests a protected endpoint
- THEN the system returns HTTP 401 with JSON error body (no redirect)
Requirement: SignalR Hub Endpoint Path (Modified)
The system SHALL map the StatusHub to the /hubs/status endpoint path.
Modified Business Rules
- The system SHALL map StatusHub to
/hubs/statusendpoint - The system SHALL configure SignalR with default settings (no custom protocols)
Scenario: Client connects to SignalR hub
- WHEN a Blazor WASM client connects to SignalR
- THEN the system accepts connections at
/hubs/status
Requirement: Dependency Injected Memory Cache (Modified)
The system SHALL use DI-injected IMemoryCache for file template caching.
Modified Business Rules
- The system SHALL inject
IMemoryCachevia constructor (notMemoryCache.Default) - The system SHALL use
MemoryCacheEntryOptionswithAbsoluteExpirationRelativeToNow - The system SHALL use
TryGetValue<T>pattern for type-safe cache retrieval
Scenario: File template cached with DI cache
- WHEN a file template is generated
- THEN the system stores it in the injected
IMemoryCachewith 1-minute expiration
Migration Notes
| Legacy Pattern | New Pattern | Rationale |
|---|---|---|
System.DirectoryServices.DirectoryEntry |
System.DirectoryServices.Protocols.LdapConnection |
Cross-platform compatibility |
| EPPlus | ClosedXML | MIT license (EPPlus commercial in v7+) |
| Newtonsoft.Json | System.Text.Json | Built-in, better performance |
GlobalHost.ConnectionManager.GetHubContext<T>() |
IHubContext<T> via DI |
Standard DI pattern, testable |
| NLog | ILogger<T> |
Built-in logging abstraction |
WebConfigurationManager.AppSettings |
IOptions<T> |
Strongly-typed configuration |
MemoryCache.Default |
IMemoryCache via DI |
Standard caching abstraction |
| Login redirect on 401 | HTTP 401 response | Blazor WASM SPA compatibility |