Skip to content

financial.rego

Allow rules for the most common transactional and read-side actions. Unlike the other modules, financial.rego defines deny and hitl as partial sets (no default boolean) so YAML-compiled rules — which emit deny[reason] if { … } and hitl[reason] if { … } — can extend them without colliding with a boolean default.

Package: kitelogik.financial · Source: kitelogik/policies/financial.rego

Rules

ActionAllowed whenRisk-tier hint (set by main.rego)
read_customer_record, list_transactionsSession has the read_customer scopeINFORMATIONAL
approve_refund (≤ $100)Role ∈ {support_agent, manager, worker_agent} and scope approve_refund_under_100 and amount in [0, 100]TRANSACTIONAL_LOW
approve_refund (≤ $1000)Role = manager and scope approve_refund_under_1000 and amount in [0, 1000]TRANSACTIONAL_HIGH (HITL on > $100, by main.rego)
send_notificationSession has the send_notifications scope(default OPERATIONAL)
query_memoryAny active session (non-empty session_id)(default OPERATIONAL)
write_memorySession has the memory_write scope(default OPERATIONAL)
execute_codecontext.sandbox_verified == true(default OPERATIONAL) — without sandbox, security.rego hard-denies

All amount checks use is_number(...) first to close the OPA structural-ordering bypass (null < 0 would otherwise satisfy inequality silently).

Selected source

rego
# Allow low-value refunds for support agents and delegated workers
allow if {
    input.action == "approve_refund"
    input.context.user_role in {"support_agent", "manager", "worker_agent"}
    "approve_refund_under_100" in input.context.session_scopes
    is_number(input.args.amount)
    input.args.amount >= 0
    input.args.amount <= 100
}

# Allow higher-value refunds for managers with elevated scope
allow if {
    input.action == "approve_refund"
    input.context.user_role == "manager"
    "approve_refund_under_1000" in input.context.session_scopes
    is_number(input.args.amount)
    input.args.amount >= 0
    input.args.amount <= 1000
}

How main.rego uses this module

main.rego aggregates this module's allow rules:

rego
# Allow if a sub-policy grants access AND security/delegation don't deny
allow if { not deny; financial.allow }

To extend financial governance with your own rules, write them in YAML (then: allow / then: hitl / then: deny) and compile — they land in the kitelogik.userpolicy package, which main.rego aggregates the same way:

rego
allow if { not deny; userpolicy.allow }
deny if { some msg; userpolicy.deny[msg] }
requires_hitl if { some msg; userpolicy.hitl[msg] }

So you never edit main.rego or this module directly — your compiled YAML is picked up automatically.

Extending in your own project

The intended path is YAML rather than editing the OSS rego directly:

yaml
# policies/refund_extras.yaml
version: 1
rules:
  - name: block_weekend_refunds
    when:
      action: approve_refund
      args:
        amount: { gt: 0 }
    then: deny
    reason: "Refunds disabled outside business hours"

Compile with kitelogik compile policies/refund_extras.yaml — the rules land in the kitelogik.userpolicy package. The main.rego aggregator then sees userpolicy.deny["Refunds disabled outside business hours"] on every refund event, which becomes a hard deny.

For more complex extensions (cross-event invariants, time-of-day rules), write Rego directly in the kitelogik.userpolicy package using a set-valued deny[reason] if {...} rule — main.rego aggregates those the same way.

Released under the Apache 2.0 License.