Why this keeps going wrong
More backends are shipping than ever, written faster than ever, often by people who did not read the access rules that came with them. The default gets shipped. Nobody notices until someone else does.
This is not hypothetical. A permissive default is what put thousands of indie apps online with their user tables readable by anyone holding a public key.
Why the usual tools do not help
Every scanner for this works from the outside. You hand it a live URL, it pulls your config out of your own frontend bundle, and it probes your tables the way an attacker would. That only works once the app is public, which means it only ever tells you about a leak after strangers could already read the data.
Answering it offline instead
CrescoDB owns your schema, so the same question can be answered from a file in version control, before anything leaves your machine.
Graded by what is exposed, not whether
This is the part worth understanding, because it is why the check stays useful.
- A public price list is a note. A price list is supposed to be public. Flagging it would be noise.
- A public table holding an email, a phone number or a diagnosis is a critical. It stops the deploy.
- A table any signed-in user can read every row of is a warning, because authentication alone does not stop user A reading user B's rows. That needs per-row ownership.
A checker that cries wolf gets muted, and a muted checker protects nobody.
Wiring it into CI
cresco audit --json gives machine-readable findings and a blocksDeploy verdict, and exits non-zero on a critical, so a pipeline can gate on it.
Catching it while you type
The VS Code extension runs the same audit on save and puts findings as squiggles on the offending line, with a quick fix on the lightbulb. Same implementation as the deploy check, so the editor and the deploy can never disagree.