Skip to content

v2.17.5

Latest

Choose a tag to compare

@schmitech schmitech released this 05 Sep 19:57
· 5 commits to main since this release

[2.17.5] - 2026-09-05

Security

  • Feedback Session Ownership: GET /api/feedback/{session_id} and POST /api/feedback now verify that the calling API key owns the session before reading or writing feedback, matching the ownership check already used by thread creation and conversation deletion. Previously any valid adapter key could read another tenant's feedback records, including free-text thumbs-down comments, for any known session id. Requests made without an API key (key enforcement disabled) are unaffected, so standalone feedback keeps working; keyed requests fail closed with 503 when chat history - the source of session ownership - is unavailable, and 403 on a session belonging to another key.
  • API Key Expiration (Authentication Phase 8): API keys now enforce a finite lifetime. New keys default to a 90-day expiration (api_keys.default_lifetime_days), capped at a 365-day maximum (api_keys.max_lifetime_days); expired keys are rejected on every API-key authentication path before adapter resolution, allowlists, and quotas, with no fallback to api_keys.allow_default. Administrators can renew a key's expiration or grant a justified non-expiring exception (allow_non_expiring_exceptions) via POST /admin/api-keys/{id}/renew or orbit key renew, audited without ever recording a raw key. Pre-existing keys are migrated to a finite expiration automatically and idempotently on server startup. List/detail/status responses and the CLI (orbit key list --expired/--expiring-within-days) surface expires_at, expiration_policy, and days_remaining. Completes the API-key portion of the NIST IA-5 authenticator-management control contribution.
  • Two-Factor Authentication (Authentication Phase 7): Local password accounts can now enroll TOTP-based 2FA via POST /auth/mfa/enroll + /auth/mfa/confirm (QR/otpauth:// enrollment, confirmation-gated activation, one-time recovery codes shown once), opt-in via auth.two_factor.enabled. auth.two_factor.required_for_roles (default ["admin"]) blocks login for an unenrolled user in that role until an admin assists. Login becomes two-step for an enrolled account: POST /auth/login returns an intermediate token (mfa_required: true) which must be completed via POST /auth/login/2fa with a TOTP or recovery code, rate limited independently of the password-login buckets. An optional "remember this device" (auth.two_factor.remember_device_days) lets a recognized device skip the second factor. An administrator with users.manage can reset a user's 2FA via DELETE /auth/users/{user_id}/mfa, audited as auth.mfa.admin_reset. TOTP secrets are encrypted at rest (AES-256-GCM, ORBIT_MFA_ENCRYPTION_KEY - generate one with utils/scripts/generate_mfa_encryption_key.py). Enrollment also returns a ready-to-display qr_code_data_uri rendered server-side, scannable by Google Authenticator and other standard TOTP apps. A missing/invalid ORBIT_MFA_ENCRYPTION_KEY now surfaces as a clear 503 on enrollment and login-completion (instead of an opaque 500 or, on the login path, a misleading "invalid code" 401).
  • Admin IP Allowlisting (Authentication Phase 6): /admin/* and the admin-scoped /auth/* routes (user management, blacklist/allowlist, session revocation) can now be restricted to a configurable set of IP addresses/CIDR ranges, opt-in via auth.admin_ip_allowlist.enabled. Rules are managed at runtime via GET/POST/DELETE /auth/admin-ip-rules or orbit user admin-ip, unioned with static default_ranges config. Loopback requests are always exempt so orbit CLI commands against the local server are never blocked, and deleting a rule that would exclude the requesting admin's own current IP is refused without an explicit confirmation flag.

Admin Panel

  • Costs Tab Data Labels: The "Top N by cost" bar chart and "Cost share" doughnut on the Costs tab now show on-chart value/percentage labels via a vendored chartjs-plugin-datalabels, instead of requiring a hover to read the numbers. The plugin is registered globally with its display default disabled, so Feedback and Overview charts (which build their own chart options) are unaffected.
  • Help-Tooltip Field Pattern: Replaced inline field explanations/hint paragraphs across the Adapters, API Keys, Prompts, Users, and MCP tabs with a "?" help-icon tooltip beside each label, following the pattern already used on the Skills tab, which now shares the same helper (helpTooltip/tooltipField/formSection in core/dom.js) instead of a local copy. Also fixed a Skills-tab mobile layout regression from the shared .form-section class, restored inline (not stacked) label/icon layout for MCP's default-settings tooltips, added missing labels/tooltips for the MCP pool_size/pool_idle_timeout settings, and switched the Costs tab's "Group by" dropdown to user-friendly option labels (e.g. "Adapter" instead of adapter_name).