test/openagents/audit_test.exs

main at 58e6347eeb72 · 2 KB

defmodule OpenAgents.AuditTest do
  @moduledoc """
  CANON-002. The audit ledger admits every actor kind the application produces.

  `machine` is one of them. A paired computer that authenticates to the Git
  plane pushes and fetches under `{:machine, id}`, so `audit_events.actor_type`
  really does carry the value and keeps its spelling.

  The population that matters here is not a reading of the `Audit.record!/5`
  call sites: the Git-plane actor is a variable, so scanning the source for a
  literal `{:machine, …}` finds nothing and proves nothing. It comes from
  `OpenAgents.Forge.GitHTTP.audit_actor_kinds/0`, the list that decides what
  `audit_actor/1` can return.
  """
  use OpenAgents.DataCase, async: true

  alias OpenAgents.{Audit, AuditEvent}
  alias OpenAgents.Forge.GitHTTP

  test "every Git-plane principal kind is an accepted audit actor" do
    accepted = MapSet.new(Audit.actor_kinds())

    for kind <- GitHTTP.audit_actor_kinds() do
      assert MapSet.member?(accepted, Atom.to_string(kind)),
             "a #{kind} push would raise inside Audit.record!/5 after the pack is written"
    end
  end

  test "the schema admits exactly the kinds record!/5 accepts" do
    for kind <- Audit.actor_kinds() do
      assert AuditEvent.changeset(%AuditEvent{}, attributes(kind)).valid?,
             "audit_events refuses the declared actor kind #{kind}"
    end

    refute AuditEvent.changeset(%AuditEvent{}, attributes("computer")).valid?
  end

  test "record!/5 writes each declared kind" do
    for kind <- Audit.actor_kinds() do
      event =
        Audit.record!("vocabulary.probe", {String.to_existing_atom(kind), "actor"}, "probe", kind)

      assert event.actor_type == kind
    end

    assert_raise FunctionClauseError, fn ->
      Audit.record!("vocabulary.probe", {:computer, "actor"}, "probe", "computer")
    end
  end

  defp attributes(actor_type) do
    %{
      event_type: "vocabulary.probe",
      actor_type: actor_type,
      actor_id: "actor",
      subject_type: "probe",
      subject_id: actor_type,
      metadata: %{}
    }
  end
end