Operation names are open vocabulary and nothing checks that the two sides agree, so a typo or a rename goes quiet instead of loud, in both directions.
An allow line naming an operation nothing asks about does nothing. The line is there, it looks like a rule, and it has no effect.
A can? or authorize naming an operation nothing declares is always false. That one is worse - the answer is a legal one, so the button just never appears and nothing fails.
Both of these happened here when #1187 renamed the grant gates. The demo app kept allow :manage_roles and lost its rule without a word, and the features app kept can?(user, :manage_roles, doc), which would have answered false forever if that commit hadn't happened to touch the line. Everything compiled and every test stayed green.
Most operation names are literals, so the compiler can see both sides and say so. The rest are computed at runtime, where the check has to happen instead.
While in there: the code calls these "policy operations" in four places, which names the wrong owner. An operation is a verb on an entity - can?(user, :delete, post) answers on a type with no policy at all - and a policy is a set of rules about who may perform one. lib/hologram/policy.ex:272, lib/hologram/query.ex:83, lib/hologram/entity.ex:23, lib/hologram/entity/validator.ex:1141, plus the 2026-08-10 vocabulary lock in 08-mutations.md, which chose the word and shouldn't have implied the owner.
Operation names are open vocabulary and nothing checks that the two sides agree, so a typo or a rename goes quiet instead of loud, in both directions.
An allow line naming an operation nothing asks about does nothing. The line is there, it looks like a rule, and it has no effect.
A
can?orauthorizenaming an operation nothing declares is always false. That one is worse - the answer is a legal one, so the button just never appears and nothing fails.Both of these happened here when #1187 renamed the grant gates. The demo app kept
allow :manage_rolesand lost its rule without a word, and the features app keptcan?(user, :manage_roles, doc), which would have answered false forever if that commit hadn't happened to touch the line. Everything compiled and every test stayed green.Most operation names are literals, so the compiler can see both sides and say so. The rest are computed at runtime, where the check has to happen instead.
While in there: the code calls these "policy operations" in four places, which names the wrong owner. An operation is a verb on an entity -
can?(user, :delete, post)answers on a type with no policy at all - and a policy is a set of rules about who may perform one.lib/hologram/policy.ex:272,lib/hologram/query.ex:83,lib/hologram/entity.ex:23,lib/hologram/entity/validator.ex:1141, plus the 2026-08-10 vocabulary lock in08-mutations.md, which chose the word and shouldn't have implied the owner.