Deny reasons beat silent 403s
A bare 403 tells the client “no.” It does not tell the engineer why.
When an authorization check fails, return a stable reason code alongside the deny — missing role, wrong tenant, relationship not found, policy expired. Keep the message safe for the client (no secrets), and log the full decision server-side.
That habit turns “it doesn’t work” into a fixable ticket: you can see whether the role is wrong, the resource mapping is missing, or the policy never loaded. Silent denies waste hours; explainable denies teach the system and the team.
