Files
alknet/docs/architecture/questions/011-handler-level-auth-resolution-observability.md
T
glm-5.2 1baa619ce9 docs(arch): decompose open-questions.md into per-OQ files under questions/
The monolithic open-questions.md (1310 lines, 47 OQs) was large enough to be
unmanageable, with high size variance (OQ-42 at 220 lines next to OQ-06 at 8).
Decomposed into one file per OQ under docs/architecture/questions/ (NNN-slug.md,
mirroring the ADR convention), with open-questions.md retained as the index:
theme-grouped tables plus a cross-theme Deferred/Blocked section that surfaces
the 6 deferred OQs with their Blocked-on conditions inline (the safe-exit
visibility surface). Per-OQ content moved verbatim; all 62 inbound links stay
valid (none used anchors). README's curated OQ summary dropped (now redundant
with the index tables).

Also seeds tasks/architecture/ with this task plus two follow-ups found during
the decompose: OQ-09/10 missing structured Blocked-on fields, and the
tasks/architecture/ blocker-task half of the Safe Exit protocol being
unenforced.
2026-07-06 16:07:59 +00:00

3.3 KiB

OQ-11: Handler-Level Auth Resolution Observability

  • Origin: auth.md

  • Status: resolved

  • Door type: Two-way

  • Priority: medium

  • Resolution: Option B — handlers store resolved identity on the Connection. When a handler resolves identity inside handle() (the handler-level auth phase), it calls connection.set_identity(identity) to store the resolved Identity on the connection object. The endpoint and observability layers can read it later for connection logging, audit trails, and metrics.

    Why not Option A (return identity from handle()): it changes the ProtocolHandler trait signature for all handlers, even those that don't do auth resolution (DNS, health check). It also assumes one identity per connection — but the call protocol can have different identities per request on the same connection (one connection, multiple call.requested events with different auth tokens). Returning a single identity from handle() would be misleading for the call protocol.

    Why not Option C (identity stays local): the resolved identity is useful beyond the handler. The endpoint may want to log "connection from X authenticated as Y." A connection-level observability layer needs the identity. If it stays local, every handler that resolves identity would need to duplicate logging logic, and the endpoint can't correlate connections to identities.

    Two identity scopes exist and must not be conflated:

    • Connection-level identity (this decision): set once by the handler in handle(), stored on Connection, read by the endpoint for logging/observability. This is the "connection owner" — who opened this QUIC connection.
    • Per-request identity (already in the call protocol spec): set per call.requested by the CallAdapter, stored on OperationContext.identity. This is the "call caller" — who is making this specific call, which may upgrade mid-session (different auth tokens on the same connection).

    Both exist. The connection-level identity is the stable "who is this connection from"; the per-request identity is the dynamic "who is this specific call from." The call protocol's per-request resolution (which may produce a different identity than the connection-level resolution) takes precedence for ACL on OperationContext — the connection-level identity is for observability only, not for ACL.

    C13 resolution (review #002): the endpoint does not read identity() after handle() returns. The Connection is moved into the spawned handler task (endpoint.md), so the endpoint no longer has a reference to it. Connection-level observability (remote addr, ALPN, connection ID) is logged by the endpoint before the move. Identity-level observability is logged by the handler (the handler knows which identity it resolved and can log it). There is no Arc<Connection> sharing or channel-based identity-reporting mechanism — the simplest honest answer that avoids over-engineering the observability path before there's a demonstrated need. If a future use case requires the endpoint to correlate connections to identities, an Arc<Connection> or a side-channel can be added then.

  • Cross-references: ADR-004, ADR-011, ADR-015 (per-request identity on OperationContext), auth.md