save checkpoint
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
# Configurable Route Table - Configuration Model and Validation
|
||||
|
||||
## Module
|
||||
Gateway
|
||||
|
||||
## Status
|
||||
VERIFIED
|
||||
|
||||
## Description
|
||||
The Gateway supports a configurable route table via `GatewayOptions.Routes` (`List<StellaOpsRoute>`). Each route is defined by a `StellaOpsRouteType` enum (Microservice, ReverseProxy, StaticFiles, StaticFile, WebSocket, NotFoundPage, ServerErrorPage), a `Path`, an optional `IsRegex` flag, a `TranslatesTo` target, and optional `Headers` dictionary. The `GatewayOptionsValidator` validates all routes with type-specific rules: ReverseProxy requires valid HTTP(S) URL, WebSocket requires ws:///wss:// URL, StaticFiles/StaticFile/NotFoundPage/ServerErrorPage require non-empty file/directory paths, all routes require non-empty Path, and regex paths must be valid regex patterns.
|
||||
|
||||
## Implementation Details
|
||||
- **Modules**: `src/Router/__Libraries/StellaOps.Router.Gateway/`, `src/Router/StellaOps.Gateway.WebService/`
|
||||
- **Key Classes**:
|
||||
- `StellaOpsRoute` (`src/Router/__Libraries/StellaOps.Router.Gateway/Configuration/StellaOpsRoute.cs`) - Route model class with `StellaOpsRouteType` enum (7 values)
|
||||
- `GatewayOptions` (`src/Router/StellaOps.Gateway.WebService/Configuration/GatewayOptions.cs`) - `Routes` property (`List<StellaOpsRoute>`)
|
||||
- `GatewayOptionsValidator` (`src/Router/StellaOps.Gateway.WebService/Configuration/GatewayOptionsValidator.cs`) - Type-specific validation rules for all 7 route types
|
||||
- **Tests**:
|
||||
- `GatewayOptionsValidatorTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Configuration/GatewayOptionsValidatorTests.cs`) - 11 route validation tests
|
||||
- `StellaOpsRouteResolverTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Routing/StellaOpsRouteResolverTests.cs`) - 9 resolver unit tests
|
||||
|
||||
## E2E Test Plan
|
||||
- [ ] Validate that a ReverseProxy route with invalid URL fails validation
|
||||
- [ ] Validate that a WebSocket route with non-ws:// URL fails validation
|
||||
- [ ] Validate that a StaticFiles route with empty TranslatesTo fails validation
|
||||
- [ ] Validate that a route with empty Path fails validation
|
||||
- [ ] Validate that a route with IsRegex=true and invalid regex fails validation
|
||||
- [ ] Validate that a properly configured route table with all 7 types passes validation
|
||||
- [ ] Gateway starts successfully with a valid route table configuration
|
||||
|
||||
## Verification
|
||||
- **Run ID**: run-001
|
||||
- **Date**: 2026-02-12
|
||||
- **Method**: Tier 0 source verification + Tier 1 build/code review (224/224 tests pass) + Tier 2a live HTTP API testing
|
||||
- **Build**: PASS (0 errors, 0 warnings)
|
||||
- **Tests**: PASS (224/224 Gateway tests pass)
|
||||
- **Tier 2a Evidence**: `docs/qa/feature-checks/runs/gateway/configurable-route-table-configuration-model/run-001/tier2-api-check.json`
|
||||
- **Verdict**: PASS
|
||||
@@ -0,0 +1,36 @@
|
||||
# Configurable Route Table - Error Page Fallback (404/500)
|
||||
|
||||
## Module
|
||||
Gateway
|
||||
|
||||
## Status
|
||||
VERIFIED
|
||||
|
||||
## Description
|
||||
The Gateway supports `NotFoundPage` and `ServerErrorPage` route types that serve custom HTML error pages for 404 and 500+ responses respectively. Configured via `StellaOpsRoute` with `Type = NotFoundPage` or `Type = ServerErrorPage`, `TranslatesTo` = path to an HTML file on disk. When any route in the pipeline produces a 404 or 500+ response with an empty body, the `ErrorPageFallbackMiddleware` intercepts and serves the configured HTML page. Includes a fast-path optimization that skips response body buffering entirely when no error pages are configured. Falls back to a JSON error response when the configured error page file is missing.
|
||||
|
||||
## Implementation Details
|
||||
- **Modules**: `src/Router/__Libraries/StellaOps.Router.Gateway/`, `src/Router/StellaOps.Gateway.WebService/`
|
||||
- **Key Classes**:
|
||||
- `StellaOpsRoute` (`src/Router/__Libraries/StellaOps.Router.Gateway/Configuration/StellaOpsRoute.cs`) - Route model with `StellaOpsRouteType.NotFoundPage` and `StellaOpsRouteType.ServerErrorPage`
|
||||
- `ErrorPageFallbackMiddleware` (`src/Router/StellaOps.Gateway.WebService/Middleware/ErrorPageFallbackMiddleware.cs`) - Intercepts 404/500 responses, serves configured HTML pages, fast-path for no-error-page config
|
||||
- `GatewayOptionsValidator` (`src/Router/StellaOps.Gateway.WebService/Configuration/GatewayOptionsValidator.cs`) - Validates error page routes have non-empty TranslatesTo file paths
|
||||
- `Program.cs` (`src/Router/StellaOps.Gateway.WebService/Program.cs`) - Registers error routes in DI and `ErrorPageFallbackMiddleware` at end of pipeline
|
||||
- **Tests**:
|
||||
- `RouteTableIntegrationTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Integration/RouteTableIntegrationTests.cs`) - Error page behavior verified through route resolution tests (unmatched paths return 404)
|
||||
|
||||
## E2E Test Plan
|
||||
- [ ] Unmatched route returns 404 with custom HTML page: `GET /unmatched/path` returns 404 with `Content-Type: text/html` and custom page content
|
||||
- [ ] 404 response status code is preserved: response status is 404 (not 200)
|
||||
- [ ] 500 error page: trigger a 500 response and verify custom HTML page is served with `Content-Type: text/html`
|
||||
- [ ] Fast-path: when no error pages configured, responses pass through without buffering overhead
|
||||
- [ ] JSON fallback: when error page file is missing on disk, returns JSON error `{"error":"not_found","status":404}`
|
||||
|
||||
## Verification
|
||||
- **Run ID**: run-001
|
||||
- **Date**: 2026-02-12
|
||||
- **Method**: Tier 0 source verification + Tier 1 build/code review (224/224 tests pass) + Tier 2a live HTTP API testing
|
||||
- **Build**: PASS (0 errors, 0 warnings)
|
||||
- **Tests**: PASS (224/224 Gateway tests pass)
|
||||
- **Tier 2a Evidence**: `docs/qa/feature-checks/runs/gateway/configurable-route-table-error-page-fallback/run-001/tier2-api-check.json`
|
||||
- **Verdict**: PASS
|
||||
@@ -0,0 +1,39 @@
|
||||
# Configurable Route Table - Reverse Proxy
|
||||
|
||||
## Module
|
||||
Gateway
|
||||
|
||||
## Status
|
||||
VERIFIED
|
||||
|
||||
## Description
|
||||
The Gateway supports a `ReverseProxy` route type that forwards HTTP requests to an upstream service. Configured via `StellaOpsRoute` with `Type = ReverseProxy`, `Path` = URL prefix, `TranslatesTo` = upstream base URL. Features: prefix stripping (for non-regex routes), header forwarding (excluding hop-by-hop), upstream status code passthrough, custom header injection via `Headers` dictionary, regex-based path matching (`IsRegex = true`), timeout handling (returns 504), and connection error handling (returns 502).
|
||||
|
||||
## Implementation Details
|
||||
- **Modules**: `src/Router/__Libraries/StellaOps.Router.Gateway/`, `src/Router/StellaOps.Gateway.WebService/`
|
||||
- **Key Classes**:
|
||||
- `StellaOpsRoute` (`src/Router/__Libraries/StellaOps.Router.Gateway/Configuration/StellaOpsRoute.cs`) - Route model with `StellaOpsRouteType.ReverseProxy`
|
||||
- `StellaOpsRouteResolver` (`src/Router/StellaOps.Gateway.WebService/Routing/StellaOpsRouteResolver.cs`) - Supports both prefix and regex matching for proxy routes
|
||||
- `RouteDispatchMiddleware` (`src/Router/StellaOps.Gateway.WebService/Middleware/RouteDispatchMiddleware.cs`) - `HandleReverseProxy` method using `IHttpClientFactory`, strips prefix, forwards headers, streams response
|
||||
- `GatewayOptionsValidator` (`src/Router/StellaOps.Gateway.WebService/Configuration/GatewayOptionsValidator.cs`) - Validates ReverseProxy route has valid HTTP(S) URL in TranslatesTo
|
||||
- **Tests**:
|
||||
- `RouteTableIntegrationTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Integration/RouteTableIntegrationTests.cs`) - 7 ReverseProxy integration tests
|
||||
- `GatewayOptionsValidatorTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Configuration/GatewayOptionsValidatorTests.cs`) - ReverseProxy URL validation tests
|
||||
|
||||
## E2E Test Plan
|
||||
- [ ] Forward request to upstream: `GET /proxy/echo` returns proxied response from upstream with 200
|
||||
- [ ] Strip path prefix: `GET /proxy/sub/path` forwards as `/sub/path` to upstream
|
||||
- [ ] Forward request headers: custom headers (e.g., `X-Test-Header`) are forwarded to upstream
|
||||
- [ ] Pass through upstream status codes: 201, 400, 500 are returned as-is
|
||||
- [ ] Inject configured headers: route with `Headers["X-Custom-Route"] = "injected-value"` injects that header into upstream request
|
||||
- [ ] Regex path matching: route with `IsRegex = true` and pattern `^/api/v[0-9]+/.*` matches `GET /api/v2/data`
|
||||
- [ ] Timeout handling: upstream timeout returns 504 Gateway Timeout
|
||||
|
||||
## Verification
|
||||
- **Run ID**: run-001
|
||||
- **Date**: 2026-02-12
|
||||
- **Method**: Tier 0 source verification + Tier 1 build/code review (224/224 tests pass) + Tier 2a live HTTP API testing
|
||||
- **Build**: PASS (0 errors, 0 warnings)
|
||||
- **Tests**: PASS (224/224 Gateway tests pass)
|
||||
- **Tier 2a Evidence**: `docs/qa/feature-checks/runs/gateway/configurable-route-table-reverse-proxy/run-001/tier2-api-check.json`
|
||||
- **Verdict**: PASS
|
||||
@@ -0,0 +1,37 @@
|
||||
# Configurable Route Table - Route Resolution Engine
|
||||
|
||||
## Module
|
||||
Gateway
|
||||
|
||||
## Status
|
||||
VERIFIED
|
||||
|
||||
## Description
|
||||
The Gateway includes a `StellaOpsRouteResolver` that maps incoming HTTP request paths to configured `StellaOpsRoute` entries. Uses first-match-wins ordering. Supports both prefix matching (case-insensitive `PathString.StartsWith`) and compiled regex matching (`IsRegex = true`). Excludes `NotFoundPage` and `ServerErrorPage` routes from path resolution (these are handled separately by `ErrorPageFallbackMiddleware`). Returns `null` for no match, allowing fallthrough to the existing Microservice pipeline.
|
||||
|
||||
## Implementation Details
|
||||
- **Modules**: `src/Router/StellaOps.Gateway.WebService/`
|
||||
- **Key Classes**:
|
||||
- `StellaOpsRouteResolver` (`src/Router/StellaOps.Gateway.WebService/Routing/StellaOpsRouteResolver.cs`) - First-match-wins resolver with prefix and regex support
|
||||
- `RouteDispatchMiddleware` (`src/Router/StellaOps.Gateway.WebService/Middleware/RouteDispatchMiddleware.cs`) - Calls resolver, dispatches to handler based on route type
|
||||
- `Program.cs` (`src/Router/StellaOps.Gateway.WebService/Program.cs`) - Registers `StellaOpsRouteResolver` as singleton in DI
|
||||
- **Tests**:
|
||||
- `StellaOpsRouteResolverTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Routing/StellaOpsRouteResolverTests.cs`) - 9 unit tests (exact match, prefix, regex, no match, first-match-wins, excluded error types, case-insensitive, empty)
|
||||
- `RouteTableIntegrationTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Integration/RouteTableIntegrationTests.cs`) - 2 route resolution integration tests
|
||||
|
||||
## E2E Test Plan
|
||||
- [ ] Exact path match: `GET /favicon.ico` resolves to StaticFile route (returns file content)
|
||||
- [ ] Prefix match: `GET /app/index.html` resolves to StaticFiles route (serves directory file)
|
||||
- [ ] Regex match: `GET /api/v2/data` resolves to ReverseProxy route with pattern `^/api/v[0-9]+/.*`
|
||||
- [ ] No match fallthrough: `GET /unmatched/path` returns 404 (falls through to Microservice pipeline)
|
||||
- [ ] First-match-wins: when multiple routes could match, first configured route takes precedence
|
||||
- [ ] Case-insensitive: `GET /APP/index.html` resolves to `/app` StaticFiles route
|
||||
|
||||
## Verification
|
||||
- **Run ID**: run-001
|
||||
- **Date**: 2026-02-12
|
||||
- **Method**: Tier 0 source verification + Tier 1 build/code review (224/224 tests pass) + Tier 2a live HTTP API testing
|
||||
- **Build**: PASS (0 errors, 0 warnings)
|
||||
- **Tests**: PASS (224/224 Gateway tests pass)
|
||||
- **Tier 2a Evidence**: `docs/qa/feature-checks/runs/gateway/configurable-route-table-route-resolver/run-001/tier2-api-check.json`
|
||||
- **Verdict**: PASS
|
||||
@@ -0,0 +1,35 @@
|
||||
# Configurable Route Table - Static File Serving
|
||||
|
||||
## Module
|
||||
Gateway
|
||||
|
||||
## Status
|
||||
VERIFIED
|
||||
|
||||
## Description
|
||||
The Gateway supports a `StaticFile` route type that serves a single specific file at an exact path. Configured via `StellaOpsRoute` with `Type = StaticFile`, `Path` = exact URL path (e.g., `/favicon.ico`), `TranslatesTo` = physical file path. Sub-paths are rejected (e.g., `/favicon.ico/extra` returns 404). The file is served with the correct MIME type inferred from the file extension.
|
||||
|
||||
## Implementation Details
|
||||
- **Modules**: `src/Router/__Libraries/StellaOps.Router.Gateway/`, `src/Router/StellaOps.Gateway.WebService/`
|
||||
- **Key Classes**:
|
||||
- `StellaOpsRoute` (`src/Router/__Libraries/StellaOps.Router.Gateway/Configuration/StellaOpsRoute.cs`) - Route model with `StellaOpsRouteType.StaticFile`
|
||||
- `StellaOpsRouteResolver` (`src/Router/StellaOps.Gateway.WebService/Routing/StellaOpsRouteResolver.cs`) - Resolves exact path match for StaticFile routes
|
||||
- `RouteDispatchMiddleware` (`src/Router/StellaOps.Gateway.WebService/Middleware/RouteDispatchMiddleware.cs`) - `HandleStaticFile` method serves exact file with MIME detection
|
||||
- `GatewayOptionsValidator` (`src/Router/StellaOps.Gateway.WebService/Configuration/GatewayOptionsValidator.cs`) - Validates StaticFile route has non-empty TranslatesTo file path
|
||||
- **Tests**:
|
||||
- `RouteTableIntegrationTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Integration/RouteTableIntegrationTests.cs`) - 3 StaticFile integration tests
|
||||
- `GatewayOptionsValidatorTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Configuration/GatewayOptionsValidatorTests.cs`) - StaticFile validation tests
|
||||
|
||||
## E2E Test Plan
|
||||
- [ ] Serve a single file: `GET /favicon.ico` returns file content with 200
|
||||
- [ ] Reject sub-paths: `GET /favicon.ico/extra` returns 404
|
||||
- [ ] Correct Content-Type: `GET /favicon.ico` returns `Content-Type: image/x-icon`
|
||||
|
||||
## Verification
|
||||
- **Run ID**: run-001
|
||||
- **Date**: 2026-02-12
|
||||
- **Method**: Tier 0 source verification + Tier 1 build/code review (224/224 tests pass) + Tier 2a live HTTP API testing
|
||||
- **Build**: PASS (0 errors, 0 warnings)
|
||||
- **Tests**: PASS (224/224 Gateway tests pass)
|
||||
- **Tier 2a Evidence**: `docs/qa/feature-checks/runs/gateway/configurable-route-table-static-file-serving/run-001/tier2-api-check.json`
|
||||
- **Verdict**: PASS
|
||||
@@ -0,0 +1,38 @@
|
||||
# Configurable Route Table - Static Files Serving
|
||||
|
||||
## Module
|
||||
Gateway
|
||||
|
||||
## Status
|
||||
VERIFIED
|
||||
|
||||
## Description
|
||||
The Gateway supports a `StaticFiles` route type that serves directory contents mapped to a URL prefix. Configured via `StellaOpsRoute` with `Type = StaticFiles`, `Path` = URL prefix, `TranslatesTo` = physical directory path. Supports SPA fallback (serving `index.html` for extensionless paths) when the route's `Headers["x-spa-fallback"]` is set to `"true"`. Files are served with correct MIME types via `FileExtensionContentTypeProvider`. Multiple StaticFiles routes can coexist with isolated path scopes.
|
||||
|
||||
## Implementation Details
|
||||
- **Modules**: `src/Router/__Libraries/StellaOps.Router.Gateway/`, `src/Router/StellaOps.Gateway.WebService/`
|
||||
- **Key Classes**:
|
||||
- `StellaOpsRoute` (`src/Router/__Libraries/StellaOps.Router.Gateway/Configuration/StellaOpsRoute.cs`) - Route model with `StellaOpsRouteType.StaticFiles`
|
||||
- `StellaOpsRouteResolver` (`src/Router/StellaOps.Gateway.WebService/Routing/StellaOpsRouteResolver.cs`) - First-match-wins route resolution engine
|
||||
- `RouteDispatchMiddleware` (`src/Router/StellaOps.Gateway.WebService/Middleware/RouteDispatchMiddleware.cs`) - `HandleStaticFiles` method uses `PhysicalFileProvider` and `FileExtensionContentTypeProvider`
|
||||
- `GatewayOptionsValidator` (`src/Router/StellaOps.Gateway.WebService/Configuration/GatewayOptionsValidator.cs`) - Validates StaticFiles route has non-empty TranslatesTo directory path
|
||||
- **Tests**:
|
||||
- `RouteTableIntegrationTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Integration/RouteTableIntegrationTests.cs`) - 8 StaticFiles integration tests
|
||||
- `GatewayOptionsValidatorTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Configuration/GatewayOptionsValidatorTests.cs`) - StaticFiles validation tests
|
||||
|
||||
## E2E Test Plan
|
||||
- [ ] Serve a file from a mapped directory: `GET /app/index.html` returns HTML content with 200 and `Content-Type: text/html`
|
||||
- [ ] Serve a nested file: `GET /app/assets/style.css` returns CSS content with 200 and `Content-Type: text/css`
|
||||
- [ ] Return 404 for missing file: `GET /app/missing.txt` returns 404
|
||||
- [ ] Verify MIME types: `.html` -> `text/html`, `.css` -> `text/css`, `.js` -> `application/javascript`, `.json` -> `application/json`
|
||||
- [ ] SPA fallback: `GET /app/some/route` (extensionless) returns `index.html` when `x-spa-fallback=true`
|
||||
- [ ] Multiple mappings isolation: `/app/` and `/docs/` serve from different directories without interference
|
||||
|
||||
## Verification
|
||||
- **Run ID**: run-001
|
||||
- **Date**: 2026-02-12
|
||||
- **Method**: Tier 0 source verification + Tier 1 build/code review (224/224 tests pass) + Tier 2a live HTTP API testing
|
||||
- **Build**: PASS (0 errors, 0 warnings)
|
||||
- **Tests**: PASS (224/224 Gateway tests pass)
|
||||
- **Tier 2a Evidence**: `docs/qa/feature-checks/runs/gateway/configurable-route-table-static-files-serving/run-001/tier2-api-check.json`
|
||||
- **Verdict**: PASS
|
||||
@@ -0,0 +1,37 @@
|
||||
# Configurable Route Table - WebSocket Proxy
|
||||
|
||||
## Module
|
||||
Gateway
|
||||
|
||||
## Status
|
||||
VERIFIED
|
||||
|
||||
## Description
|
||||
The Gateway supports a `WebSocket` route type that accepts WebSocket upgrade requests and proxies them bidirectionally to an upstream WebSocket server. Configured via `StellaOpsRoute` with `Type = WebSocket`, `Path` = URL prefix, `TranslatesTo` = upstream WebSocket URL (ws:// or wss://). The middleware accepts the client WebSocket, opens a `ClientWebSocket` connection to the upstream, and pumps messages in both directions. Supports text messages, binary messages, and close frame propagation.
|
||||
|
||||
## Implementation Details
|
||||
- **Modules**: `src/Router/__Libraries/StellaOps.Router.Gateway/`, `src/Router/StellaOps.Gateway.WebService/`
|
||||
- **Key Classes**:
|
||||
- `StellaOpsRoute` (`src/Router/__Libraries/StellaOps.Router.Gateway/Configuration/StellaOpsRoute.cs`) - Route model with `StellaOpsRouteType.WebSocket`
|
||||
- `StellaOpsRouteResolver` (`src/Router/StellaOps.Gateway.WebService/Routing/StellaOpsRouteResolver.cs`) - Resolves WebSocket routes by path prefix
|
||||
- `RouteDispatchMiddleware` (`src/Router/StellaOps.Gateway.WebService/Middleware/RouteDispatchMiddleware.cs`) - `HandleWebSocket` method: accepts client WS, connects upstream `ClientWebSocket`, bidirectional pump loop
|
||||
- `GatewayOptionsValidator` (`src/Router/StellaOps.Gateway.WebService/Configuration/GatewayOptionsValidator.cs`) - Validates WebSocket route has valid ws:// or wss:// URL in TranslatesTo
|
||||
- `Program.cs` (`src/Router/StellaOps.Gateway.WebService/Program.cs`) - Registers `app.UseWebSockets()` in the pipeline
|
||||
- **Tests**:
|
||||
- `RouteTableIntegrationTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Integration/RouteTableIntegrationTests.cs`) - 4 WebSocket integration tests
|
||||
- `GatewayOptionsValidatorTests` (`src/Router/__Tests/StellaOps.Gateway.WebService.Tests/Configuration/GatewayOptionsValidatorTests.cs`) - WebSocket URL validation tests
|
||||
|
||||
## E2E Test Plan
|
||||
- [ ] WebSocket upgrade succeeds: connect to `ws://host/ws/echo` and verify state is Open
|
||||
- [ ] Text message round-trip: send "Hello WebSocket" text message, receive same text echo back
|
||||
- [ ] Binary message round-trip: send binary payload `[0x01, 0x02, 0x03, 0xFF]`, receive identical binary echo
|
||||
- [ ] Close handshake: send close frame with NormalClosure, verify connection state becomes Closed
|
||||
|
||||
## Verification
|
||||
- **Run ID**: run-001
|
||||
- **Date**: 2026-02-12
|
||||
- **Method**: Tier 0 source verification + Tier 1 build/code review (224/224 tests pass) + Tier 2a live HTTP API testing
|
||||
- **Build**: PASS (0 errors, 0 warnings)
|
||||
- **Tests**: PASS (224/224 Gateway tests pass)
|
||||
- **Tier 2a Evidence**: `docs/qa/feature-checks/runs/gateway/configurable-route-table-websocket-proxy/run-001/tier2-api-check.json`
|
||||
- **Verdict**: PASS
|
||||
Reference in New Issue
Block a user