Repair router frontdoor convergence and live route contracts

This commit is contained in:
master
2026-03-09 19:09:19 +02:00
parent 49d1c57597
commit bf937c9395
25 changed files with 740 additions and 61 deletions

View File

@@ -18,6 +18,7 @@ Rollout policy: `docs/operations/multi-tenant-rollout-and-compatibility.md`
- HTTP is not used for internal microservice-to-gateway traffic
- Request/response bodies are opaque to the router (raw bytes/streams)
- Forwarded HTTP headers remain case-insensitive across Router frame transport and ASP.NET bridge dispatch; lowercase HTTP/2 names such as `content-type` must be preserved for JSON-bound endpoints, and the ASP.NET bridge must mark POST/PUT/PATCH requests as body-capable so minimal-API JSON binding survives frame dispatch
- Gateway scope authorization evaluates against the resolved per-request scope set from identity expansion (`GatewayContextKeys.Scopes`), so coarse compatibility scopes such as `orch:quota` can satisfy their fine-grained frontdoor equivalents without changing downstream policy names
### Transport Architecture
@@ -106,6 +107,8 @@ Browser → Router Gateway (port 80) → [microservices via binary transport]
The Angular SPA dist is provided by a `console-builder` init container that copies the built files to a shared `console-dist` volume mounted at `/app/wwwroot`.
When the gateway runs in-container, listener binding must honor explicit `ASPNETCORE_URLS` / `ASPNETCORE_HTTP_PORTS` / `ASPNETCORE_HTTPS_PORTS` values from compose. Wildcard hosts (`+`, `*`) are normalized to `0.0.0.0` before Kestrel listeners are created so the declared HTTP frontdoor contract actually comes up.
---
## Service Identity
@@ -177,6 +180,7 @@ public sealed class EndpointDescriptor
- ASP.NET-style route templates
- Parameter segments: `{id}`, `{userId}`
- Extra path segments are consumed only by explicit catch-all parameters (`{**path}`); ordinary terminal parameters must not behave like implicit catch-alls during messaging transport dispatch
- Case sensitivity and trailing slash handling follow ASP.NET conventions
---
@@ -533,6 +537,8 @@ Gateway tracks:
- Derives status from heartbeat recency
- Marks stale instances as Unhealthy
- Uses health in routing decisions
- Messaging transports stay push-first even when backed by notifiable queues; the missed-notification safety-net timeout is derived from the configured heartbeat interval and clamped to a short bounded window instead of falling back to a fixed long poll.
- Gateway degraded and stale transitions are normalized against the messaging heartbeat contract. A gateway may not mark an instance `Degraded` earlier than `2x` the heartbeat interval or `Unhealthy` earlier than `3x` the heartbeat interval, even when looser defaults were configured.
Periodic HELLO re-registration is valid so a microservice can repopulate gateway state after a gateway restart, but it must refresh the existing logical transport connection instead of minting a second one. Gateway routing state also deduplicates by service instance identity (`ServiceName`, `Version`, `InstanceId`, transport) before re-indexing endpoints so repeated HELLO frames cannot accumulate stale route candidates.