ProofedMesh/policies/transformations/expense_test.rego

299 lines
8.4 KiB
Rego
Raw Permalink Normal View History

package proofedmesh.transformations.expense_test
import data.proofedmesh.transformations.expense
import rego.v1
# ------------------------------------------------------------------
# v1.0.0 — flat single-project (unchanged behaviour)
# ------------------------------------------------------------------
canonical_payload := {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "428.50",
}
sink_payload := {"expense": {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "428.50",
}}
test_allow_map_to_sink if {
expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.0.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.0.0"},
"input_payload": canonical_payload,
"output_payload": sink_payload,
}
}
test_deny_unknown_agent if {
not expense.allow with input as {
"agent_id": "agent-rogue",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.0.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.0.0"},
"input_payload": canonical_payload,
"output_payload": sink_payload,
}
}
test_deny_schema_mismatch if {
not expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.0.0"},
"output_schema": {"name": "sink.db.expense", "version": "2.0.0"},
"input_payload": canonical_payload,
"output_payload": sink_payload,
}
}
test_deny_total_amount_change if {
tampered := {"expense": {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "999.99",
}}
not expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.0.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.0.0"},
"input_payload": canonical_payload,
"output_payload": tampered,
}
}
test_deny_currency_change if {
tampered := {"expense": {
"employee_id": "EMP-12345",
"currency": "USD",
"total_amount": "428.50",
}}
not expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.0.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.0.0"},
"input_payload": canonical_payload,
"output_payload": tampered,
}
}
test_deny_employee_change if {
tampered := {"expense": {
"employee_id": "EMP-99999",
"currency": "EUR",
"total_amount": "428.50",
}}
not expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.0.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.0.0"},
"input_payload": canonical_payload,
"output_payload": tampered,
}
}
test_deny_posting_agent_cannot_map if {
not expense.allow with input as {
"agent_id": "agent-sink-posting",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.0.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.0.0"},
"input_payload": canonical_payload,
"output_payload": sink_payload,
}
}
# ------------------------------------------------------------------
# v1.1.0 — per-line allocations
# ------------------------------------------------------------------
canonical_v11 := {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "428.50",
}
sink_v11_two_items_split := {"expense": {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "428.50",
"items": [
{
"amount": "328.50",
"allocations": [
{"amount": "197.10"},
{"amount": "131.40"},
],
},
{
"amount": "100.00",
"allocations": [
{"amount": "70.00"},
{"amount": "30.00"},
],
},
],
}}
test_allow_v110_map_to_sink_split if {
expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.1.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.1.0"},
"input_payload": canonical_v11,
"output_payload": sink_v11_two_items_split,
}
}
test_deny_v110_allocation_sum_mismatch if {
bad_sink := {"expense": {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "428.50",
"items": [
{
"amount": "328.50",
"allocations": [
{"amount": "197.10"},
{"amount": "131.50"}, # 328.60, nicht 328.50
],
},
{
"amount": "100.00",
"allocations": [
{"amount": "70.00"},
{"amount": "30.00"},
],
},
],
}}
not expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.1.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.1.0"},
"input_payload": canonical_v11,
"output_payload": bad_sink,
}
}
test_allow_v110_single_allocation if {
one := {"expense": {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "428.50",
"items": [
{"amount": "328.50", "allocations": [{"amount": "328.50"}]},
{"amount": "100.00", "allocations": [{"amount": "100.00"}]},
],
}}
expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.1.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.1.0"},
"input_payload": canonical_v11,
"output_payload": one,
}
}
test_v110_still_enforces_total_currency_employee if {
tampered_total := {"expense": {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "999.99",
"items": [{"amount": "328.50", "allocations": [{"amount": "328.50"}]}],
}}
not expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.1.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.1.0"},
"input_payload": canonical_v11,
"output_payload": tampered_total,
}
}
test_allow_v110_normalize if {
# normalize keeps canonical v1.1.0 shape, no sink allocation check applies.
expense.allow with input as {
"agent_id": "agent-travel",
"operation": "expense.normalize",
"input_schema": {"name": "expense.canonical", "version": "1.1.0"},
"output_schema": {"name": "expense.canonical", "version": "1.1.0"},
"input_payload": canonical_v11,
"output_payload": {"expense": canonical_v11},
}
}
# ------------------------------------------------------------------
# v1.2.0 — allocations + receipts + per-diem items (map_to_sink)
# ------------------------------------------------------------------
canonical_v12 := {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "484.50",
}
sink_v12_mixed := {"expense": {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "484.50",
"items": [
{"amount": "328.50", "allocations": [{"amount": "328.50"}]},
{"amount": "14.00", "allocations": [{"amount": "14.00"}]},
{"amount": "28.00", "allocations": [{"amount": "28.00"}]},
{"amount": "14.00", "allocations": [{"amount": "14.00"}]},
{"amount": "100.00", "allocations": [{"amount": "100.00"}]},
],
}}
test_allow_v120_map_to_sink_mixed_items if {
expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.2.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.2.0"},
"input_payload": canonical_v12,
"output_payload": sink_v12_mixed,
}
}
test_deny_v120_allocation_sum_mismatch if {
bad := {"expense": {
"employee_id": "EMP-12345",
"currency": "EUR",
"total_amount": "484.50",
"items": [{"amount": "328.50", "allocations": [{"amount": "328.51"}]}],
}}
not expense.allow with input as {
"agent_id": "agent-sink-mapping",
"operation": "expense.map_to_sink",
"input_schema": {"name": "expense.canonical", "version": "1.2.0"},
"output_schema": {"name": "sink.db.expense", "version": "1.2.0"},
"input_payload": canonical_v12,
"output_payload": bad,
}
}
test_allow_v120_normalize if {
expense.allow with input as {
"agent_id": "agent-travel",
"operation": "expense.normalize",
"input_schema": {"name": "expense.canonical", "version": "1.2.0"},
"output_schema": {"name": "expense.canonical", "version": "1.2.0"},
"input_payload": canonical_v12,
"output_payload": {"expense": canonical_v12},
}
}