fix(incidents): re-assert hardened incidents_insert policy + clearer error

Production: a basic member filing an incident (incl. anonymous) hit an
RLS violation on table incidents. Not reproducible from source; the code
and the 016/017 policy both permit it, so it is a deployed policy/data
divergence.

- scripts/025 idempotently re-asserts incidents_insert verbatim from
  017/schema.sql so a drifted deployment converges to the known-good
  policy. Access-neutral, no schema change.
- fileIncident maps an RLS rejection to an actionable message and logs
  the technical detail server-side instead of raw Postgres.

Minimal hotfix off origin/main: only the two production-affecting files.
If the report persists post-deploy the cause is not policy drift; the
discriminating SQL is tracked in the local stack's HANDOFF.
This commit is contained in:
Moheeb Zara
2026-05-15 22:11:33 -07:00
parent 4c9b55147b
commit 1340b4cd79
2 changed files with 70 additions and 1 deletions
+21 -1
View File
@@ -70,7 +70,27 @@ export async function fileIncident(formData: {
.select()
.single()
if (error) return { error: error.message }
if (error) {
// A row-level-security rejection here means the caller's membership is not
// resolving against this space in the database (see scripts/025 header).
// The raw Postgres text is not actionable for a reporter, so surface a
// clear message and keep the technical detail in the server log.
const isRls = error.code === '42501' || /row-level security/i.test(error.message)
if (isRls) {
console.error('fileIncident RLS rejection', {
space_id: member.space_id,
member_id: member.id,
is_anonymous: isAnonymous,
code: error.code,
message: error.message,
})
return {
error:
'Could not file the report: your membership is not fully linked to this space. Contact a space admin.',
}
}
return { error: error.message }
}
// Don't include the reporter's identity in the activity log if anonymous.
await logActivity(