Skip to content

Expose a typed retryable readiness error for route auth #724

Description

@thomaskwon416

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:

  1. POST /eve/v1/session authenticates and returns a new session ID.
  2. The client immediately opens GET /eve/v1/session/:sessionId/stream.
  3. An application-owned, awaited session.started projection may not yet have made the session-to-owner mapping queryable.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions