Skip to content

P1 E10 F10.1h: count bounded authentication outcomes #272

Description

@gnanirahulnutakki

Goal

Add the smallest truthful denominator for the Hub's existing authentication-refusal signal: one bounded Prometheus counter for completed authentication attempts with the closed outcomes accepted|refused.

Scope

  • Emit one sanitized accepted observation immediately after the existing bearer-token or browser-session verifier succeeds, before workspace authorization and before the protected handler runs.
  • Preserve every existing sanitized refused observation and the uniform 401 {"error":"unauthorized"} response.
  • Expose sith_auth_attempts_total{outcome="accepted|refused"} through the existing opt-in loopback-only metrics listener, with both series preinitialized at zero.
  • Preserve the existing unlabeled sith_auth_refusals_total for compatibility; each refusal increments it and the new outcome="refused" series exactly once.
  • Keep the process-supervised and slog authentication audit observers refusal-only. Accepted attempts must not create a log record, datagram, delivery-drop count, or child-process work.
  • Carry no request, credential, verifier error, tenant, workspace, actor, principal, token, IP, path, method, trace, correlation, or authorization-result field or label.

Explicit nonclaims

  • This does not cover OIDC provider exchange/callback failures, authorization denials, handler outcomes, or every future authentication mode.
  • It is denominator substrate only: no refusal ratio, alert threshold, brute-force detector, SLO, error budget, page, or complete security-monitoring claim is added.
  • It adds no listener, Service, exporter, persistence, remote write, cloud resource, or other-system telemetry retention.

Acceptance criteria

  • Bearer/API and browser-session/console verification each emit exactly one accepted event after successful credential verification; workspace-forbidden requests still count as authenticated, not refused.
  • All existing refusal paths emit exactly one refused event and retain byte-for-byte uniform unauthorized responses.
  • The new counter exposes only the two preinitialized outcome series and cannot create caller-controlled cardinality.
  • The legacy refusal counter remains unchanged and increments once per refusal.
  • Process and slog refusal observers silently ignore accepted events without logging or recording a delivery drop; metric observation remains independently panic-isolated.
  • Invalid events and observer panics cannot change authentication or suppress later fanout destinations.
  • Tests cover bearer and browser success/refusal, authorization separation, exact increments, zero-at-start, invalid values, no accepted log/datagram, fanout isolation, and forbidden-label/value absence.
  • README, E10 notes, Notion, Obsidian, and the EXTENDED session record state the boundary and nonclaims.
  • Focused/race tests, full CI, vulnerability checks, forced-RLS/isolation, release/Helm/OCI/Kind gates, secret scan, CodeRabbit, signed DCO/GSTACK, exact-head GitHub gates, merge, and exact post-merge dev gates pass.

Security, cost, and rationale

Prometheus guidance recommends pairing failure counters with a total-attempt counter, using one logical metric with bounded labels, and preinitializing known series. The only new runtime cost is one fixed two-series counter increment per completed verifier decision. There is no attacker-controlled label, network path, or cloud resource; scrape and storage cost remains operator-owned on the existing optional loopback endpoint.

References

Parent: #28 (E10)

Metadata

Metadata

Assignees

No one assigned

    Labels

    phase-1Phase 1: read-only federation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions