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>
- 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
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>
Add spend_threshold_level() to detect when a key crosses 80%, 95%, or
100% of its budget. Dedup via a global DashMap so each threshold fires
only once per budget period. After accumulate_spend(), read the updated
spend from SQLite and fire a spend_alert webhook via the existing
CallbackConfig infrastructure (new notify_json method).
Includes reset_alert_level() for budget period rollover and 4 unit tests
covering threshold boundaries, dedup behavior, and map reset.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract row_to_virtual_key helper (3 copies -> 1) in admin/db.rs
- Deduplicate stop_reason mapping: reverse_streaming_map now calls
the shared anthropic_stop_reason_to_openai from reverse_message_map
- Fix stream_options dead code in chat_completions streaming path
(omit_stream_options was overwritten unconditionally)
- Add buffer size limit to Bedrock event stream decoder (was unbounded)
- Replace full serde_json parse with string extraction in detect_event_type
(runs on every Bedrock streaming event)
- Remove redundant WHAT comments in reverse_message_map.rs
- Fix clippy redundant closure warnings in db.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Handle o-series reasoning models (o1, o3, o4-mini): drop max_tokens
(keep only max_completion_tokens) and convert system -> developer role
- Restore read_timeout(900s) alongside tcp_keepalive(60s) to bound hung
connections that keepalive alone cannot detect
- Reuse epoch_to_iso8601 from admin/db.rs instead of duplicating the
Hinnant civil date algorithm in backend/mod.rs
- Make ISO 8601 conversion testable via anchor time parameter
- Fix f64 truncation in duration parsing (use .round() before cast)
- Extract convert_reset_duration helper to deduplicate header injection
- Use eq_ignore_ascii_case in is_o_series_model to avoid allocation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Security: hash API keys with SHA-256 for constant-time comparison (eliminates
length timing leak), require explicit PROXY_OPEN_RELAY for unauthenticated
access, gate /metrics behind auth, sanitize admin error responses, enforce
log_level allowlist on DB restore, validate GCP identifiers against URL
injection, add referrer-policy header to admin SPA.
Correctness: hold concurrency semaphore permit through entire stream lifetime
(not just until headers are sent), fix SSE parser to resume scanning near
chunk boundaries instead of re-scanning from start, mark padding tool call
slots as closed to prevent spurious ContentBlockStop events, mark responses
streaming translator as finished on error to prevent double closure events,
serialize concurrent config writes with a Mutex.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Split config.rs into config/{mod,tls,url_validation}.rs and extract
server/{passthrough,streaming,token_counting}.rs and admin/ws.rs from
their parent modules for clarity.
Functional changes:
- Add DNS rebinding protection on admin API (Host header validation)
- Fix IPv6 host parsing in admin origin check (bare ::1 was mishandled)
- Return Anthropic-shaped errors for JSON parse failures (400 not 422)
and unmatched routes (404 not_found_error)
- Forward extra fields from Anthropic request to OpenAI request
- Count "Error: " prefix tokens for error tool results
- Reduce TOKENIZER visibility to module-private
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Constant-time token comparison in admin auth (timing side-channel)
- Origin header parsing via URL to prevent bypass (e.g., 127.0.0.1.attacker.com)
- CSP headers and X-Frame-Options on admin SPA
- WebSocket origin check for cross-site WS hijacking prevention
- Switch admin DB mutex from tokio::Mutex to std::Mutex, use spawn_blocking
- Poison-recovery on std::sync locks (unwrap_or_else + into_inner)
- JSON builder for SSE error fallback to prevent injection
- UTF-8-safe secret redaction (char-aware slicing)
- Add RedactedThinking content block and SignatureDelta streaming types
- Map OpenAI refusal field to Anthropic text block (non-streaming + streaming)
- Map OpenAI cached_tokens to Anthropic cache_read_input_tokens
- Map HTTP 408 to Anthropic OverloadedError
- Warn on trace log level and log_bodies enable via admin API
- Update CLAUDE.md docs to match current state
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Security: strip admin token from browser URL, add cross-origin rejection
middleware for admin API, skip tool calls with empty names instead of
substituting "unknown".
Correctness: use BytesMut for SSE buffering to prevent UTF-8 corruption
at TCP chunk boundaries, use saturating_sub for epoch arithmetic, handle
CRLF SSE frame delimiters.
Runtime: switch runtime_config to std::sync::RwLock (guard is !Send),
use block_in_place for SQLite IO, spawn_blocking for tokenization,
add tracing reload layer so admin log_level changes apply immediately.
Reliability: retry failed log buffer flushes with capped retry queue,
add MAX_SSE_BUFFER_SIZE guard in middleware handler, cap tool call and
part indices to prevent unbounded vec growth.
Observability: defer streaming request logging until stream completes
so entries capture actual status, latency, and token counts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>