fix(ai): valid Tailwind token + base_url URL validation

- Data-handling block in _llm_provider_selector swaps the invalid
  bg-surface-secondary token for bg-container-inset, matching the
  inset-card pattern used elsewhere in sure-design-system/components.css.
  bg-surface-secondary is not defined anywhere in the design system —
  Tailwind treated it as a no-op, so the block rendered with no
  background contrast.
- Settings::HostingsController validates anthropic_base_url as a
  URI::HTTP (catches https too) and raises Setting::ValidationError
  with a localized message when the input is not parseable.
  Previously any string was persisted, surfacing as an opaque
  connection error at request time instead of an immediate UX failure.
- Blank base_url now clears the setting (was already the case but
  exercised explicitly in tests now).
This commit is contained in:
Guillem Arias
2026-05-25 20:39:27 +02:00
parent c81055ea58
commit e7d4a00f73
4 changed files with 34 additions and 2 deletions

View File

@@ -174,7 +174,16 @@ class Settings::HostingsController < ApplicationController
end
if hosting_params.key?(:anthropic_base_url)
Setting.anthropic_base_url = hosting_params[:anthropic_base_url].presence
raw_base_url = hosting_params[:anthropic_base_url].to_s.strip
if raw_base_url.blank?
Setting.anthropic_base_url = nil
else
parsed = URI.parse(raw_base_url) rescue nil
unless parsed.is_a?(URI::HTTP)
raise Setting::ValidationError, t(".invalid_anthropic_base_url")
end
Setting.anthropic_base_url = raw_base_url
end
end
if hosting_params.key?(:anthropic_model)

View File

@@ -30,7 +30,7 @@
<p class="text-xs text-secondary"><%= t(".provider_help") %></p>
<% end %>
<div class="rounded-md border border-secondary p-3 bg-surface-secondary text-xs text-secondary space-y-2">
<div class="rounded-md border border-secondary p-3 bg-container-inset text-xs text-secondary space-y-2">
<p class="font-medium text-primary"><%= t(".data_retention_heading") %></p>
<p><%= t(".data_retention_openai") %></p>
<p><%= t(".data_retention_anthropic") %></p>

View File

@@ -197,6 +197,7 @@ en:
invalid_onboarding_state: Invalid onboarding state
invalid_sync_time: Invalid sync time format. Please use HH:MM format (e.g., 02:30).
invalid_llm_budget: "%{field} must be a whole number ≥ %{minimum}."
invalid_anthropic_base_url: Anthropic Base URL must be an http(s) URL.
scheduler_sync_failed: Settings saved, but failed to update the sync schedule. Please try again or check the server logs.
disconnect_external_assistant:
external_assistant_disconnected: External assistant disconnected

View File

@@ -101,6 +101,28 @@ class Settings::HostingsControllerTest < ActionDispatch::IntegrationTest
end
end
test "rejects non-URL anthropic base_url" do
with_self_hosting do
Setting.anthropic_base_url = nil
patch settings_hosting_url, params: { setting: { anthropic_base_url: "not-a-url" } }
assert_response :unprocessable_entity
assert_match(/Anthropic Base URL must be an http/, flash[:alert])
assert_nil Setting.anthropic_base_url
end
end
test "clears anthropic base_url when blank value submitted" do
with_self_hosting do
Setting.anthropic_base_url = "https://bedrock.example.com"
patch settings_hosting_url, params: { setting: { anthropic_base_url: "" } }
assert_nil Setting.anthropic_base_url
end
end
test "can update llm_provider to anthropic" do
with_self_hosting do
patch settings_hosting_url, params: { setting: { llm_provider: "anthropic" } }