Problem
eveChannel() authorizers sometimes need to distinguish an authenticated caller whose authorization dependency is not queryable yet from an unauthenticated or forbidden caller.
A concrete case is owner-authorized initial session streaming:
POST /eve/v1/session authenticates and returns a new session ID.
- The client immediately opens
GET /eve/v1/session/:sessionId/stream.
- An application-owned, awaited
session.started projection may not yet have made the session-to-owner mapping queryable.
- The caller is valid, but returning
403 permanently fails the native client. The native stream opener already treats 425 as bounded/retryable.
Today the public AuthFn contract only documents principal/null plus UnauthenticatedError and ForbiddenError. routeAuth internally preserves errors carrying a Response, but application code must rely on that private duck-typed behavior to emit 425.
Proposed invariant
An authenticated route dependency that is provably pending may fail with one public, typed retryable readiness error. Unauthorized callers must continue to receive 401/403. Application code must not copy Eve routes, proxy streams, or implement retry sleeps.
Proposed API
Export a public typed error from eve/channels/auth, name to maintainer preference, for example:
throw new SessionNotReadyError();
The error should own a framework-shaped response:
- HTTP
425 Too Early
cache-control: no-store
- stable machine code such as
session_not_ready
- optional bounded
Retry-After, if desired
Scope
- Public error class and types.
routeAuth tests proving exact response preservation and auth-walk termination.
- Native client coverage confirming 425 retry remains bounded and abort-aware.
- Auth guide documentation and patch changeset.
No new transport or retry implementation is required; the native client already retries 425.
Alternatives considered
Exposing target-session initiator/current auth at route time would be stronger but substantially larger: the current channel session handle exposes only ID, continuation token, and event stream, while session.started does not expose SessionAuthContext. A typed readiness error is the smallest public contract that closes the gap without leaking session auth or adding a durable metadata index.
Consumer
FreshlakeAI/livetaxbot TGL-493/TGL-494. The consumer has adversarial coverage ensuring 425 is returned only for an exact owned, running, unattached reservation; missing, stale, cross-user, cross-chat, or differently attached records remain 403.
Problem
eveChannel()authorizers sometimes need to distinguish an authenticated caller whose authorization dependency is not queryable yet from an unauthenticated or forbidden caller.A concrete case is owner-authorized initial session streaming:
POST /eve/v1/sessionauthenticates and returns a new session ID.GET /eve/v1/session/:sessionId/stream.session.startedprojection may not yet have made the session-to-owner mapping queryable.403permanently fails the native client. The native stream opener already treats425as bounded/retryable.Today the public
AuthFncontract only documents principal/null plusUnauthenticatedErrorandForbiddenError.routeAuthinternally preserves errors carrying aResponse, but application code must rely on that private duck-typed behavior to emit425.Proposed invariant
An authenticated route dependency that is provably pending may fail with one public, typed retryable readiness error. Unauthorized callers must continue to receive 401/403. Application code must not copy Eve routes, proxy streams, or implement retry sleeps.
Proposed API
Export a public typed error from
eve/channels/auth, name to maintainer preference, for example:The error should own a framework-shaped response:
425 Too Earlycache-control: no-storesession_not_readyRetry-After, if desiredScope
routeAuthtests proving exact response preservation and auth-walk termination.No new transport or retry implementation is required; the native client already retries 425.
Alternatives considered
Exposing target-session initiator/current auth at route time would be stronger but substantially larger: the current channel session handle exposes only ID, continuation token, and event stream, while
session.starteddoes not exposeSessionAuthContext. A typed readiness error is the smallest public contract that closes the gap without leaking session auth or adding a durable metadata index.Consumer
FreshlakeAI/livetaxbot TGL-493/TGL-494. The consumer has adversarial coverage ensuring 425 is returned only for an exact owned, running, unattached reservation; missing, stale, cross-user, cross-chat, or differently attached records remain 403.