Ship the policy, not the code
When a business rule must be enforced on both the backend and frontend, duplicating logic leads to inevitable drift. Three strategies are explored: sharing code (risky across separate deployments or different languages), shipping the decision (backend returns computed allowed actions like `allowedActions: ['CANCEL']` so the frontend renders state rather than re-deriving it), and shipping the policy (serializing rules via tools like CASL or JSON Schema so only a stable evaluator is shared, not the volatile business logic). The recommendation is to always share something — preferably as data — rather than letting the same invariant live in two places.