-module(lightspeed@ops@tenant_expansion_harness).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lightspeed/ops/tenant_expansion_harness.gleam").
-export([run_scenario/1, run_matrix/0, budget_version_label/0, scenario_label/1, pass_fail_label/1, signature/1, scenario/1, deterministic/1, outcomes/1, failed_scenarios/1, nondeterministic_failures/1, report_signature/1, snapshot_signature/0, snapshot_report_markdown/0]).
-export_type([scenario/0, scenario_outcome/0, report/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(" Deterministic tenant isolation and policy runtime expansion harness (M52).\n").
-type scenario() :: cross_surface_workflow_coverage |
extended_quota_containment |
audit_trace_completeness |
multi_tenant_abuse_regression |
regression_gate_determinism.
-type scenario_outcome() :: {scenario_outcome,
scenario(),
boolean(),
boolean(),
binary()}.
-type report() :: {report, list(scenario_outcome()), integer(), integer()}.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 524).
-spec count_nondeterministic(list(scenario_outcome())) -> integer().
count_nondeterministic(Outcomes) ->
case Outcomes of
[] ->
0;
[Outcome | Rest] ->
case erlang:element(4, Outcome) of
true ->
count_nondeterministic(Rest);
false ->
1 + count_nondeterministic(Rest)
end
end.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 513).
-spec count_failed(list(scenario_outcome())) -> integer().
count_failed(Outcomes) ->
case Outcomes of
[] ->
0;
[Outcome | Rest] ->
case erlang:element(3, Outcome) of
true ->
count_failed(Rest);
false ->
1 + count_failed(Rest)
end
end.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 546).
-spec join_with(binary(), list(binary())) -> binary().
join_with(Separator, Values) ->
case Values of
[] ->
<<""/utf8>>;
[Value] ->
Value;
[Value@1 | Rest] ->
<<<<Value@1/binary, Separator/binary>>/binary,
(join_with(Separator, Rest))/binary>>
end.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 481).
-spec determinism_signature() -> binary().
determinism_signature() ->
Runtime = lightspeed@tenant@policy:new(
lightspeed@tenant@policy:tenant_context(
<<"actor-determinism"/utf8>>,
<<"tenant-determinism"/utf8>>,
editor
),
lightspeed@tenant@policy:expanded_budget(3, 2, 2, 2, 1, 1)
),
{Runtime@1, _} = lightspeed@tenant@policy:evaluate(
Runtime,
{read, <<"tenant-determinism"/utf8>>}
),
{Runtime@2, _} = lightspeed@tenant@policy:evaluate(
Runtime@1,
{emit_event, 1}
),
{Runtime@3, _} = lightspeed@tenant@policy:evaluate(
Runtime@2,
{start_pipeline_run, 1}
),
{Runtime@4, _} = lightspeed@tenant@policy:evaluate(
Runtime@3,
{apply_mitigation, throttle_events, 1}
),
<<<<<<<<<<"runtime="/utf8,
(lightspeed@tenant@policy:signature(Runtime@4))/binary>>/binary,
"|usage="/utf8>>/binary,
(lightspeed@tenant@policy:expanded_usage_label(
lightspeed@tenant@policy:runtime_usage(Runtime@4)
))/binary>>/binary,
"|decisions="/utf8>>/binary,
(join_with(
<<";"/utf8>>,
gleam@list:map(
lightspeed@tenant@policy:decisions(Runtime@4),
fun lightspeed@tenant@policy:decision_label/1
)
))/binary>>.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 473).
-spec evaluate_regression_gate_determinism() -> {boolean(), binary()}.
evaluate_regression_gate_determinism() ->
First = determinism_signature(),
Second = determinism_signature(),
Passed = (First =:= Second) andalso (First /= <<""/utf8>>),
{Passed, First}.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 535).
-spec contains_substring(binary(), binary()) -> boolean().
contains_substring(Value, Part) ->
gleam_stdlib:contains_string(Value, Part).
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 389).
-spec evaluate_multi_tenant_abuse_regression() -> {boolean(), binary()}.
evaluate_multi_tenant_abuse_regression() ->
Attacker_runtime = lightspeed@tenant@policy:new(
lightspeed@tenant@policy:tenant_context(
<<"actor-attacker"/utf8>>,
<<"tenant-attacker"/utf8>>,
tenant_admin
),
lightspeed@tenant@policy:expanded_budget(1, 1, 1, 1, 1, 1)
),
Victim_runtime = lightspeed@tenant@policy:new(
lightspeed@tenant@policy:tenant_context(
<<"actor-victim"/utf8>>,
<<"tenant-victim"/utf8>>,
tenant_admin
),
lightspeed@tenant@policy:expanded_budget(1, 1, 1, 1, 1, 1)
),
{Attacker_runtime@1, Attacker_read_other} = lightspeed@tenant@policy:evaluate(
Attacker_runtime,
{read, <<"tenant-victim"/utf8>>}
),
{Attacker_runtime@2, Attacker_write_other} = lightspeed@tenant@policy:evaluate(
Attacker_runtime@1,
{write, <<"tenant-victim"/utf8>>}
),
{Attacker_runtime@3, Attacker_replay_1} = lightspeed@tenant@policy:evaluate(
Attacker_runtime@2,
{replay_pipeline_run, 1}
),
{Attacker_runtime@4, Attacker_replay_2} = lightspeed@tenant@policy:evaluate(
Attacker_runtime@3,
{replay_pipeline_run, 1}
),
{Attacker_runtime@5, Attacker_mitigated} = lightspeed@tenant@policy:evaluate(
Attacker_runtime@4,
{apply_mitigation, isolate_tenant, 1}
),
{Victim_runtime@1, Victim_read_own} = lightspeed@tenant@policy:evaluate(
Victim_runtime,
{read, <<"tenant-victim"/utf8>>}
),
{Victim_runtime@2, Victim_pipeline} = lightspeed@tenant@policy:evaluate(
Victim_runtime@1,
{start_pipeline_run, 1}
),
{Victim_runtime@3, Victim_event} = lightspeed@tenant@policy:evaluate(
Victim_runtime@2,
{emit_event, 1}
),
Attacker_denials = lightspeed@tenant@policy:denials(Attacker_runtime@5),
Attacker_denial_labels = join_with(
<<";"/utf8>>,
gleam@list:map(
Attacker_denials,
fun lightspeed@tenant@policy:denial_label/1
)
),
Passed = (((((((((((lightspeed@tenant@policy:outcome_label(
Attacker_read_other
)
=:= <<"denied:tenant_mismatch:tenant-victim"/utf8>>)
andalso (lightspeed@tenant@policy:outcome_label(Attacker_write_other) =:= <<"denied:tenant_mismatch:tenant-victim"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Attacker_replay_1) =:= <<"allowed:within_budget"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Attacker_replay_2) =:= <<"denied:pipeline_replay_quota_exceeded"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Attacker_mitigated) =:= <<"allowed:mitigation_applied:isolate_tenant"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Victim_read_own) =:= <<"allowed:tenant_match"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Victim_pipeline) =:= <<"allowed:within_budget"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Victim_event) =:= <<"allowed:within_budget"/utf8>>))
andalso (erlang:length(Attacker_denials) =:= 3))
andalso (lightspeed@tenant@policy:denials(Victim_runtime@3) =:= []))
andalso contains_substring(
Attacker_denial_labels,
<<"tenant_mismatch:tenant-victim"/utf8>>
))
andalso contains_substring(
Attacker_denial_labels,
<<"pipeline_replay_quota_exceeded"/utf8>>
),
{Passed,
<<<<<<<<<<"attacker="/utf8,
(lightspeed@tenant@policy:signature(
Attacker_runtime@5
))/binary>>/binary,
"|victim="/utf8>>/binary,
(lightspeed@tenant@policy:signature(Victim_runtime@3))/binary>>/binary,
"|attacker_denials="/utf8>>/binary,
Attacker_denial_labels/binary>>}.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 321).
-spec evaluate_audit_trace_completeness() -> {boolean(), binary()}.
evaluate_audit_trace_completeness() ->
Runtime = lightspeed@tenant@policy:new(
lightspeed@tenant@policy:tenant_context(
<<"actor-audit"/utf8>>,
<<"tenant-audit"/utf8>>,
viewer
),
lightspeed@tenant@policy:expanded_budget(2, 1, 1, 1, 1, 2)
),
{Runtime@1, Read_own} = lightspeed@tenant@policy:evaluate(
Runtime,
{read, <<"tenant-audit"/utf8>>}
),
{Runtime@2, Write_denied} = lightspeed@tenant@policy:evaluate(
Runtime@1,
{write, <<"tenant-audit"/utf8>>}
),
{Runtime@3, Mitigation} = lightspeed@tenant@policy:evaluate(
Runtime@2,
{apply_mitigation, isolate_tenant, 1}
),
{Runtime@4, Replay_denied} = lightspeed@tenant@policy:evaluate(
Runtime@3,
{replay_pipeline_run, 2}
),
Decisions = lightspeed@tenant@policy:decisions(Runtime@4),
Decision_labels = gleam@list:map(
Decisions,
fun lightspeed@tenant@policy:decision_label/1
),
Decision_metrics = gleam@list:map(
Decisions,
fun(Decision) ->
lightspeed@ops@telemetry:metric_line(
lightspeed@tenant@policy:decision_metric(Decision)
)
end
),
Denial_metrics = gleam@list:map(
lightspeed@tenant@policy:denials(Runtime@4),
fun(Denial) ->
lightspeed@ops@telemetry:metric_line(
lightspeed@tenant@policy:denial_metric(Denial)
)
end
),
Joined_decisions = join_with(<<";"/utf8>>, Decision_labels),
Joined_metrics = join_with(<<";"/utf8>>, Decision_metrics),
Joined_denials = join_with(<<";"/utf8>>, Denial_metrics),
Passed = (((((((((((lightspeed@tenant@policy:outcome_label(Read_own) =:= <<"allowed:tenant_match"/utf8>>)
andalso (lightspeed@tenant@policy:outcome_label(Write_denied) =:= <<"denied:role_forbidden"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Mitigation) =:= <<"allowed:mitigation_applied:isolate_tenant"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Replay_denied) =:= <<"denied:pipeline_replay_quota_exceeded"/utf8>>))
andalso (erlang:length(Decisions) =:= 4))
andalso contains_substring(Joined_decisions, <<"|decision=allowed|"/utf8>>))
andalso contains_substring(Joined_decisions, <<"|decision=denied|"/utf8>>))
andalso contains_substring(
Joined_decisions,
<<"|decision=mitigated|"/utf8>>
))
andalso contains_substring(
Joined_metrics,
<<"lightspeed.tenant.policy_decision_total"/utf8>>
))
andalso contains_substring(
Joined_denials,
<<"lightspeed.tenant.policy_denied_total"/utf8>>
))
andalso contains_substring(Joined_denials, <<"reason=role_forbidden"/utf8>>))
andalso contains_substring(
Joined_denials,
<<"reason=pipeline_replay_quota_exceeded"/utf8>>
),
{Passed,
<<<<<<<<<<"decisions="/utf8, Joined_decisions/binary>>/binary,
"|decision_metrics="/utf8>>/binary,
Joined_metrics/binary>>/binary,
"|denial_metrics="/utf8>>/binary,
Joined_denials/binary>>}.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 243).
-spec evaluate_extended_quota_containment() -> {boolean(), binary()}.
evaluate_extended_quota_containment() ->
A_runtime = lightspeed@tenant@policy:new(
lightspeed@tenant@policy:tenant_context(
<<"actor-a"/utf8>>,
<<"tenant-a"/utf8>>,
tenant_admin
),
lightspeed@tenant@policy:expanded_budget(2, 1, 1, 1, 1, 1)
),
B_runtime = lightspeed@tenant@policy:new(
lightspeed@tenant@policy:tenant_context(
<<"actor-b"/utf8>>,
<<"tenant-b"/utf8>>,
tenant_admin
),
lightspeed@tenant@policy:expanded_budget(2, 1, 1, 1, 1, 1)
),
{A_runtime@1, A_e1} = lightspeed@tenant@policy:evaluate(
A_runtime,
{emit_event, 1}
),
{A_runtime@2, A_e2} = lightspeed@tenant@policy:evaluate(
A_runtime@1,
{emit_event, 1}
),
{A_runtime@3, A_e3} = lightspeed@tenant@policy:evaluate(
A_runtime@2,
{emit_event, 1}
),
{A_runtime@4, A_pr1} = lightspeed@tenant@policy:evaluate(
A_runtime@3,
{start_pipeline_run, 1}
),
{A_runtime@5, A_pr2} = lightspeed@tenant@policy:evaluate(
A_runtime@4,
{start_pipeline_run, 1}
),
{A_runtime@6, A_m1} = lightspeed@tenant@policy:evaluate(
A_runtime@5,
{apply_mitigation, throttle_events, 1}
),
{A_runtime@7, A_m2} = lightspeed@tenant@policy:evaluate(
A_runtime@6,
{apply_mitigation, pause_pipelines, 1}
),
{B_runtime@1, B_e1} = lightspeed@tenant@policy:evaluate(
B_runtime,
{emit_event, 1}
),
{B_runtime@2, B_pr1} = lightspeed@tenant@policy:evaluate(
B_runtime@1,
{start_pipeline_run, 1}
),
{B_runtime@3, B_rp1} = lightspeed@tenant@policy:evaluate(
B_runtime@2,
{replay_pipeline_run, 1}
),
A_usage = lightspeed@tenant@policy:expanded_usage_label(
lightspeed@tenant@policy:runtime_usage(A_runtime@7)
),
B_usage = lightspeed@tenant@policy:expanded_usage_label(
lightspeed@tenant@policy:runtime_usage(B_runtime@3)
),
Passed = (((((((((((((lightspeed@tenant@policy:outcome_label(A_e1) =:= <<"allowed:within_budget"/utf8>>)
andalso (lightspeed@tenant@policy:outcome_label(A_e2) =:= <<"allowed:within_budget"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(A_e3) =:= <<"denied:event_quota_exceeded"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(A_pr1) =:= <<"allowed:within_budget"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(A_pr2) =:= <<"denied:pipeline_run_quota_exceeded"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(A_m1) =:= <<"allowed:mitigation_applied:throttle_events"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(A_m2) =:= <<"denied:mitigation_quota_exceeded"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(B_e1) =:= <<"allowed:within_budget"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(B_pr1) =:= <<"allowed:within_budget"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(B_rp1) =:= <<"allowed:within_budget"/utf8>>))
andalso (A_usage =:= <<"events=2,sessions=0,jobs=0,pipeline_runs=1,pipeline_replays=0,mitigations=1"/utf8>>))
andalso (B_usage =:= <<"events=1,sessions=0,jobs=0,pipeline_runs=1,pipeline_replays=1,mitigations=0"/utf8>>))
andalso (erlang:length(lightspeed@tenant@policy:denials(A_runtime@7)) =:= 3))
andalso (lightspeed@tenant@policy:denials(B_runtime@3) =:= []),
{Passed,
<<<<<<<<<<<<<<"a_usage="/utf8, A_usage/binary>>/binary,
"|b_usage="/utf8>>/binary,
B_usage/binary>>/binary,
"|a_denials="/utf8>>/binary,
(join_with(
<<","/utf8>>,
gleam@list:map(
lightspeed@tenant@policy:denials(A_runtime@7),
fun(Denial) -> erlang:element(5, Denial) end
)
))/binary>>/binary,
"|b_runtime="/utf8>>/binary,
(lightspeed@tenant@policy:signature(B_runtime@3))/binary>>}.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 198).
-spec evaluate_cross_surface_workflow_coverage() -> {boolean(), binary()}.
evaluate_cross_surface_workflow_coverage() ->
Runtime = lightspeed@tenant@policy:new(
lightspeed@tenant@policy:tenant_context(
<<"actor-x"/utf8>>,
<<"tenant-x"/utf8>>,
tenant_admin
),
lightspeed@tenant@policy:expanded_budget(4, 2, 2, 2, 1, 2)
),
{Runtime@1, Read_own} = lightspeed@tenant@policy:evaluate(
Runtime,
{read, <<"tenant-x"/utf8>>}
),
{Runtime@2, Event} = lightspeed@tenant@policy:evaluate(
Runtime@1,
{emit_event, 1}
),
{Runtime@3, Pipeline_run} = lightspeed@tenant@policy:evaluate(
Runtime@2,
{start_pipeline_run, 1}
),
{Runtime@4, Pipeline_replay} = lightspeed@tenant@policy:evaluate(
Runtime@3,
{replay_pipeline_run, 1}
),
{Runtime@5, Write_other} = lightspeed@tenant@policy:evaluate(
Runtime@4,
{write, <<"tenant-y"/utf8>>}
),
Decisions = lightspeed@tenant@policy:decisions(Runtime@5),
Decision_labels = gleam@list:map(
Decisions,
fun lightspeed@tenant@policy:decision_label/1
),
Joined_labels = join_with(<<";"/utf8>>, Decision_labels),
Usage = lightspeed@tenant@policy:expanded_usage_label(
lightspeed@tenant@policy:runtime_usage(Runtime@5)
),
Passed = ((((((((((lightspeed@tenant@policy:outcome_label(Read_own) =:= <<"allowed:tenant_match"/utf8>>)
andalso (lightspeed@tenant@policy:outcome_label(Event) =:= <<"allowed:within_budget"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Pipeline_run) =:= <<"allowed:within_budget"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Pipeline_replay) =:= <<"allowed:within_budget"/utf8>>))
andalso (lightspeed@tenant@policy:outcome_label(Write_other) =:= <<"denied:tenant_mismatch:tenant-y"/utf8>>))
andalso (erlang:length(Decisions) =:= 5))
andalso contains_substring(Joined_labels, <<"|surface=data|"/utf8>>))
andalso contains_substring(Joined_labels, <<"|surface=runtime|"/utf8>>))
andalso contains_substring(Joined_labels, <<"|surface=pipeline|"/utf8>>))
andalso contains_substring(Joined_labels, <<"|decision=denied|"/utf8>>))
andalso (Usage =:= <<"events=1,sessions=0,jobs=0,pipeline_runs=1,pipeline_replays=1,mitigations=0"/utf8>>),
{Passed,
<<<<<<<<<<"usage="/utf8, Usage/binary>>/binary, "|decisions="/utf8>>/binary,
Joined_labels/binary>>/binary,
"|runtime="/utf8>>/binary,
(lightspeed@tenant@policy:signature(Runtime@5))/binary>>}.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 188).
-spec evaluate(scenario()) -> {boolean(), binary()}.
evaluate(Scenario) ->
case Scenario of
cross_surface_workflow_coverage ->
evaluate_cross_surface_workflow_coverage();
extended_quota_containment ->
evaluate_extended_quota_containment();
audit_trace_completeness ->
evaluate_audit_trace_completeness();
multi_tenant_abuse_regression ->
evaluate_multi_tenant_abuse_regression();
regression_gate_determinism ->
evaluate_regression_gate_determinism()
end.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 61).
?DOC(" Run one M52 scenario twice and require deterministic parity.\n").
-spec run_scenario(scenario()) -> scenario_outcome().
run_scenario(Scenario) ->
{First_passed, First_signature} = evaluate(Scenario),
{Second_passed, Second_signature} = evaluate(Scenario),
Deterministic = (First_passed =:= Second_passed) andalso (First_signature
=:= Second_signature),
Passed = (First_passed andalso Second_passed) andalso Deterministic,
{scenario_outcome, Scenario, Passed, Deterministic, First_signature}.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 42).
?DOC(" Run all M52 scenarios.\n").
-spec run_matrix() -> report().
run_matrix() ->
Outcomes = begin
_pipe = [cross_surface_workflow_coverage,
extended_quota_containment,
audit_trace_completeness,
multi_tenant_abuse_regression,
regression_gate_determinism],
gleam@list:map(_pipe, fun run_scenario/1)
end,
{report, Outcomes, count_failed(Outcomes), count_nondeterministic(Outcomes)}.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 77).
?DOC(" M52 budget profile version label.\n").
-spec budget_version_label() -> binary().
budget_version_label() ->
<<"m52.budget.v"/utf8, (erlang:integer_to_binary(1))/binary>>.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 82).
?DOC(" Scenario label.\n").
-spec scenario_label(scenario()) -> binary().
scenario_label(Scenario) ->
case Scenario of
cross_surface_workflow_coverage ->
<<"cross_surface_workflow_coverage"/utf8>>;
extended_quota_containment ->
<<"extended_quota_containment"/utf8>>;
audit_trace_completeness ->
<<"audit_trace_completeness"/utf8>>;
multi_tenant_abuse_regression ->
<<"multi_tenant_abuse_regression"/utf8>>;
regression_gate_determinism ->
<<"regression_gate_determinism"/utf8>>
end.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 93).
?DOC(" Stable pass/fail label.\n").
-spec pass_fail_label(scenario_outcome()) -> binary().
pass_fail_label(Outcome) ->
case erlang:element(3, Outcome) of
true ->
<<"pass"/utf8>>;
false ->
<<"fail"/utf8>>
end.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 101).
?DOC(" Scenario signature accessor.\n").
-spec signature(scenario_outcome()) -> binary().
signature(Outcome) ->
erlang:element(5, Outcome).
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 106).
?DOC(" Scenario accessor.\n").
-spec scenario(scenario_outcome()) -> scenario().
scenario(Outcome) ->
erlang:element(2, Outcome).
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 111).
?DOC(" Determinism accessor.\n").
-spec deterministic(scenario_outcome()) -> boolean().
deterministic(Outcome) ->
erlang:element(4, Outcome).
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 116).
?DOC(" Report outcomes accessor.\n").
-spec outcomes(report()) -> list(scenario_outcome()).
outcomes(Report) ->
erlang:element(2, Report).
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 121).
?DOC(" Failed scenario count.\n").
-spec failed_scenarios(report()) -> integer().
failed_scenarios(Report) ->
erlang:element(3, Report).
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 126).
?DOC(" Nondeterministic scenario count.\n").
-spec nondeterministic_failures(report()) -> integer().
nondeterministic_failures(Report) ->
erlang:element(4, Report).
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 539).
-spec bool_label(boolean()) -> binary().
bool_label(Value) ->
case Value of
true ->
<<"true"/utf8>>;
false ->
<<"false"/utf8>>
end.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 131).
?DOC(" Stable report signature.\n").
-spec report_signature(report()) -> binary().
report_signature(Report) ->
Entries = gleam@list:map(
erlang:element(2, Report),
fun(Outcome) ->
<<<<<<<<<<<<(scenario_label(erlang:element(2, Outcome)))/binary,
"="/utf8>>/binary,
(pass_fail_label(Outcome))/binary>>/binary,
":deterministic="/utf8>>/binary,
(bool_label(erlang:element(4, Outcome)))/binary>>/binary,
":"/utf8>>/binary,
(erlang:element(5, Outcome))/binary>>
end
),
join_with(<<";"/utf8>>, Entries).
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 147).
?DOC(" Deterministic snapshot signature for M52 fixture drift gates.\n").
-spec snapshot_signature() -> binary().
snapshot_signature() ->
<<<<<<"m52.snapshot.v"/utf8, (erlang:integer_to_binary(1))/binary>>/binary,
"|"/utf8>>/binary,
(report_signature(run_matrix()))/binary>>.
-file("src/lightspeed/ops/tenant_expansion_harness.gleam", 155).
?DOC(" Deterministic markdown report for M52 fixture scripts.\n").
-spec snapshot_report_markdown() -> binary().
snapshot_report_markdown() ->
Report = run_matrix(),
Failed = failed_scenarios(Report),
Nondeterministic = nondeterministic_failures(Report),
Status = case (Failed =:= 0) andalso (Nondeterministic =:= 0) of
true ->
<<"OK"/utf8>>;
false ->
<<"FAIL"/utf8>>
end,
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"# Tenant Expansion Fixture Report\n\n"/utf8,
"snapshot_version: "/utf8>>/binary,
(erlang:integer_to_binary(
1
))/binary>>/binary,
"\n"/utf8>>/binary,
"budget_version: "/utf8>>/binary,
(budget_version_label(
))/binary>>/binary,
"\n"/utf8>>/binary,
"status: "/utf8>>/binary,
Status/binary>>/binary,
"\n"/utf8>>/binary,
"failed_scenarios: "/utf8>>/binary,
(erlang:integer_to_binary(
Failed
))/binary>>/binary,
"\n"/utf8>>/binary,
"nondeterministic_failures: "/utf8>>/binary,
(erlang:integer_to_binary(Nondeterministic))/binary>>/binary,
"\n\n"/utf8>>/binary,
"snapshot_signature: "/utf8>>/binary,
(snapshot_signature())/binary>>/binary,
"\n\n"/utf8>>/binary,
"report_signature: "/utf8>>/binary,
(report_signature(Report))/binary>>/binary,
"\n"/utf8>>.