src/lightspeed@tenant@policy.erl

-module(lightspeed@tenant@policy).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lightspeed/tenant/policy.gleam").
-export([tenant_context/3, system_context/1, budget/3, expanded_budget/6, default_budget/0, new/2, valid/1, mitigation_label/1, evaluate/2, repository_scope/1, role_label/1, telemetry_tags/1, action_label/1, denial_metric/1, decision_kind_label/1, surface_label/1, decision_metric/1, context_label/1, outcome_label/1, budget_label/1, usage_label/1, denial_label/1, expanded_budget_label/1, expanded_usage_label/1, decision_label/1, context/1, runtime_budget/1, runtime_usage/1, denials/1, decisions/1, signature/1]).
-export_type([role/0, context/0, surface/0, mitigation/0, action/0, budget/0, usage/0, denial_telemetry/0, decision_kind/0, decision_telemetry/0, outcome/0, runtime/0, budget_class/0]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(" Tenant isolation and policy runtime contracts (M29/M52 expansion).\n").

-type role() :: viewer | editor | tenant_admin.

-type context() :: {tenant_context, binary(), binary(), role()} |
    {system_context, binary()}.

-type surface() :: runtime_surface |
    data_surface |
    pipeline_surface |
    policy_surface.

-type mitigation() :: throttle_events | pause_pipelines | isolate_tenant.

-type action() :: {read, binary()} |
    {write, binary()} |
    {delete, binary()} |
    {emit_event, integer()} |
    {open_session, integer()} |
    {start_job, integer()} |
    {start_pipeline_run, integer()} |
    {replay_pipeline_run, integer()} |
    {apply_mitigation, mitigation(), integer()}.

-type budget() :: {budget,
        integer(),
        integer(),
        integer(),
        integer(),
        integer(),
        integer()}.

-type usage() :: {usage,
        integer(),
        integer(),
        integer(),
        integer(),
        integer(),
        integer()}.

-type denial_telemetry() :: {denial_telemetry,
        binary(),
        binary(),
        action(),
        binary(),
        usage(),
        budget()}.

-type decision_kind() :: allowed_decision | denied_decision | mitigated_decision.

-type decision_telemetry() :: {decision_telemetry,
        binary(),
        binary(),
        surface(),
        action(),
        decision_kind(),
        binary(),
        usage(),
        budget()}.

-type outcome() :: {allowed, binary()} | {denied, denial_telemetry()}.

-opaque runtime() :: {runtime,
        context(),
        budget(),
        usage(),
        list(denial_telemetry()),
        list(decision_telemetry())}.

-type budget_class() :: event_budget |
    session_budget |
    job_budget |
    pipeline_run_budget |
    pipeline_replay_budget |
    mitigation_budget.

-file("src/lightspeed/tenant/policy.gleam", 124).
?DOC(" Build one tenant context.\n").
-spec tenant_context(binary(), binary(), role()) -> context().
tenant_context(Actor_id, Tenant_id, Role) ->
    {tenant_context, Actor_id, Tenant_id, Role}.

-file("src/lightspeed/tenant/policy.gleam", 133).
?DOC(" Build one system context.\n").
-spec system_context(binary()) -> context().
system_context(Actor_id) ->
    {system_context, Actor_id}.

-file("src/lightspeed/tenant/policy.gleam", 138).
?DOC(" Build one budget.\n").
-spec budget(integer(), integer(), integer()) -> budget().
budget(Max_events, Max_sessions, Max_jobs) ->
    {budget, Max_events, Max_sessions, Max_jobs, Max_jobs, Max_jobs, Max_events}.

-file("src/lightspeed/tenant/policy.gleam", 150).
?DOC(" Build one expanded budget profile for runtime/data/pipeline controls.\n").
-spec expanded_budget(
    integer(),
    integer(),
    integer(),
    integer(),
    integer(),
    integer()
) -> budget().
expanded_budget(
    Max_events,
    Max_sessions,
    Max_jobs,
    Max_pipeline_runs,
    Max_pipeline_replays,
    Max_mitigations
) ->
    {budget,
        Max_events,
        Max_sessions,
        Max_jobs,
        Max_pipeline_runs,
        Max_pipeline_replays,
        Max_mitigations}.

-file("src/lightspeed/tenant/policy.gleam", 169).
?DOC(" Default tenant budget profile.\n").
-spec default_budget() -> budget().
default_budget() ->
    {budget, 8, 3, 5, 5, 3, 6}.

-file("src/lightspeed/tenant/policy.gleam", 181).
?DOC(" Build one policy runtime.\n").
-spec new(context(), budget()) -> runtime().
new(Context, Budget) ->
    {runtime, Context, Budget, {usage, 0, 0, 0, 0, 0, 0}, [], []}.

-file("src/lightspeed/tenant/policy.gleam", 199).
?DOC(" Validate policy runtime invariants.\n").
-spec valid(runtime()) -> boolean().
valid(Runtime) ->
    (((((((((((erlang:element(2, erlang:element(3, Runtime)) >= 0) andalso (erlang:element(
        3,
        erlang:element(3, Runtime)
    )
    >= 0))
    andalso (erlang:element(4, erlang:element(3, Runtime)) >= 0))
    andalso (erlang:element(5, erlang:element(3, Runtime)) >= 0))
    andalso (erlang:element(6, erlang:element(3, Runtime)) >= 0))
    andalso (erlang:element(7, erlang:element(3, Runtime)) >= 0))
    andalso (erlang:element(2, erlang:element(4, Runtime)) >= 0))
    andalso (erlang:element(3, erlang:element(4, Runtime)) >= 0))
    andalso (erlang:element(4, erlang:element(4, Runtime)) >= 0))
    andalso (erlang:element(5, erlang:element(4, Runtime)) >= 0))
    andalso (erlang:element(6, erlang:element(4, Runtime)) >= 0))
    andalso (erlang:element(7, erlang:element(4, Runtime)) >= 0).

-file("src/lightspeed/tenant/policy.gleam", 689).
-spec action_surface(action()) -> surface().
action_surface(Action) ->
    case Action of
        {read, _} ->
            data_surface;

        {write, _} ->
            data_surface;

        {delete, _} ->
            data_surface;

        {emit_event, _} ->
            runtime_surface;

        {open_session, _} ->
            runtime_surface;

        {start_job, _} ->
            pipeline_surface;

        {start_pipeline_run, _} ->
            pipeline_surface;

        {replay_pipeline_run, _} ->
            pipeline_surface;

        {apply_mitigation, _, _} ->
            policy_surface
    end.

-file("src/lightspeed/tenant/policy.gleam", 703).
-spec context_actor_tenant(context()) -> {binary(), binary()}.
context_actor_tenant(Context) ->
    case Context of
        {tenant_context, Actor_id, Tenant_id, _} ->
            {Actor_id, Tenant_id};

        {system_context, Actor_id@1} ->
            {Actor_id@1, <<"system"/utf8>>}
    end.

-file("src/lightspeed/tenant/policy.gleam", 667).
-spec record_decision(runtime(), action(), decision_kind(), binary()) -> runtime().
record_decision(Runtime, Action, Decision, Reason) ->
    {Actor_id, Tenant_id} = context_actor_tenant(erlang:element(2, Runtime)),
    Entry = {decision_telemetry,
        Actor_id,
        Tenant_id,
        action_surface(Action),
        Action,
        Decision,
        Reason,
        erlang:element(4, Runtime),
        erlang:element(3, Runtime)},
    {runtime,
        erlang:element(2, Runtime),
        erlang:element(3, Runtime),
        erlang:element(4, Runtime),
        erlang:element(5, Runtime),
        [Entry | erlang:element(6, Runtime)]}.

-file("src/lightspeed/tenant/policy.gleam", 626).
-spec deny(runtime(), action(), binary(), binary(), binary()) -> {runtime(),
    outcome()}.
deny(Runtime, Action, Actor_id, Tenant_id, Reason) ->
    Denial = {denial_telemetry,
        Actor_id,
        Tenant_id,
        Action,
        Reason,
        erlang:element(4, Runtime),
        erlang:element(3, Runtime)},
    Runtime@1 = {runtime,
        erlang:element(2, Runtime),
        erlang:element(3, Runtime),
        erlang:element(4, Runtime),
        [Denial | erlang:element(5, Runtime)],
        erlang:element(6, Runtime)},
    Runtime@2 = record_decision(Runtime@1, Action, denied_decision, Reason),
    {Runtime@2, {denied, Denial}}.

-file("src/lightspeed/tenant/policy.gleam", 614).
-spec deny_for_context(runtime(), action(), binary()) -> {runtime(), outcome()}.
deny_for_context(Runtime, Action, Reason) ->
    case erlang:element(2, Runtime) of
        {tenant_context, Actor_id, Tenant_id, _} ->
            deny(Runtime, Action, Actor_id, Tenant_id, Reason);

        {system_context, Actor_id@1} ->
            deny(Runtime, Action, Actor_id@1, <<"system"/utf8>>, Reason)
    end.

-file("src/lightspeed/tenant/policy.gleam", 406).
?DOC(" Stable mitigation label.\n").
-spec mitigation_label(mitigation()) -> binary().
mitigation_label(Mitigation) ->
    case Mitigation of
        throttle_events ->
            <<"throttle_events"/utf8>>;

        pause_pipelines ->
            <<"pause_pipelines"/utf8>>;

        isolate_tenant ->
            <<"isolate_tenant"/utf8>>
    end.

-file("src/lightspeed/tenant/policy.gleam", 657).
-spec allow_mitigated(runtime(), action(), binary()) -> {runtime(), outcome()}.
allow_mitigated(Runtime, Action, Reason) ->
    Runtime@1 = record_decision(Runtime, Action, mitigated_decision, Reason),
    {Runtime@1, {allowed, Reason}}.

-file("src/lightspeed/tenant/policy.gleam", 587).
-spec within_budget(usage(), budget(), budget_class()) -> boolean().
within_budget(Usage, Budget, Budget_class) ->
    case Budget_class of
        event_budget ->
            erlang:element(2, Usage) =< erlang:element(2, Budget);

        session_budget ->
            erlang:element(3, Usage) =< erlang:element(3, Budget);

        job_budget ->
            erlang:element(4, Usage) =< erlang:element(4, Budget);

        pipeline_run_budget ->
            erlang:element(5, Usage) =< erlang:element(5, Budget);

        pipeline_replay_budget ->
            erlang:element(6, Usage) =< erlang:element(6, Budget);

        mitigation_budget ->
            erlang:element(7, Usage) =< erlang:element(7, Budget)
    end.

-file("src/lightspeed/tenant/policy.gleam", 570).
-spec projected_usage(usage(), integer(), budget_class()) -> usage().
projected_usage(Usage, Units, Budget_class) ->
    case Budget_class of
        event_budget ->
            {usage,
                erlang:element(2, Usage) + Units,
                erlang:element(3, Usage),
                erlang:element(4, Usage),
                erlang:element(5, Usage),
                erlang:element(6, Usage),
                erlang:element(7, Usage)};

        session_budget ->
            {usage,
                erlang:element(2, Usage),
                erlang:element(3, Usage) + Units,
                erlang:element(4, Usage),
                erlang:element(5, Usage),
                erlang:element(6, Usage),
                erlang:element(7, Usage)};

        job_budget ->
            {usage,
                erlang:element(2, Usage),
                erlang:element(3, Usage),
                erlang:element(4, Usage) + Units,
                erlang:element(5, Usage),
                erlang:element(6, Usage),
                erlang:element(7, Usage)};

        pipeline_run_budget ->
            {usage,
                erlang:element(2, Usage),
                erlang:element(3, Usage),
                erlang:element(4, Usage),
                erlang:element(5, Usage) + Units,
                erlang:element(6, Usage),
                erlang:element(7, Usage)};

        pipeline_replay_budget ->
            {usage,
                erlang:element(2, Usage),
                erlang:element(3, Usage),
                erlang:element(4, Usage),
                erlang:element(5, Usage),
                erlang:element(6, Usage) + Units,
                erlang:element(7, Usage)};

        mitigation_budget ->
            {usage,
                erlang:element(2, Usage),
                erlang:element(3, Usage),
                erlang:element(4, Usage),
                erlang:element(5, Usage),
                erlang:element(6, Usage),
                erlang:element(7, Usage) + Units}
    end.

-file("src/lightspeed/tenant/policy.gleam", 536).
-spec apply_mitigation(runtime(), action(), mitigation(), integer()) -> {runtime(),
    outcome()}.
apply_mitigation(Runtime, Action, Mitigation, Units) ->
    case Units =< 0 of
        true ->
            deny_for_context(Runtime, Action, <<"invalid_units"/utf8>>);

        false ->
            case erlang:element(2, Runtime) of
                {system_context, _} ->
                    allow_mitigated(
                        Runtime,
                        Action,
                        <<"system_mitigation:"/utf8,
                            (mitigation_label(Mitigation))/binary>>
                    );

                {tenant_context, _, _, _} ->
                    Next_usage = projected_usage(
                        erlang:element(4, Runtime),
                        Units,
                        mitigation_budget
                    ),
                    case within_budget(
                        Next_usage,
                        erlang:element(3, Runtime),
                        mitigation_budget
                    ) of
                        true ->
                            _pipe = {runtime,
                                erlang:element(2, Runtime),
                                erlang:element(3, Runtime),
                                Next_usage,
                                erlang:element(5, Runtime),
                                erlang:element(6, Runtime)},
                            allow_mitigated(
                                _pipe,
                                Action,
                                <<"mitigation_applied:"/utf8,
                                    (mitigation_label(Mitigation))/binary>>
                            );

                        false ->
                            deny_for_context(
                                Runtime,
                                Action,
                                <<"mitigation_quota_exceeded"/utf8>>
                            )
                    end
            end
    end.

-file("src/lightspeed/tenant/policy.gleam", 603).
-spec quota_reason(budget_class()) -> binary().
quota_reason(Budget_class) ->
    case Budget_class of
        event_budget ->
            <<"event_quota_exceeded"/utf8>>;

        session_budget ->
            <<"session_quota_exceeded"/utf8>>;

        job_budget ->
            <<"job_quota_exceeded"/utf8>>;

        pipeline_run_budget ->
            <<"pipeline_run_quota_exceeded"/utf8>>;

        pipeline_replay_budget ->
            <<"pipeline_replay_quota_exceeded"/utf8>>;

        mitigation_budget ->
            <<"mitigation_quota_exceeded"/utf8>>
    end.

-file("src/lightspeed/tenant/policy.gleam", 647).
-spec allow(runtime(), action(), binary()) -> {runtime(), outcome()}.
allow(Runtime, Action, Reason) ->
    Runtime@1 = record_decision(Runtime, Action, allowed_decision, Reason),
    {Runtime@1, {allowed, Reason}}.

-file("src/lightspeed/tenant/policy.gleam", 516).
-spec consume_budget(runtime(), action(), integer(), budget_class()) -> {runtime(),
    outcome()}.
consume_budget(Runtime, Action, Units, Budget_class) ->
    case Units =< 0 of
        true ->
            deny_for_context(Runtime, Action, <<"invalid_units"/utf8>>);

        false ->
            Next_usage = projected_usage(
                erlang:element(4, Runtime),
                Units,
                Budget_class
            ),
            case within_budget(
                Next_usage,
                erlang:element(3, Runtime),
                Budget_class
            ) of
                true ->
                    _pipe = {runtime,
                        erlang:element(2, Runtime),
                        erlang:element(3, Runtime),
                        Next_usage,
                        erlang:element(5, Runtime),
                        erlang:element(6, Runtime)},
                    allow(_pipe, Action, <<"within_budget"/utf8>>);

                false ->
                    deny_for_context(
                        Runtime,
                        Action,
                        quota_reason(Budget_class)
                    )
            end
    end.

-file("src/lightspeed/tenant/policy.gleam", 710).
-spec can_write(role()) -> boolean().
can_write(Role) ->
    case Role of
        viewer ->
            false;

        editor ->
            true;

        tenant_admin ->
            true
    end.

-file("src/lightspeed/tenant/policy.gleam", 489).
-spec decide_tenant_action(runtime(), action(), binary(), boolean()) -> {runtime(),
    outcome()}.
decide_tenant_action(Runtime, Action, Resource_tenant_id, Require_write_role) ->
    case erlang:element(2, Runtime) of
        {system_context, _} ->
            allow(Runtime, Action, <<"system_scope"/utf8>>);

        {tenant_context, Actor_id, Tenant_id, Role} ->
            case Tenant_id /= Resource_tenant_id of
                true ->
                    deny(
                        Runtime,
                        Action,
                        Actor_id,
                        Tenant_id,
                        <<"tenant_mismatch:"/utf8, Resource_tenant_id/binary>>
                    );

                false ->
                    case Require_write_role andalso not can_write(Role) of
                        true ->
                            deny(
                                Runtime,
                                Action,
                                Actor_id,
                                Tenant_id,
                                <<"role_forbidden"/utf8>>
                            );

                        false ->
                            allow(Runtime, Action, <<"tenant_match"/utf8>>)
                    end
            end
    end.

-file("src/lightspeed/tenant/policy.gleam", 215).
?DOC(" Evaluate one policy action.\n").
-spec evaluate(runtime(), action()) -> {runtime(), outcome()}.
evaluate(Runtime, Action) ->
    case Action of
        {read, Resource_tenant_id} ->
            decide_tenant_action(Runtime, Action, Resource_tenant_id, false);

        {write, Resource_tenant_id@1} ->
            decide_tenant_action(Runtime, Action, Resource_tenant_id@1, true);

        {delete, Resource_tenant_id@2} ->
            decide_tenant_action(Runtime, Action, Resource_tenant_id@2, true);

        {emit_event, Units} ->
            consume_budget(Runtime, Action, Units, event_budget);

        {open_session, Units@1} ->
            consume_budget(Runtime, Action, Units@1, session_budget);

        {start_job, Units@2} ->
            consume_budget(Runtime, Action, Units@2, job_budget);

        {start_pipeline_run, Units@3} ->
            consume_budget(Runtime, Action, Units@3, pipeline_run_budget);

        {replay_pipeline_run, Units@4} ->
            consume_budget(Runtime, Action, Units@4, pipeline_replay_budget);

        {apply_mitigation, Mitigation, Units@5} ->
            apply_mitigation(Runtime, Action, Mitigation, Units@5)
    end.

-file("src/lightspeed/tenant/policy.gleam", 718).
-spec repository_role(role()) -> lightspeed@data@repository:role().
repository_role(Role) ->
    case Role of
        viewer ->
            viewer;

        editor ->
            editor;

        tenant_admin ->
            tenant_admin
    end.

-file("src/lightspeed/tenant/policy.gleam", 236).
?DOC(" Convert context to data repository scope.\n").
-spec repository_scope(context()) -> lightspeed@data@repository:scope().
repository_scope(Context) ->
    case Context of
        {tenant_context, Actor_id, Tenant_id, Role} ->
            lightspeed@data@repository:tenant_scope(
                Actor_id,
                Tenant_id,
                repository_role(Role)
            );

        {system_context, Actor_id@1} ->
            lightspeed@data@repository:system_scope(Actor_id@1)
    end.

-file("src/lightspeed/tenant/policy.gleam", 293).
?DOC(" Stable role label.\n").
-spec role_label(role()) -> binary().
role_label(Role) ->
    case Role of
        viewer ->
            <<"viewer"/utf8>>;

        editor ->
            <<"editor"/utf8>>;

        tenant_admin ->
            <<"tenant_admin"/utf8>>
    end.

-file("src/lightspeed/tenant/policy.gleam", 245).
?DOC(" Emit telemetry tags for one context.\n").
-spec telemetry_tags(context()) -> list(lightspeed@ops@telemetry:tag()).
telemetry_tags(Context) ->
    case Context of
        {tenant_context, Actor_id, Tenant_id, Role} ->
            [{tag, <<"actor_id"/utf8>>, Actor_id},
                {tag, <<"tenant_id"/utf8>>, Tenant_id},
                {tag, <<"role"/utf8>>, role_label(Role)},
                {tag, <<"scope"/utf8>>, <<"tenant"/utf8>>}];

        {system_context, Actor_id@1} ->
            [{tag, <<"actor_id"/utf8>>, Actor_id@1},
                {tag, <<"tenant_id"/utf8>>, <<"system"/utf8>>},
                {tag, <<"role"/utf8>>, <<"system"/utf8>>},
                {tag, <<"scope"/utf8>>, <<"system"/utf8>>}]
    end.

-file("src/lightspeed/tenant/policy.gleam", 311).
?DOC(" Stable action label.\n").
-spec action_label(action()) -> binary().
action_label(Action) ->
    case Action of
        {read, Resource_tenant_id} ->
            <<"read:"/utf8, Resource_tenant_id/binary>>;

        {write, Resource_tenant_id@1} ->
            <<"write:"/utf8, Resource_tenant_id@1/binary>>;

        {delete, Resource_tenant_id@2} ->
            <<"delete:"/utf8, Resource_tenant_id@2/binary>>;

        {emit_event, Units} ->
            <<"emit_event:"/utf8, (erlang:integer_to_binary(Units))/binary>>;

        {open_session, Units@1} ->
            <<"open_session:"/utf8, (erlang:integer_to_binary(Units@1))/binary>>;

        {start_job, Units@2} ->
            <<"start_job:"/utf8, (erlang:integer_to_binary(Units@2))/binary>>;

        {start_pipeline_run, Units@3} ->
            <<"start_pipeline_run:"/utf8,
                (erlang:integer_to_binary(Units@3))/binary>>;

        {replay_pipeline_run, Units@4} ->
            <<"replay_pipeline_run:"/utf8,
                (erlang:integer_to_binary(Units@4))/binary>>;

        {apply_mitigation, Mitigation, Units@5} ->
            <<<<<<"apply_mitigation:"/utf8,
                        (mitigation_label(Mitigation))/binary>>/binary,
                    ":"/utf8>>/binary,
                (erlang:integer_to_binary(Units@5))/binary>>
    end.

-file("src/lightspeed/tenant/policy.gleam", 263).
?DOC(" Convert one denial telemetry event into a counter metric.\n").
-spec denial_metric(denial_telemetry()) -> lightspeed@ops@telemetry:metric().
denial_metric(Denial) ->
    {counter,
        <<"lightspeed.tenant.policy_denied_total"/utf8>>,
        1,
        [{tag, <<"actor_id"/utf8>>, erlang:element(2, Denial)},
            {tag, <<"tenant_id"/utf8>>, erlang:element(3, Denial)},
            {tag, <<"action"/utf8>>, action_label(erlang:element(4, Denial))},
            {tag, <<"reason"/utf8>>, erlang:element(5, Denial)}]}.

-file("src/lightspeed/tenant/policy.gleam", 415).
?DOC(" Stable decision-kind label.\n").
-spec decision_kind_label(decision_kind()) -> binary().
decision_kind_label(Decision) ->
    case Decision of
        allowed_decision ->
            <<"allowed"/utf8>>;

        denied_decision ->
            <<"denied"/utf8>>;

        mitigated_decision ->
            <<"mitigated"/utf8>>
    end.

-file("src/lightspeed/tenant/policy.gleam", 396).
?DOC(" Stable surface label.\n").
-spec surface_label(surface()) -> binary().
surface_label(Surface) ->
    case Surface of
        runtime_surface ->
            <<"runtime"/utf8>>;

        data_surface ->
            <<"data"/utf8>>;

        pipeline_surface ->
            <<"pipeline"/utf8>>;

        policy_surface ->
            <<"policy"/utf8>>
    end.

-file("src/lightspeed/tenant/policy.gleam", 277).
?DOC(" Convert one decision telemetry event into a counter metric.\n").
-spec decision_metric(decision_telemetry()) -> lightspeed@ops@telemetry:metric().
decision_metric(Entry) ->
    {counter,
        <<"lightspeed.tenant.policy_decision_total"/utf8>>,
        1,
        [{tag, <<"actor_id"/utf8>>, erlang:element(2, Entry)},
            {tag, <<"tenant_id"/utf8>>, erlang:element(3, Entry)},
            {tag, <<"surface"/utf8>>, surface_label(erlang:element(4, Entry))},
            {tag, <<"action"/utf8>>, action_label(erlang:element(5, Entry))},
            {tag,
                <<"decision"/utf8>>,
                decision_kind_label(erlang:element(6, Entry))},
            {tag, <<"reason"/utf8>>, erlang:element(7, Entry)}]}.

-file("src/lightspeed/tenant/policy.gleam", 302).
?DOC(" Stable context label.\n").
-spec context_label(context()) -> binary().
context_label(Context) ->
    case Context of
        {tenant_context, Actor_id, Tenant_id, Role} ->
            <<<<<<<<<<"tenant:"/utf8, Actor_id/binary>>/binary, ":"/utf8>>/binary,
                        Tenant_id/binary>>/binary,
                    ":"/utf8>>/binary,
                (role_label(Role))/binary>>;

        {system_context, Actor_id@1} ->
            <<"system:"/utf8, Actor_id@1/binary>>
    end.

-file("src/lightspeed/tenant/policy.gleam", 330).
?DOC(" Stable outcome label.\n").
-spec outcome_label(outcome()) -> binary().
outcome_label(Outcome) ->
    case Outcome of
        {allowed, Reason} ->
            <<"allowed:"/utf8, Reason/binary>>;

        {denied, Denial} ->
            <<"denied:"/utf8, (erlang:element(5, Denial))/binary>>
    end.

-file("src/lightspeed/tenant/policy.gleam", 354).
?DOC(" Stable budget label.\n").
-spec budget_label(budget()) -> binary().
budget_label(Budget) ->
    <<<<<<<<<<"events="/utf8,
                        (erlang:integer_to_binary(erlang:element(2, Budget)))/binary>>/binary,
                    ",sessions="/utf8>>/binary,
                (erlang:integer_to_binary(erlang:element(3, Budget)))/binary>>/binary,
            ",jobs="/utf8>>/binary,
        (erlang:integer_to_binary(erlang:element(4, Budget)))/binary>>.

-file("src/lightspeed/tenant/policy.gleam", 364).
?DOC(" Stable usage label.\n").
-spec usage_label(usage()) -> binary().
usage_label(Usage) ->
    <<<<<<<<<<"events="/utf8,
                        (erlang:integer_to_binary(erlang:element(2, Usage)))/binary>>/binary,
                    ",sessions="/utf8>>/binary,
                (erlang:integer_to_binary(erlang:element(3, Usage)))/binary>>/binary,
            ",jobs="/utf8>>/binary,
        (erlang:integer_to_binary(erlang:element(4, Usage)))/binary>>.

-file("src/lightspeed/tenant/policy.gleam", 338).
?DOC(" Stable denial telemetry label.\n").
-spec denial_label(denial_telemetry()) -> binary().
denial_label(Denial) ->
    <<<<<<<<<<<<<<<<<<<<<<"actor="/utf8, (erlang:element(2, Denial))/binary>>/binary,
                                            "|tenant="/utf8>>/binary,
                                        (erlang:element(3, Denial))/binary>>/binary,
                                    "|action="/utf8>>/binary,
                                (action_label(erlang:element(4, Denial)))/binary>>/binary,
                            "|reason="/utf8>>/binary,
                        (erlang:element(5, Denial))/binary>>/binary,
                    "|usage="/utf8>>/binary,
                (usage_label(erlang:element(6, Denial)))/binary>>/binary,
            "|budget="/utf8>>/binary,
        (budget_label(erlang:element(7, Denial)))/binary>>.

-file("src/lightspeed/tenant/policy.gleam", 374).
?DOC(" Stable expanded budget label for M52 cross-surface policy evidence.\n").
-spec expanded_budget_label(budget()) -> binary().
expanded_budget_label(Budget) ->
    <<<<<<<<<<<<(budget_label(Budget))/binary, ",pipeline_runs="/utf8>>/binary,
                        (erlang:integer_to_binary(erlang:element(5, Budget)))/binary>>/binary,
                    ",pipeline_replays="/utf8>>/binary,
                (erlang:integer_to_binary(erlang:element(6, Budget)))/binary>>/binary,
            ",mitigations="/utf8>>/binary,
        (erlang:integer_to_binary(erlang:element(7, Budget)))/binary>>.

-file("src/lightspeed/tenant/policy.gleam", 385).
?DOC(" Stable expanded usage label for M52 cross-surface policy evidence.\n").
-spec expanded_usage_label(usage()) -> binary().
expanded_usage_label(Usage) ->
    <<<<<<<<<<<<(usage_label(Usage))/binary, ",pipeline_runs="/utf8>>/binary,
                        (erlang:integer_to_binary(erlang:element(5, Usage)))/binary>>/binary,
                    ",pipeline_replays="/utf8>>/binary,
                (erlang:integer_to_binary(erlang:element(6, Usage)))/binary>>/binary,
            ",mitigations="/utf8>>/binary,
        (erlang:integer_to_binary(erlang:element(7, Usage)))/binary>>.

-file("src/lightspeed/tenant/policy.gleam", 424).
?DOC(" Stable decision-telemetry label.\n").
-spec decision_label(decision_telemetry()) -> binary().
decision_label(Entry) ->
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"actor="/utf8,
                                                                (erlang:element(
                                                                    2,
                                                                    Entry
                                                                ))/binary>>/binary,
                                                            "|tenant="/utf8>>/binary,
                                                        (erlang:element(
                                                            3,
                                                            Entry
                                                        ))/binary>>/binary,
                                                    "|surface="/utf8>>/binary,
                                                (surface_label(
                                                    erlang:element(4, Entry)
                                                ))/binary>>/binary,
                                            "|action="/utf8>>/binary,
                                        (action_label(erlang:element(5, Entry)))/binary>>/binary,
                                    "|decision="/utf8>>/binary,
                                (decision_kind_label(erlang:element(6, Entry)))/binary>>/binary,
                            "|reason="/utf8>>/binary,
                        (erlang:element(7, Entry))/binary>>/binary,
                    "|usage="/utf8>>/binary,
                (expanded_usage_label(erlang:element(8, Entry)))/binary>>/binary,
            "|budget="/utf8>>/binary,
        (expanded_budget_label(erlang:element(9, Entry)))/binary>>.

-file("src/lightspeed/tenant/policy.gleam", 444).
?DOC(" Runtime context accessor.\n").
-spec context(runtime()) -> context().
context(Runtime) ->
    erlang:element(2, Runtime).

-file("src/lightspeed/tenant/policy.gleam", 449).
?DOC(" Runtime budget accessor.\n").
-spec runtime_budget(runtime()) -> budget().
runtime_budget(Runtime) ->
    erlang:element(3, Runtime).

-file("src/lightspeed/tenant/policy.gleam", 454).
?DOC(" Runtime usage accessor.\n").
-spec runtime_usage(runtime()) -> usage().
runtime_usage(Runtime) ->
    erlang:element(4, Runtime).

-file("src/lightspeed/tenant/policy.gleam", 459).
?DOC(" Runtime denials in stable order.\n").
-spec denials(runtime()) -> list(denial_telemetry()).
denials(Runtime) ->
    lists:reverse(erlang:element(5, Runtime)).

-file("src/lightspeed/tenant/policy.gleam", 464).
?DOC(" Runtime decisions in stable order.\n").
-spec decisions(runtime()) -> list(decision_telemetry()).
decisions(Runtime) ->
    lists:reverse(erlang:element(6, Runtime)).

-file("src/lightspeed/tenant/policy.gleam", 469).
?DOC(" Stable runtime signature.\n").
-spec signature(runtime()) -> binary().
signature(Runtime) ->
    <<<<<<<<<<<<<<"context="/utf8,
                                (context_label(erlang:element(2, Runtime)))/binary>>/binary,
                            "|budget="/utf8>>/binary,
                        (budget_label(erlang:element(3, Runtime)))/binary>>/binary,
                    "|usage="/utf8>>/binary,
                (usage_label(erlang:element(4, Runtime)))/binary>>/binary,
            "|denials="/utf8>>/binary,
        (erlang:integer_to_binary(erlang:length(erlang:element(5, Runtime))))/binary>>.