From 7f9d9646a51a0231d983101e8c7e34fd8f286888 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 16 Jun 2026 14:33:39 +0200 Subject: [PATCH] fix(auth): boot AshAuthentication children under the :mv otp_app --- lib/mv/application.ex | 2 +- test/mv/application_test.exs | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 test/mv/application_test.exs diff --git a/lib/mv/application.ex b/lib/mv/application.ex index 1b6014e..e9d62d0 100644 --- a/lib/mv/application.ex +++ b/lib/mv/application.ex @@ -32,7 +32,7 @@ defmodule Mv.Application do {Task.Supervisor, name: Mv.TaskSupervisor}, {DNSCluster, query: Application.get_env(:mv, :dns_cluster_query) || :ignore}, {Phoenix.PubSub, name: Mv.PubSub}, - {AshAuthentication.Supervisor, otp_app: :my}, + {AshAuthentication.Supervisor, otp_app: :mv}, SystemActor, # Start a worker by calling: Mv.Worker.start_link(arg) # {Mv.Worker, arg}, diff --git a/test/mv/application_test.exs b/test/mv/application_test.exs new file mode 100644 index 0000000..c8f24b0 --- /dev/null +++ b/test/mv/application_test.exs @@ -0,0 +1,58 @@ +defmodule Mv.ApplicationTest do + @moduledoc """ + Guards the AshAuthentication supervisor wiring in `Mv.Application`. + + The auth children (token Expunger, audit-log batcher/expunger) resolve their + configuration via `Spark.sparks(otp_app, Ash.Resource)`. With the wrong + `otp_app` they silently start against an empty resource set: the token + Expunger then runs against no token resources and becomes a no-op. This test + pins the corrected `:mv` wiring against the *running* application tree: the + supervisor and all three children are present, and the token Expunger booted + live and resolved the real `:mv` token resource. + + The two audit-log children legitimately report an `:undefined` pid because no + `AuditLogResource` resources exist under `:mv` (their init returns `:ignore`); + that is a successful start, not a crash, so they are only asserted present. + """ + use ExUnit.Case, async: false + + alias AshAuthentication.TokenResource.Expunger + + test "AshAuthentication children boot under the :mv otp_app and resolve real config" do + # Locate the running AshAuthentication.Supervisor inside the live app tree. + auth_sup = + Mv.Supervisor + |> Supervisor.which_children() + |> Enum.find_value(fn + {AshAuthentication.Supervisor, pid, _type, _mods} when is_pid(pid) -> pid + _ -> nil + end) + + assert is_pid(auth_sup), "AshAuthentication.Supervisor is not running in Mv.Supervisor" + + children = Supervisor.which_children(auth_sup) + child_ids = children |> Enum.map(&elem(&1, 0)) |> Enum.sort() + + # All three auth children are present in the supervision tree. + assert child_ids == + Enum.sort([ + AshAuthentication.TokenResource.Expunger, + AshAuthentication.AuditLogResource.Batcher, + AshAuthentication.AuditLogResource.Expunger + ]) + + # The token Expunger booted as a live process and resolved the real :mv + # token resource — proving the children run against non-empty :mv config + # rather than the empty set the wrong otp_app produced. + expunger_pid = + Enum.find_value(children, fn + {Expunger, pid, _, _} when is_pid(pid) -> pid + _ -> nil + end) + + assert is_pid(expunger_pid), "token Expunger did not boot as a live process under :mv" + assert Process.alive?(expunger_pid) + assert %{otp_app: :mv, resources: resources} = :sys.get_state(expunger_pid) + assert Map.has_key?(resources, Mv.Accounts.Token) + end +end