Commit Graph
66 Commits
Author SHA1 Message Date
whit3rabbitandClaude c90fb9f640 feat: loopback-open auth default, --port flag, max_tokens fix, UI banner
- Auth default is now loopback-open (not reject-all). With no
  PROXY_API_KEYS, no PROXY_OPEN_RELAY, no virtual keys and no OIDC,
  loopback TCP peers are accepted and LAN/remote peers get 401. The
  decision uses the real TCP peer (ConnectInfo via
  into_make_service_with_connect_info), not the spoofable
  X-Forwarded-For. effective_auth_mode() (keys/open_relay/loopback_only)
  + proxy_key_count are surfaced on GET /admin/api/status; the admin UI
  shows a warning banner when no key is set.
- Add --port/-p CLI flag that sets LISTEN_PORT for the run. Stripped
  before any run/providers subcommand so flags meant for the launched
  tool survive; pure scan is unit-tested.
- Startup port handling: the run subcommand pre-checks the listen port
  and fails fast with a hint when in use; wait_for_port readiness timeout
  10s -> 30s; listener bind failures (proxy + admin) now print an
  actionable message and exit(1) instead of panicking.
- POST /v1/chat/completions no longer 400s on a missing max_tokens for
  OpenAI-compatible backends. The internal placeholder is stripped via a
  new OMIT_MAX_TOKENS_MARKER so the backend applies its own default
  (e.g. LM Studio's 8192); the marker never leaks upstream. Explicit
  max_tokens is still forwarded verbatim. Anthropic backends unchanged.
- Tier router logs the selected tier at info (tier/backend/model)
  instead of routing silently.
- Admin UI modal no longer dismisses when a text-selection drag starts
  inside the card (dismiss only on a press that begins on the backdrop).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-16 20:08:13 -05:00
whit3rabbitandClaude Opus 4.8 9b6bf97841 chore: fix clippy warnings (-D warnings clean across all targets)
- bootstrap test: std::slice::from_ref instead of &[x.clone()]
  (cloned_ref_to_slice_refs)
- chat_completions test: is_some_and instead of map_or(false, ..)
- token_counting: move count_content above mod tests
  (items_after_test_module)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 20:51:08 -05:00
whit3rabbitandClaude Opus 4.8 e96ec18b24 feat: admin UI on by bare launch + tier-router review fixes
Admin/browser:
- Enable admin UI on bare (zero-arg) launch; auto-open default browser
  (main_helpers::bootstrap::admin_enabled / is_default_launch, browser.rs).
- Guard Docker (docker-entrypoint.sh) and systemd (packaging/anyllm-proxy.service)
  so headless server installs keep admin opt-in (DISABLE_ADMIN default off).

Claude Code tier router fixes (from code review):
- put.rs: validate only *enabled* tiers, and accept statically-configured
  (all_backends) targets via new SharedState.static_backends, not just managed.
- openai_signals: drop historical reasoning_content check so a plain follow-up
  in a reasoning conversation isn't misrouted to the Think tier.
- resolve_router_tier: warn! on fail-open when an active tier's backend is
  unknown instead of silently bypassing the router.

Tests: static-config backend acceptance; existing router coverage still green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 20:38:25 -05:00
whit3rabbitandClaude Opus 4.8 b27aa583f0 feat: Claude Code tier router, merged Routing tab, and theme redesign
Router (opt-in, disabled by default): classify each request by shape
(image / web_search / think / long_context / background / default) and route
it to a configured backend+model, bypassing model-name routing. Backend in
config/router_config.rs + server/router_signals.rs, wired through app_state,
the chat_completions and messages handlers, and the /admin/api/config
put/get/delete routes; covered by tests/router_config_admin.rs.

Admin UI: merge the former Router and Routes tabs into a single Routing tab
with two subtabs, Auto Router (route by request shape) and Model Routes
(named model aliases, load-balanced). Old #/router and #/routes URLs redirect
to the matching subtab.

Theme: move accent color and light/dark mode into a Settings > Display
section as independent axes (mode layers over any accent), default accent
Blue, migrating existing anyllm.theme=light values.

Also: settings copy tweak for thinking-repair, RouterConfig API types, and the
regenerated dist/index.html bundle.

Note: theme and router share Sidebar.tsx and globals.css at the hunk level, so
they land together rather than as separate commits.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 19:15:56 -05:00
whit3rabbitandClaude 86d01d29fd refactor: split large files into modules
- Split config.rs into config/{mod,delete,get,put}.rs
- Split routes_api.rs into routes_api/{mod,helpers,providers,routes}.rs
- Split passthrough/handlers.rs into handlers/{mod,errors,generic,messages}.rs
- Split streaming.rs into streaming/{mod,handler,helpers}.rs
- Split main_helpers/async_main/admin.rs into admin/{mod,config,tasks}.rs
- Minor cleanups in chat_completions backends, token_counting, tests
- Add docs/TEST_PARITY_LITELLM.md

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-13 06:11:40 -05:00
whit3rabbitandClaude Opus 4.8 7fc44582c6 fix: enforce model allowlist on Bedrock native routes; fix model discovery
Bedrock native routes (converse/converse-stream/invoke/invoke-with-response-
stream) now enforce the virtual key's model allowlist, closing a model-scope
bypass where a model-scoped key could invoke any Bedrock modelId.

Admin UI "Query models" discovery: stop doubling /v1 into /v1/v1/models for
local providers whose catalog base URL already ends in /v1, trim trailing
slashes off api_base, support Anthropic-native providers (x-api-key +
anthropic-version auth, display_name model field), and show/warn about the
discovery target URL in the Add-Backend form.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 09:14:20 -05:00
whit3rabbitandClaude Opus 4.8 a108c35ff1 feat(admin-ui): default-open provider options, route curl snippet, live proxy status
Admin UI UX fixes plus the route-dispatch feature set:

- Providers: selecting a provider shows the full key/options form immediately
  instead of hiding it behind a "+ Add key" button; "Cancel" becomes "Reset".
- Routes: enabled routes show a ready-to-run curl snippet (endpoint URL from the
  new proxy_port on /admin/api/status, route name as the model) with a copy button.
- Settings: live proxy status badge (running/unreachable) backed by a proxy_running
  TCP liveness check on /admin/api/status, plus a per-save "applied live" toast.
- Backend: plumb proxy listen_port into SharedState; expose proxy_port + proxy_running.
- Also includes the RouteRouter dispatch layer, per-route option overrides, local-LLM
  backend support, favorites, and model discovery (see CHANGELOG [Unreleased]).

Ignore .gate/ security-scanner scratch artifacts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 07:48:13 -05:00
whit3rabbit 8d523abd63 feat: pxpipe context compression + forge guardrails + LiteLLM catalog refresh + otel security bump 2026-07-05 16:22:51 -05:00
whit3rabbitandClaude Sonnet 5 a87cae6ca4 feat: ANTHROPIC_FORWARD_CLIENT_AUTH with live admin-UI toggle
Adds opt-in client-credential forwarding for Anthropic passthrough
(single-key/BYOK deployments), plus fixes found in review:

- Startup safeguard now shares one check (server/middleware/auth.rs)
  with the live admin PUT /admin/api/config path, closing a bypass
  where PROXY_OPEN_RELAY=true alongside 2+ PROXY_API_KEYS entries
  slipped past the old startup-only check.
- x-goog-api-key is now recognized as a forwardable credential
  (renamed to x-api-key upstream, since Anthropic doesn't understand
  that header name), matching validate_auth's precedence.
- Managed (admin-API) backends no longer carry a dead
  forward_client_auth field that could never take effect.
- ClientAuthPath forwarding decisions are now double-checked against
  live VirtualKeyContext/JwtClaims presence, not just the enum, to
  fail closed if the two ever desync.
- Moved from a per-backend BackendConfig field to a global
  RuntimeConfig field (like anthropic_thinking_repair), making it
  live-toggleable from the admin UI with no restart, and uniform
  across every Anthropic-kind backend in a multi-backend deployment.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 15:40:53 -05:00
whit3rabbitandClaude Sonnet 5 9456d1ad1b feat: opt-in forge-guardrails tool-call policy + Anthropic thinking-block repair
- Tool-call guardrails (lsp_first/quiet_command/write_payload_cap nudges,
  fingerprint dedup) for local-LLM tool loops. Configurable via YAML
  tool_execution.guardrails, FORGE_TOOL_CALL_POLICY env fallback, or the
  admin UI (live, no restart).
- Anthropic thinking-block record/repair (ANTHROPIC_THINKING_REPAIR):
  records ground truth off the real API and repairs client-corrupted
  thinking/redacted_thinking blocks in replayed conversations.
- Bidirectional thinking_blocks (signature/redacted state) round-trip
  through the OpenAI-compat wire format for LiteLLM-style clients.
- Review fixes: guardrail-mode divergence between streaming/non-streaming
  paths, cross-backend/tenant cache-namespace collision, client-controlled
  integer overflow in thinking budget_tokens, dropped reasoning_content and
  citations on repair/translation paths, a fail-closed race under cache
  eviction, plus dedup/simplification cleanup and doc corrections.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04 13:03:02 -05:00
whit3rabbit ce89a2d19c Release 0.10.1 2026-06-20 15:24:43 -05:00
whit3rabbit af7fe570c7 fix: complete admin UI and backend wiring 2026-06-20 11:01:29 -05:00
whit3rabbitandClaude Opus 4.8 65cf673b97 feat: performative admin UI redesign + admin API contract fixes
Large admin-ui refactor (Performative component system, sidebar nav,
provider/route tabs) plus backend module restructuring.

Admin UI contract fixes (this session):
- Fix Models page crash: useBackends unwraps {backends:[...]}; align
  ModelEntry to {model_name, deployments} and ModelsResponse.strategy;
  fix add-model body to {model_name, actual_model, backend_name}.
- Fix Backends/Providers health rendering: source per-backend status and
  latency from the uptime endpoint (health_checks); narrow Backend type to
  the real get_backends shape.
- Route + sidebar-link the previously-unrouted Backends tab.

Verified: cargo test (exit 0), clippy -D warnings (exit 0), fmt --check,
admin-ui tsc + vite build all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:13:59 -05:00
whit3rabbit 3eae037f62 Wire Anthropic extensions through proxy 2026-06-07 10:20:07 -05:00
whit3rabbit f78c925b6a Align provider catalog with LiteLLM canonical IDs 2026-05-23 16:34:03 -05:00
whit3rabbit 85477cee8b fix: enforce virtual-key model allowlist on model-selecting passthrough routes (#15)
* fix(proxy): enforce virtual key model allowlist on passthrough endpoints

* fix: enforce virtual key policy on model passthroughs
2026-05-23 15:20:58 -05:00
whit3rabbit c29b523554 fix: reject unknown models when model router is active (#13)
* fix: reject unknown models when model router is active

* fix: use existing invalid request error for model router
2026-05-23 15:20:29 -05:00
whit3rabbit 1f300d8566 Fix virtual-key accounting across generation routes 2026-05-23 12:22:39 -05:00
whit3rabbit 158815acbd Block virtual-key passthrough bypass 2026-05-23 12:22:39 -05:00
whit3rabbit 025d992ca3 Add in-process chat completion runtime 2026-05-23 12:22:39 -05:00
whit3rabbitandClaude Opus 4.7 6de126893f chore: fix all clippy lints across workspace
- tools_map: use std::slice::from_ref over &[clone()] in 4 tests
- gemini_streaming_map: rewrite match as matches!
- backend/mod.rs: move impl BackendClient before #[cfg(test)] mod tests
- middleware: replace .filter().last() with .rfind() (xff parsing)
- middleware: drop dead `|| true` in is_ip_allowed smoke test
- sse: drop blank line between doc comment and assert_sse_ok
- streaming example: collapse nested if-let into outer match arms
- tool_execution tests: array literal over vec! for one-off slices
- live_bedrock: use is_some_and instead of map_or(false, _)
- live_api / live_responses: contains() over iter().any() on &[&str]

All test-only / example changes; no production behavior change.
1130 tests pass, fmt clean, clippy -D warnings clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 19:11:35 -05:00
whit3rabbitandClaude Sonnet 4.6 816b64ae6a feat: add 16 new provider stubs and providers catalog UI tab
New providers: assemblyai, baidu, blackboxai, brave, cartesia, deepgram,
elevenlabs, exa, iflytek, lmsys, playht, pollinations, serper, siliconflow,
stability, tavily. Registered in mod.rs and registry.rs.

Adds a Providers tab to the admin UI with a ProviderIcon component and
catalog route. Updates backend, streaming, config, and test infrastructure
to align with the expanded provider set. Bumps all crate versions to 0.9.0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 17:42:46 -05:00
whit3rabbitandClaude Sonnet 4.6 be038e4164 feat: add provider catalog, bedrock native passthrough, and generic passthrough
Introduces anyllm_providers crate as metadata-only catalog (ProviderDef,
ModelDef, registry). Wires any provider-id as BACKEND via OpenAIClient.
Adds bedrock_native.rs (Converse/InvokeModel with SigV4) and
generic_passthrough.rs catch-all for Translate mode. Updates config,
backend clients, streaming, token counting, and compatibility tests
to support the expanded provider surface. Updates model pricing and docs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 16:33:59 -05:00
whit3rabbitandClaude Sonnet 4.6 1f9bb02968 feat: add Docker support, Gemini input handler, and batch engine improvements
Adds multi-arch Docker build with docker-compose, GitHub Actions CI workflow,
Gemini native input parsing, batch engine SQLite/file/webhook refactors,
and Bedrock streaming fixes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-05 12:01:24 -05:00
whit3rabbit b6158cf3fe feat: refactor admin routes into modular sub-modules and implement model management API endpoints 2026-04-04 20:30:13 -05:00
whit3rabbitandClaude Sonnet 4.6 72ba916241 fix: streaming tool execution iterates up to max_iterations like non-streaming path
The single follow-up pass after initial stream tool calls is replaced with
a loop bounded by engine.loop_config.max_iterations. Each iteration collects
new tool calls from the follow-up stream, builds growing current_messages,
and breaks early if no new tool calls appear or total_timeout is reached.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 20:30:13 -05:00
whit3rabbitandClaude Sonnet 4.6 0593d1ae1b feat: add has_more to pagination responses, disable Next when no more results
Fetch limit+1 rows in get_requests and get_audit_log; if the extra row
exists set has_more=true and truncate back to limit. Admin UI disables
the Next button when has_more is false. Two new integration tests verify
the field is present and false on an empty DB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 20:30:13 -05:00
whit3rabbitandClaude Sonnet 4.6 28580ff311 fix: validate backend_name exists before adding model deployment
Rejects POST /admin/api/models with 400 if the backend_name is not in
backend_metrics, preventing silent routing failures at dispatch time.
Includes a regression test that confirms the guard fires correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 20:30:13 -05:00
whit3rabbitandClaude Sonnet 4.6 84315840f8 fix: harden security, fix expires_at TTL, improve translation accuracy
- Wrap admin token in Zeroizing<String> so memory is wiped on drop
- Use SSRF-safe HTTP client for Langfuse and webhook dispatcher
- Wire up webhook dispatcher at startup (was previously un-started)
- Fix batch expires_at: was using now instead of now+24h
- Extract epoch_secs() helper; replace 4 inline SystemTime::now() blocks
- Gemini tool_choice {type:tool}: use ANY+allowedFunctionNames instead of AUTO
- Map Anthropic thinking budget_tokens to OpenAI reasoning_effort
- Preserve temperature/top_p for GA o-series models (o1/o3/o3-mini/o4-mini);
  only strip for o1-preview and o1-mini which reject those params
- Azure simple config: always route through default_base_url; guard against
  double-appending deployment path when user provides a full URL

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:33:23 -05:00
whit3rabbitandClaude Sonnet 4.6 8ac9ef2677 Merge feat/batch-engine-phase1 into main
Resolves conflicts: take HEAD (security audit) for mcp.rs imports,
register_server_blocking error handling, and maybe_execute_tools loop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 16:00:37 -05:00
whit3rabbitandClaude Sonnet 4.6 ef5f0f596c refactor(proxy): wire batch handlers through BatchEngine crate
Proxy batch handlers now use BatchEngine for job lifecycle, file storage,
and webhook delivery instead of direct SQLite calls. Old batch/db.rs
stripped to Anthropic-specific mapping only. Cancel endpoint at
POST /v1/batches/{id}/cancel. BatchEngine initialized in main.rs startup
with second SQLite connection. Cancel integration test added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 06:49:40 -05:00
whit3rabbitandClaude Sonnet 4.6 bdf73c9057 test(admin): update virtual_keys tests for one-time CSRF tokens
CSRF tokens are now one-time use. Tests updated to:
- Pre-insert TEST_CSRF_TOKEN in test_admin_router() for unit tests
- Call reinsert_csrf() before each additional mutation in multi-step tests
- Add fetch_csrf() helper for real-server tests
- update create_key_via_admin() to fetch a fresh token per call

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 06:48:44 -05:00
whit3rabbit 9803668b7d feat(proxy): wire batch_engine into proxy crate
- Replace batch/mod.rs types with re-exports from anyllm_batch_engine
- Strip batch/db.rs to Anthropic->OpenAI ID mapping only (batch_file/batch_job owned by engine)
- Rewrite batch/routes.rs to use BatchEngine for upload, create, get, list, cancel
- Remove batch_file/batch_job table creation from admin/db.rs init_db
- Add batch_engine parameter to app_multi_with_shared (5th arg, Option<Arc<BatchEngine>>)
- Initialize BatchEngine in main.rs with its own SQLite connection (admin-enabled path)
- Update batch_api.rs tests to use make_test_batch_engine() helper
- Fix anthropic_batch.rs to call init_anthropic_batch_map_table instead of removed init_batch_tables
- Add cancel_queued_batch integration test
2026-03-31 06:48:16 -05:00
whit3rabbitandClaude Opus 4.6 a5b095f988 fix(tools): handle Deny policy as error ToolResult instead of silent PassThrough
partition_tool_calls now returns three buckets (auto_execute, pass_through,
denied). Denied tools generate ToolResult entries with is_error:true and a
"denied by policy" message, which are fed back to the LLM in a follow-up
turn so it can see the rejection. Updated all callers (maybe_execute_tools,
streaming handler in chat_completions.rs) and added unit + integration tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 22:47:46 -05:00
whit3rabbitandClaude Sonnet 4.6 d7082b8812 test: add integration tests for tool execution engine
Covers partition_tool_calls, execute_tool_calls (success + ordering),
tool_results_to_user_message (success + error is_error flag),
is_duplicate, extract_tool_calls, and passthrough-policy behavior.
10 tests, all green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 22:24:14 -05:00
whit3rabbitandClaude Sonnet 4.6 3a62796a75 feat(tools): wire ToolEngineState into AppState with config-driven setup
Add ToolEngineState struct (registry, policy, loop_config, mcp_manager)
and tool_engine field to AppState. Update app_multi_with_shared signature
to accept the new parameter; all callers pass None until config-driven
wiring is implemented in a future task.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 22:07:23 -05:00
whit3rabbitandClaude Opus 4.6 b6277a8b86 feat: operator observability dashboard with error classification
- Admin UI: operator view with request volume, token usage, latency,
  cost charts, failure table, and request timeline
- Backend: add error_kind() method and infer_error_kind() for stable
  error classification (rate_limit, timeout, backend_error, client_error)
- Admin DB: error_kind column in request_log, observability aggregate
  queries (bucketed timeseries, failure breakdown, timeline)
- Gemini: improved streaming translation, thinking block support,
  grounding metadata passthrough
- Request timeout: configurable REQUEST_TIMEOUT_SECS with streaming
  watchdog
- Model pricing: MODEL_PRICING_FILE for external pricing overrides
- Degradation header: ANYLLM_DEGRADATION_WARNINGS env var control

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 19:12:03 -05:00
whit3rabbit e053ac8bbc Merge branch 'feat/model-routing-ux' 2026-03-30 18:24:21 -05:00
whit3rabbitandClaude Sonnet 4.6 6950b4ec52 feat(server): gate degradation header in chat_completions; add on/off header tests
Wrap all four inject_degradation_header calls in chat_completions.rs with
state.expose_degradation_warnings guard, matching the pattern already applied
in routes.rs. Update existing degradation test to use expose_degradation_warnings:
true; add suppressed-when-disabled test for the false case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:13:15 -05:00
whit3rabbit 12aa5e100c feat(config): wire simple YAML format into MultiConfig::load via 'models:' key detection
- Probe YAML with serde_yaml::Value before dispatching to LiteLLM parser
- If root 'models:' key present, dispatch to simple::parse_simple_yaml()
- LiteLLM path (model_list:) and TOML path unchanged
- Add tempfile dev-dependency for integration tests
- Add simple_config integration tests covering both dispatch paths
2026-03-30 17:11:38 -05:00
whit3rabbitandClaude Sonnet 4.6 f15af5969b fix(config): add expose_degradation_warnings to all Config struct literals in tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 17:06:35 -05:00
whit3rabbitandClaude Sonnet 4.6 4fbaf43011 fix(security): populate source_ip in all admin audit log entries
Add ConnectInfo<SocketAddr> extractor to all seven admin mutation
handlers (put_config, delete_config_override, create_key, update_key,
revoke_key, add_model, remove_model). Pass addr.ip().to_string() as
source_ip in each emit_audit call.

Update integration tests to use into_make_service_with_connect_info
and MockConnectInfo so the ConnectInfo extractor is satisfied in test
servers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 06:38:05 -05:00
whit3rabbitandClaude Opus 4.6 5c73adfaea feat(admin): team-focused UI overhaul with key editing and audit log
Backend:
- PUT /admin/api/keys/{id}: update virtual key fields (role immutable),
  refreshes DashMap, emits key_updated audit entry
- update_virtual_key(): resets spend period when budget_duration changes
- query_audit_log(): action, target_type, since, until filter params
- query_request_log(): add until filter param; wire through RequestsQuery
- GET /admin/api/metrics: include streaming counters (started/completed/failed/disconnected)
- GET /admin/api/env: include RATE_LIMIT_FAIL_POLICY

UI:
- Dashboard: streaming metrics stat row
- Request Log: key filter dropdown, since/until date pickers, Key column
- Access Control tab: allowed_models tag input, edit modal, budget progress
  bars, key prefix link navigates to filtered request log
- Settings: override badges from overridden_keys, Security section
  (IP allowlist, rate limit fail policy)
- Audit tab: action/target/date filters, paginated table

Tests:
- 7 unit tests for update_virtual_key and query_audit_log filters
- 4 integration tests for PUT /admin/api/keys/{id} lifecycle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 18:08:34 -05:00
whit3rabbit 1d167e9863 feat(proxy): add Anthropic batch route handlers 2026-03-27 23:47:00 -05:00
whit3rabbit 6cd37068e3 feat(admin): add CSRF token middleware and /admin/csrf-token endpoint
- validate_csrf middleware: rejects POST/PUT/DELETE without matching X-CSRF-Token header + csrf_token cookie
- GET /admin/csrf-token: public endpoint returning JSON + Set-Cookie (not httpOnly, SameSite=Strict)
- CSRF middleware layered inside validate_admin_token (auth checked first)
- 7 new unit tests in routes.rs for CSRF behavior
- Updated virtual_keys.rs integration tests to include CSRF headers on all POST/DELETE admin calls
2026-03-27 23:45:03 -05:00
whit3rabbitandClaude Sonnet 4.6 f3f5179a64 security: add rate limiting to admin API endpoints (10 RPM per IP)
Defense-in-depth against token brute-force on the admin API. Uses a
DashMap-based sliding window (60s) per client IP, applied as the
outermost middleware layer on protected admin routes. Admin server now
uses into_make_service_with_connect_info to expose client IP. Limit
is configurable at runtime via set_admin_rpm for test flexibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 15:45:37 -05:00
whit3rabbitandClaude Sonnet 4.6 915a703a5a security: HMAC-SHA256 keyed hashing for virtual keys with dual-mode migration
New virtual keys are hashed with HMAC-SHA256 using a per-installation
secret (auto-generated and stored in SQLite settings table). Auth
middleware tries HMAC hash first, falls back to legacy SHA-256 for
pre-existing keys. This binds key hashes to the installation, so a
stolen database cannot be used to brute-force keys elsewhere.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 15:14:34 -05:00
whit3rabbitandClaude Opus 4.6 793439240c test: add live integration tests for OpenAI Responses API backend
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 06:45:54 -05:00
whit3rabbitandClaude Sonnet 4.6 25279835a7 feat: add LiteLLM config.yaml compatibility and model-level routing
Accept LiteLLM config.yaml directly via PROXY_CONFIG=config.yaml. Parses
model_list with provider/model format, supports multiple deployments per
model name with round-robin + RPM-aware load balancing, cross-backend
dispatch, and os.environ/VAR env var syntax. Adds env var aliases for
LITELLM_MASTER_KEY, AZURE_API_KEY, AZURE_API_BASE, LITELLM_CONFIG.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 05:39:51 -05:00
whit3rabbitandClaude Opus 4.6 d6b9d61071 feat: add caching, batch API, cost tracking, budget/RBAC, audio/image passthrough
LiteLLM parity features:
- Response caching (in-memory moka, optional Redis tier) with per-request TTL
- Batch API (file upload, job creation/listing via OpenAI delegation)
- Per-key budget enforcement (daily/monthly/lifetime) with lazy period reset
- RBAC (admin/developer key roles, developer keys blocked from /admin/)
- Audio transcription/speech and image generation passthrough
- Fallback chain config (YAML-based, 5xx/429 failover)
- Cost tracking foundation (model pricing DB, per-key spend queries)

Code quality cleanup (simplify pass):
- Extract try_cache_response helper (was copy-pasted 4x)
- Extract common_routes for batch/models (was duplicated across 3 HandlerMode arms)
- Deduplicate embeddings_passthrough to delegate to raw_passthrough
- Remove dead code: inject_cost_header, BudgetDuration::from_str_lossy, duplicate CacheConfig
- Collapse epoch_to_ymd wrapper into pub(crate) days_to_ymd

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:23:38 -05:00