79 lines
2 KiB
Rego
79 lines
2 KiB
Rego
# METADATA
|
|
# title: Data source policy for ds:receipts
|
|
# description: |
|
|
# Governs who may upload (write) and who may read receipts.
|
|
# Receipts are PII. agent-travel uploads during the chat; downstream agents
|
|
# may only read by content_hash and only within an active user session.
|
|
# authors:
|
|
# - CTO Agent <cto@basicstack.de>
|
|
# related_resources:
|
|
# - ref: docs/architecture/v1.1.md#user-content-47-belege-receipts--upload-hashbindung-lesezugriff-entlang-der-kette
|
|
# - ref: schemas/ds/receipts/v1.0.0.json
|
|
package proofedmesh.data_sources.receipts
|
|
|
|
import rego.v1
|
|
|
|
default allow := false
|
|
|
|
allow if {
|
|
input.data_source == "ds:receipts"
|
|
input.user_sub != ""
|
|
input.session_id != ""
|
|
some rule in agent_scope_rules
|
|
rule.agent_id == input.agent_id
|
|
rule.operation == input.operation
|
|
filters_ok(rule)
|
|
}
|
|
|
|
agent_scope_rules := [
|
|
{
|
|
"agent_id": "agent-travel",
|
|
"operation": "write",
|
|
"required_filters": set(),
|
|
"allowed_filters": set(),
|
|
},
|
|
{
|
|
"agent_id": "agent-sink-mapping",
|
|
"operation": "read",
|
|
"required_filters": {"content_hash"},
|
|
"allowed_filters": {"content_hash"},
|
|
},
|
|
{
|
|
"agent_id": "agent-sink-posting",
|
|
"operation": "read",
|
|
"required_filters": {"content_hash"},
|
|
"allowed_filters": {"content_hash"},
|
|
},
|
|
]
|
|
|
|
filters_ok(rule) if {
|
|
rule.operation == "write"
|
|
}
|
|
|
|
filters_ok(rule) if {
|
|
rule.operation == "read"
|
|
provided := {k | some k; _ := input.filters[k]}
|
|
count(provided - rule.allowed_filters) == 0
|
|
count(rule.required_filters - provided) == 0
|
|
}
|
|
|
|
deny_reason contains msg if {
|
|
input.data_source != "ds:receipts"
|
|
msg := sprintf("wrong data_source: %s", [input.data_source])
|
|
}
|
|
|
|
deny_reason contains msg if {
|
|
input.user_sub == ""
|
|
msg := "missing user_sub (receipts always require an active user session)"
|
|
}
|
|
|
|
deny_reason contains msg if {
|
|
not any_rule_matches
|
|
msg := sprintf("no scope rule for agent=%s op=%s", [input.agent_id, input.operation])
|
|
}
|
|
|
|
any_rule_matches if {
|
|
some rule in agent_scope_rules
|
|
rule.agent_id == input.agent_id
|
|
rule.operation == input.operation
|
|
}
|