Marked as helpful by the asker
The dashboard runs as postgres, which bypasses RLS, so it will always work there. That's why it feels inconsistent.
Your policy is fine. The usual cause is that the insert doesn't include user_id, so auth.uid() = null is false. Check what your app actually sends:
await supabase.from('orders').insert({ ...order, user_id: user.id })Better: give the column a default so the client can't get it wrong:
alter table orders alter column user_id set default auth.uid();