The most common defect we find when auditing an admin panel is a permission that exists only in the interface. A status field is hidden from editors, a delete button is conditionally rendered, a menu item is filtered out of the sidebar. Each of those is correct and each of those is insufficient, because none of them is enforced when the request arrives.
Enforce the transition, not the widget
Take publishing. The rule is that an author may write drafts but may not make content public. If that rule lives in the form schema, an author who posts a crafted request — or who uses an export, an import, or a bulk action that was added later — publishes content anyway.
We now put the rule on the model boundary. A saving hook inspects the status transition and refuses it unless the acting user holds the publishing permission. The form still hides the field, because showing a control a user cannot use is bad design, but the form is no longer the thing that makes it safe.
Fail closed, and test the refusal
Default every check to denial and grant explicitly. Then write the test that matters: not that an admin can publish, but that an author cannot, asserted against the model rather than the screen. Those are the tests that keep passing when someone adds a new entry point six months from now.
Tagged
Comments
Sign in to join the discussion.