Repository navigation
Conversation
|
Code Review Reviewed the diff for the single-selected-model feature (migration, context functions, OpenRouter request building, and admin LiveView). Overall the design is sound — transactional selection guarded by a partial unique index is a good approach — but I found one crash-level regression that should block merge, plus a few smaller items. Critical: create_llm_config/1 crashes on any validation error lib/bodhi/llm_configs.ex:306 The old code had a second, catch-all clause (defp maybe_invalidate_cache(_, _), do: :ok) that was dropped in this PR. Now create_llm_config/1 (lib/bodhi/llm_configs.ex:111-121) calls maybe_invalidate_cache(result, attrs) unconditionally, and when Repo.insert/1 returns {:error, changeset} (missing required fields, duplicate name/model, etc.) there is no matching function clause, so it raises FunctionClauseError instead of returning {:error, changeset}. This breaks:
This is likely why it wasn't caught — the PR description notes mix test couldn't run locally because Postgres wasn't reachable. Worth restoring the catch-all clause (or just inlining the {:ok, _} check without a second private function) before merging. Confusing error changeset for "model no longer exists" lib/bodhi/llm_configs.ex:77-82 LlmConfig.changeset(%LlmConfig{}, %{}) already fails validate_required for name/model/position, so the returned changeset carries three unrelated "can't be blank" errors alongside the real "model does not exist" error. The LiveView then renders inspect(changeset.errors) directly in the flash (lib/bodhi_web/live/llm_config_live/index.ex:362), which would show confusing, irrelevant validation noise to the admin if they select a model that was just deleted by someone else. Consider returning a plain error atom/tuple instead of a changeset here, or building an empty, unvalidated changeset just to carry the one error. Minor: unguarded String.to_integer/1 on client-supplied id lib/bodhi_web/live/llm_config_live/index.ex:352 A tampered/non-numeric id in the event payload (e.g. via a manually crafted pushEvent in devtools) raises ArgumentError and crashes the LiveView process rather than failing gracefully. Not exploitable beyond a self-inflicted crash of the admin's own session, but Integer.parse/1 with a fallback error branch would be more robust, consistent with how delete handles the id via Repo.get!. Nit: terminology inconsistency in the table The status badge changed from "Active" to "Selected" (lib/bodhi_web/live/llm_config_live/index.ex:179), but the table column header and the filter dropdown (active/inactive in the select) still say "Active"/"Inactive". Not a bug, just a small polish opportunity now that "active" is user-facing as "selected". Nice touches
🤖 Generated with Claude Code |
Summary
Validation