PE3b — the SupportsDeny leg of catalog↔class agreement, asserted ASYMMETRICALLY because the two
directions have opposite safety properties:
Row says Deny, class says no → a hard FAILURE. An admin UI reading the catalog would
offer a Deny grant that the provider silently ignores when evaluating. That is a real
security hole: an operator believes they revoked access and they did not.
Class says Deny, row says no → a WARNING. The capability is under-advertised, so the UI
simply never offers Deny. Fail-safe, but still drift worth surfacing.
KNOWN FINDING (as of this bundle landing): Entity Permissions is in the WARN direction —
EntityPermissionProvider.SupportsDeny = true (Phase 2b added the Allow/Deny Type column to
MJ: Entity Permissions and GetUserPermisions honors it), but every row in
metadata/permission-domains/.permission-domains.json still declares SupportsDeny: false.
Net effect: Deny rows ARE enforced at runtime but no admin surface offers to create them.
Fixing that is a product decision (update the metadata row + mj sync push), not a test change.
PE3b — the SupportsDeny leg of catalog↔class agreement, asserted ASYMMETRICALLY because the two directions have opposite safety properties:
KNOWN FINDING (as of this bundle landing):
Entity Permissionsis in the WARN direction —EntityPermissionProvider.SupportsDeny = true(Phase 2b added the Allow/DenyTypecolumn toMJ: Entity PermissionsandGetUserPermisionshonors it), but every row inmetadata/permission-domains/.permission-domains.jsonstill declaresSupportsDeny: false. Net effect: Deny rows ARE enforced at runtime but no admin surface offers to create them. Fixing that is a product decision (update the metadata row +mj sync push), not a test change.