Packages
fnord
0.9.40
0.9.40
0.9.39
0.9.38
0.9.37
0.9.36
0.9.35
0.9.34
0.9.33
0.9.32
0.9.31
0.9.30
0.9.29
0.9.28
0.9.27
0.9.26
0.9.25
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.14
0.9.13
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.99
0.8.98
0.8.97
0.8.96
0.8.95
0.8.94
0.8.93
0.8.92
0.8.91
0.8.90
0.8.89
0.8.88
0.8.87
0.8.86
0.8.85
0.8.84
0.8.83
0.8.82
0.8.81
0.8.80
0.8.79
0.8.78
0.8.77
0.8.76
0.8.75
0.8.74
0.8.73
0.8.72
0.8.71
0.8.70
0.8.69
0.8.68
0.8.67
0.8.66
0.8.65
0.8.64
0.8.63
0.8.62
0.8.61
0.8.60
0.8.59
0.8.58
0.8.57
0.8.56
0.8.55
0.8.54
0.8.53
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.47
0.8.46
0.8.45
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.1
0.8.0
0.7.24
0.7.23
0.7.22
0.7.21
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.44
0.4.43
0.4.42
0.4.41
0.4.40
0.4.39
0.4.38
0.4.37
0.4.36
0.4.35
0.4.34
0.4.33
0.4.32
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
AI code archaeology
Current section
Files
Jump to
Current section
Files
lib/services/approvals.ex
defmodule Services.Approvals do
use GenServer
# ----------------------------------------------------------------------------
# Types
# ----------------------------------------------------------------------------
defstruct [:session]
@type t :: %__MODULE__{
session: [any]
}
# ----------------------------------------------------------------------------
# Globals
# ----------------------------------------------------------------------------
@default_impl %{
edit: Services.Approvals.Edit,
shell: Services.Approvals.Shell
}
# ----------------------------------------------------------------------------
# Client API
# ----------------------------------------------------------------------------
def start_link(_opts \\ []) do
with {:ok, pid} <- GenServer.start_link(__MODULE__, nil) do
Services.Instance.register(__MODULE__, pid)
{:ok, pid}
end
end
@doc """
Discards session-scoped approval state, as when a logical session boundary
occurs within the same OS process (entering edit mode, starting a fresh
follow-up). Config is resolved at confirm-time via impl dispatch, so no
restart is needed to observe new settings.
"""
@spec reset_session() :: :ok
def reset_session() do
Services.Instance.call(__MODULE__, :reset_session)
end
@spec confirm(term, atom) ::
{:ok, :approved}
| {:denied, binary}
| {:error, binary}
def confirm(args, kind) do
Services.Instance.call(__MODULE__, {:confirm, kind, args}, :infinity)
end
# ----------------------------------------------------------------------------
# Server API
# ----------------------------------------------------------------------------
@impl GenServer
def init(_) do
{:ok, %__MODULE__{session: []}}
end
@impl GenServer
def handle_call(:reset_session, _from, _state) do
{:reply, :ok, %__MODULE__{session: []}}
end
@impl GenServer
def handle_call({:confirm, kind, args}, _from, state) do
impl = impl_for(kind)
# Execute the confirmation in a UI.Queue context to avoid deadlocks
result =
UI.Queue.run_from_genserver(fn ->
impl.confirm(state, args)
end)
case result do
{:approved, new_state} -> {:reply, {:ok, :approved}, new_state}
{:denied, reason, new_state} -> {:reply, {:denied, reason}, new_state}
{:error, reason, new_state} -> {:reply, {:error, reason}, new_state}
end
end
# ----------------------------------------------------------------------------
# Internals
# ----------------------------------------------------------------------------
defp impl_for(kind) do
Services.Globals.get_env(:fnord, :approvals, @default_impl)
|> Map.fetch!(kind)
end
end