The 28 tests prove the policies against the entities in tests.json, but production decisions run against the real grant store, and the suite never sees it. If someone adds billing to the support-assistant agent's write_groups, every test still passes. Since the Agent entity isn't per tenant, that one change reaches every tenant whose users and tenant already hold billing.
Because grants are data, I'd give the data its own check. On each change to the entity store, run cedar authorize for every agent, tool and action in each tenant, keep the set of ALLOWs, and diff it against the last run. Any new ALLOW on write or destroy goes to a reviewer before the change takes effect. That gives grant changes the same scrutiny your policy files already get.
Agreed, and this is the real gap in Part 2. The suite proves the policies over the entities in tests.json; mutation testing proves each policy earns its keep. Neither says anything about the grants production actually loads. And because Agent carries no tenant, adding billing to support-assistant’s write_groups is one edit with a blast radius of every tenant whose users and tenant already hold billing.
Your diff is the right shape. Three refinements from trying it:
You don’t have to enumerate users. Effective permission is agent ∩ user ∩ tenant, so the ceiling across all users of a tenant is agent ∩ tenant. Enumerate (agent, tenant, tool, action) with a synthetic user holding exactly the tenant’s groups. User-grant changes get their own, per-tenant diff.
Set delegated_read_groups / delegated_write_groups to the full set so the run computes the ceiling rather than one task type’s scope.
destroy is never allowed without an approval, so either supply a synthetic valid approval (same tenant, holds the grant, fresh, matching hash) or diff on write and treat destroy as write plus approval.
Then: stage the new entity store, compute the ALLOW set, diff against the promoted one, and any new ALLOW on write/destroy blocks promotion until reviewed. It’s the data equivalent of the policy mutation test. Cedar’s symbolic analyser compares policies, not entity data, so this is a loop over cedar authorize (or the library Authorizer), not a solver job.
The underlying choice is whether Agent should stay tenant-global. A per-tenant enablement attribute would shrink the blast radius, at the cost of one more thing each tenant administers. Either way the grant diff is worth having.
Mike Dabydeen
The 28 tests prove the policies against the entities in tests.json, but production decisions run against the real grant store, and the suite never sees it. If someone adds billing to the support-assistant agent's write_groups, every test still passes. Since the Agent entity isn't per tenant, that one change reaches every tenant whose users and tenant already hold billing.
Because grants are data, I'd give the data its own check. On each change to the entity store, run cedar authorize for every agent, tool and action in each tenant, keep the set of ALLOWs, and diff it against the last run. Any new ALLOW on write or destroy goes to a reviewer before the change takes effect. That gives grant changes the same scrutiny your policy files already get.