From 8357207ed5ac2e49a059e8be34fe975e70381ae5 Mon Sep 17 00:00:00 2001 From: Mark Kreyman Date: Sun, 12 Apr 2026 23:11:18 -0600 Subject: [PATCH] Fix dispatch 500 (unique constraint) and verify 500 (missing_capability) Bug 1: POST /dispatches crashed with Postgrex.Error when the agent already had an active key. Added unique_constraint declaration to ApiKey changeset so constraint violations produce 422 instead of 500. Bug 2: POST /stories/:id/verify crashed with CaseClauseError when the tenant has an audit key but no capability token was provided. Added catch-all error clause to propagate to the fallback controller. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/loopctl/auth/api_key.ex | 4 ++++ .../controllers/story_verification_controller.ex | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/lib/loopctl/auth/api_key.ex b/lib/loopctl/auth/api_key.ex index 74dfa20..b03d10d 100644 --- a/lib/loopctl/auth/api_key.ex +++ b/lib/loopctl/auth/api_key.ex @@ -47,6 +47,10 @@ defmodule Loopctl.Auth.ApiKey do |> validate_required([:name, :role]) |> validate_inclusion(:role, @roles) |> validate_tenant_for_role() + |> unique_constraint([:tenant_id, :agent_id], + name: :api_keys_one_role_per_agent_idx, + message: "agent already has an active key with this role" + ) end @doc """ diff --git a/lib/loopctl_web/controllers/story_verification_controller.ex b/lib/loopctl_web/controllers/story_verification_controller.ex index 145ffcc..e54bc87 100644 --- a/lib/loopctl_web/controllers/story_verification_controller.ex +++ b/lib/loopctl_web/controllers/story_verification_controller.ex @@ -156,6 +156,9 @@ defmodule LoopctlWeb.StoryVerificationController do {:error, :review_not_conducted} -> {:error, :review_not_conducted} + {:error, :missing_capability} -> + {:error, :missing_capability} + {:error, {:invalid_transition, _ctx} = err} -> {:error, err} @@ -164,6 +167,9 @@ defmodule LoopctlWeb.StoryVerificationController do {:error, :not_found} -> {:error, :not_found} + + {:error, other} -> + {:error, other} end end end