Skip to content

v0.0.1-beta.3

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 17 Aug 07:14
· 264 commits to main since this release

[v0.0.1-beta.3] - 2026-08-17

Added

  • Client IP capture in usage and error logs (client_ip column on both tables, exposed via the admin/user log APIs): proxy.behind_cdn (default false) enables vendor header detection — CF-Connecting-IPTrue-Client-IPX-Real-IP in order, RemoteAddr fallback; off = RemoteAddr only. Zero-allocation extraction on the request path.
  • Pagination (limit/offset) for the redemption-code usage audit endpoint — previously silently truncated at 20 rows.
  • Masked admin key listing (GET /admin/keys) with name/user/group filters and pagination.
  • WS upgrade handshake timeout (15 s) — a black-hole upstream can no longer pin concurrency slots forever.
  • Service-side search for the logs filters and a unified ScrollArea scrollbar across the admin UI.

Changed

  • Forwarding pipeline unified into a single shared skeleton: handleFormat/HandleSearch/HandleResponsesWS now share one guard stage (auth → quota → balance → concurrency gate → rate limit) and one failover loop, with per-format differences confined to two narrow interfaces (attempt + sink). Warn wording, per-format prechecks and the WS exhaustion frame stay format-specific.
  • WS relay (responses-ws and codex variants) unified onto a 5-method transport interface — the two 200-line concurrent state machines are now one skeleton plus thin adapters.
  • Key/group lifecycle semantics hardened: soft-deleted keys can no longer be resurrected through update/rotate (404), soft-deleted groups reject key creation and assignment (404), group deletion validates account membership (409, including the batch path), key updates are patch-based (only provided fields are written), and assignment replacement is transactional.
  • Admin role revocation takes effect immediately: the admin auth path now trusts the snapshot role (fail-closed when the snapshot is missing) instead of the 24 h JWT claim.
  • WS relay goroutines are panic-contained per connection (log + orderly teardown) instead of crashing the whole process; the panic log now includes a stack trace and no longer writes a 500 body into an already-started SSE stream.
  • Admin/user list endpoints clamp limit to 200; strict JSON decoding rejects unknown fields and trailing garbage with a 400.
  • Config validation is fail-fast for proxy.max_body_size (≥ 1) and upstream.idle_conn_timeout/dial_timeout (≥ 1 ms).
  • User-visible error frames never carry SDK/connection internals: codex fatal/4xx paths use fixed gateway messages, the aiclient 4xx fallback keeps internal text in logs only, and images SSE error frames use a fixed message.
  • JSON processing family converged: single-pass top-level extraction (4 full-document scans → 2), byte-level sjson rewrites (preserving >2^53 integer precision), byte-anchored event-type detection, and a usage pre-filter on the chat path — all pinned by zero-allocation assertions.
  • Web frontend: poll failures keep stale data with a warning bar instead of replacing the whole page; log filter inputs are debounced (300 ms); settings render unknown keys in a fallback card.

Fixed

  • SSE long-line truncation zeroing billing/quota on long responses (line-continuation state machine).
  • WS gateway-credential passthrough: X-Api-Key is now stripped from the upstream handshake like Authorization.
  • WS path ignoring service_tier — tier extraction, strip/reject policy and billing tier are now applied on the WS first frame.
  • Converted-path tt = 0 never deducting quota — all three exit points mirror the native tt = it + ot.
  • failover_attempts = 0 leaking concurrency slots permanently (validated ≥ 1, plus a defensive release on the exhaust path).
  • Scheduler resurrection race: apply/FailAccount are now copy-on-write CAS with a disabled absorbing state.
  • Anthropic SDK validation errors classified as 4xx instead of network errors.
  • Test flakes: stats-agg first-round assertion timing, and the user-key lifecycle list assertion depending on fake-store map iteration order.