- ApiKeyOptionsValidator (ValidateOnStart on any driver/admin node): a blank or placeholder
Security:ApiKeys:Pepper fails host start instead of rejecting every key after a green boot (R03:2.3).
- JWT is finished and opt-in by key (R03:2.4): with Security:Jwt:SigningKey set, a Bearer scheme
(JwtBearerAuthenticationHandler over JwtTokenService.TryValidate / BuildValidationParameters, fail
closed) accepts the tokens /auth/token mints; the default scheme is a cookie-or-bearer policy scheme
and the fallback policy names it, so /api/* and every RequireAuthorization endpoint take a browser
session OR a machine token. JwtOptions are validated at start (JwtOptionsValidator). Without a key,
/auth/token is not mapped (404, not the former constructor 500) and no bearer scheme exists.
A direct AddJwtBearer needs Microsoft.AspNetCore.Authentication.JwtBearer in
Directory.Packages.props (not this lane's file) — the handler is a drop-in to swap.
- AuthenticationStateAuditActorAccessor is the registered IAuditActorAccessor: the Blazor circuit's
principal first, HttpContext as the fallback (R03:2.5). HttpAuditActorAccessor shares its resolver.
- CookieAuthenticationStateProvider (unregistered, fire-and-forget ping loop) is deleted (R03:1.5/2.5).
- /auth/login logs the LDAP exception at Warning before answering 503 (R03:2.7).
- Admin operations reply with a fixed message + correlation id instead of ex.Message (R03:4.1).
Refs #733
Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT