Problem
src/hooks/useEmployerApplications.ts:257-288 — updateStatus issues an .update() with no .select(). PostgREST returns success with zero rows affected when RLS filters the target out, so error is null and the hook proceeds to mutate local state and adjust the funnel counts regardless.
Failure scenario
- An admin removes an employer from
employer_company_links while that employer has the console open.
- The employer drags an application card from "applied" to "interviewing".
- The RLS policy no longer matches the row → 0 rows updated, no error returned.
:265-267 flips the local row to "interviewing" and :280-286 increments the funnel bar.
- The employer sees a successful move. Nothing was written.
- On refresh everything snaps back, with no explanation.
The same shape applies to any transient RLS or connectivity condition — the UI always reports success.
Fix
Add .select() and treat an empty result as a failure:
const { data, error } = await supabase
.from('job_applications')
.update({ status: next })
.eq('id', id)
.select('id');
if (error) throw error;
if (!data?.length) throw new Error('Update affected no rows — permission or row missing');
Then roll back the optimistic state and surface it to the user rather than silently diverging.
Note
Same class as #71 (a write that appears to succeed but wrote nothing) and the non-transactional writes in admin-moderation-service.ts. Worth a sweep for other .update() / .delete() calls in src/ that don't check an affected-row count — this pattern is likely not unique to this hook.
Problem
src/hooks/useEmployerApplications.ts:257-288—updateStatusissues an.update()with no.select(). PostgREST returns success with zero rows affected when RLS filters the target out, soerroris null and the hook proceeds to mutate local state and adjust the funnel counts regardless.Failure scenario
employer_company_linkswhile that employer has the console open.:265-267flips the local row to "interviewing" and:280-286increments the funnel bar.The same shape applies to any transient RLS or connectivity condition — the UI always reports success.
Fix
Add
.select()and treat an empty result as a failure:Then roll back the optimistic state and surface it to the user rather than silently diverging.
Note
Same class as #71 (a write that appears to succeed but wrote nothing) and the non-transactional writes in
admin-moderation-service.ts. Worth a sweep for other.update()/.delete()calls insrc/that don't check an affected-row count — this pattern is likely not unique to this hook.