| id |
name |
namespace |
version |
status |
package |
actions |
owner |
fixtures |
caring |
activation |
metadata |
| qonto-assistant.finance-read |
qonto-assistant finance.qonto.read authorization |
qonto-assistant:finance |
v1 |
ready |
flexauth.qonto_assistant.finance_read |
|
team:platform-security |
|
| profile |
enforce |
canonical_roles |
organization_relations |
scopes |
planes |
capabilities |
exposure_modes |
conditions |
restrictions |
| caring-0.4.0-rc2 |
false |
|
|
| level |
id |
tenant |
| Tenant |
tenant:friendly:binky |
tenant:friendly:binky |
|
|
|
|
|
|
| PrivilegeEscalationBlocked |
|
|
|
| source |
flex_auth_contract |
| examples/qonto-assistant/policy_package.md |
protected-system-v0 |
|
qonto-assistant finance.qonto.read authorization
This package authorizes qonto-assistant's read surface
(QONTO-WP-0004-T04's live authorization gate). qonto-assistant keeps
custody of the bank credential and its own default-deny policy kernel
(spend/transfer/card/write tools are hard-denied there and never reach this
policy); flex-auth decides whether a specific actor may use the
finance.qonto.read capability at all.
Scope note: this policy governs who may call finance.qonto.read (an
actor/tenant question) — it does not evaluate a tenant's capability roles
or plan status (PLTF/IAM/VEN/CUS, ADR-0014). Those are tenant state
qonto-assistant checks separately via tenant-engine's live-lookup
endpoint (GET /tenants/{id}/roles/live); conflating the two here would
authorize the wrong thing, exactly as tenant-engine's own
policy_package.md notes for its analogous case.
Single-tenant dogfood today (tenant:friendly:binky only); generalizing to
other tenants is a policy update here, not a qonto-assistant code change.
Rules
import future.keywords.contains
import future.keywords.if
import future.keywords.in
valid_actions := {"finance.qonto.read"}
valid_subject_types := {"agent", "human", "service"}
known_tenant := "tenant:friendly:binky"
decision := {"effect": "allow", "reason": "finance_read_policy_matched"} if {
allowed
} else := {"effect": "deny", "reason": first_denial} if {
true
}
allowed if {
input.resource.system == "qonto-assistant"
input.action in valid_actions
input.subject.type in valid_subject_types
input.tenant == known_tenant
}
default first_denial := "no_matching_rule"
first_denial := "wrong_system" if {
input.resource.system != "qonto-assistant"
} else := "unknown_action" if {
not input.action in valid_actions
} else := "wrong_subject_type" if {
not input.subject.type in valid_subject_types
} else := "wrong_tenant" if {
input.tenant != known_tenant
}
Tests
package flexauth.qonto_assistant.finance_read_test
import future.keywords.if
import data.flexauth.qonto_assistant.finance_read
base_request := {
"id": "check:qonto-assistant-read",
"tenant": "tenant:friendly:binky",
"subject": {"id": "agent-harness-binky", "type": "agent"},
"action": "finance.qonto.read",
"resource": {"id": "finance-snapshot", "type": "finance-snapshot", "system": "qonto-assistant"}
}
test_agent_read_allowed if {
finance_read.decision.effect == "allow" with input as base_request
}
test_human_read_allowed if {
finance_read.decision.effect == "allow" with input as {
"tenant": "tenant:friendly:binky",
"subject": {"id": "bernd.worsch", "type": "human"},
"action": "finance.qonto.read",
"resource": {"id": "finance-snapshot", "type": "finance-snapshot", "system": "qonto-assistant"}
}
}
test_wrong_system_denied if {
finance_read.decision.reason == "wrong_system" with input as {
"tenant": "tenant:friendly:binky",
"subject": {"id": "agent-harness-binky", "type": "agent"},
"action": "finance.qonto.read",
"resource": {"id": "x", "type": "finance-snapshot", "system": "some-other-system"}
}
}
test_unknown_action_denied if {
finance_read.decision.reason == "unknown_action" with input as {
"tenant": "tenant:friendly:binky",
"subject": {"id": "agent-harness-binky", "type": "agent"},
"action": "finance.qonto.transfer",
"resource": {"id": "finance-snapshot", "type": "finance-snapshot", "system": "qonto-assistant"}
}
}
test_wrong_subject_type_denied if {
finance_read.decision.reason == "wrong_subject_type" with input as {
"tenant": "tenant:friendly:binky",
"subject": {"id": "unknown-device", "type": "device"},
"action": "finance.qonto.read",
"resource": {"id": "finance-snapshot", "type": "finance-snapshot", "system": "qonto-assistant"}
}
}
test_wrong_tenant_denied if {
finance_read.decision.reason == "wrong_tenant" with input as {
"tenant": "tenant:friendly:some-other-company",
"subject": {"id": "agent-harness-binky", "type": "agent"},
"action": "finance.qonto.read",
"resource": {"id": "finance-snapshot", "type": "finance-snapshot", "system": "qonto-assistant"}
}
}