LemonChannels.ModelPolicy.Route (lemon_channels v0.1.0)

View Source

Route key handling for model policies.

Routes define the hierarchical path for model policy resolution:

  • {channel_id, account_id, peer_id, thread_id} - thread-level (most specific)
  • {channel_id, account_id, peer_id, nil} - peer-level (DM/chat)
  • {channel_id, account_id, nil, nil} - account-level
  • {channel_id, nil, nil, nil} - channel-type level

Precedence (highest to lowest)

  1. Session override (temporary, per-request)
  2. Thread-level policy
  3. Peer-level policy
  4. Account-level policy
  5. Channel-type policy
  6. Global default

Examples

# Create a route for a Telegram chat thread
route = Route.new("telegram", "default", "-1001234567890", "456")

# Create a route for a Discord channel
route = Route.new("discord", "bot1", "123456789012345678", nil)

# Get route key for storage
key = Route.to_key(route)

Summary

Types

Account identifier within a channel

Channel identifier (e.g., 'telegram', 'discord')

Peer/chat/channel identifier

Route tuple for storage lookup

t()

Route struct representing a policy scope

Thread/topic identifier

Functions

Creates a wildcard route that matches any account/peer/thread within a channel.

Creates a route from a storage key tuple.

Checks if a route is more specific than another.

Returns the precedence hierarchy for policy resolution.

Converts a route struct to a storage key tuple.

Types

account_id()

@type account_id() :: String.t() | nil

Account identifier within a channel

channel_id()

@type channel_id() :: String.t()

Channel identifier (e.g., 'telegram', 'discord')

peer_id()

@type peer_id() :: String.t() | nil

Peer/chat/channel identifier

route_key()

@type route_key() ::
  {channel_id(), account_id(), peer_id(), thread_id()}
  | {channel_id(), account_id(), peer_id()}
  | {channel_id(), account_id()}
  | {channel_id()}

Route tuple for storage lookup

t()

@type t() :: %LemonChannels.ModelPolicy.Route{
  account_id: account_id(),
  channel_id: channel_id(),
  peer_id: peer_id(),
  thread_id: thread_id()
}

Route struct representing a policy scope

thread_id()

@type thread_id() :: String.t() | nil

Thread/topic identifier

Functions

channel_wide(channel_id)

@spec channel_wide(channel_id()) :: t()

Creates a wildcard route that matches any account/peer/thread within a channel.

Examples

iex> Route.channel_wide("telegram")
%Route{channel_id: "telegram", account_id: nil, peer_id: nil, thread_id: nil}

from_key(arg)

@spec from_key(route_key()) :: t()

Creates a route from a storage key tuple.

Examples

iex> Route.from_key({"telegram", "default", "123", "456"})
%Route{channel_id: "telegram", account_id: "default", peer_id: "123", thread_id: "456"}

more_specific?(a, b)

@spec more_specific?(t(), t()) :: boolean()

Checks if a route is more specific than another.

Examples

iex> Route.more_specific?(
...>   Route.new("telegram", "default", "123", "456"),
...>   Route.new("telegram", "default", "123", nil)
...> )
true

iex> Route.more_specific?(
...>   Route.new("telegram"),
...>   Route.new("telegram", "default", "123", "456")
...> )
false

new(channel_id, account_id \\ nil, peer_id \\ nil, thread_id \\ nil)

@spec new(channel_id(), account_id(), peer_id(), thread_id()) :: t()

Creates a new route struct.

Examples

iex> Route.new("telegram", "default", "123", "456")
%Route{channel_id: "telegram", account_id: "default", peer_id: "123", thread_id: "456"}

iex> Route.new("discord")
%Route{channel_id: "discord", account_id: nil, peer_id: nil, thread_id: nil}

precedence_keys(route)

@spec precedence_keys(t()) :: [route_key()]

Returns the precedence hierarchy for policy resolution.

Given a route, returns a list of increasingly general route keys to check for policy matches.

Examples

iex> Route.new("telegram", "default", "123", "456") |> Route.precedence_keys()
[
  {"telegram", "default", "123", "456"},
  {"telegram", "default", "123", nil},
  {"telegram", "default", nil, nil},
  {"telegram", nil, nil, nil}
]

to_key(route)

@spec to_key(t()) :: route_key()

Converts a route struct to a storage key tuple.

Examples

iex> Route.new("telegram", "default", "123", "456") |> Route.to_key()
{"telegram", "default", "123", "456"}