Risemi
Filters1
> Assumption: signed-in users read their own orders and create their own orders as `pending`; every status change after that is made by your server with the `service_role` key, never by the browser.

Audit: `public.orders` (about 1.8M rows)

Rule files applied: `security-rls-basics`, `security-rls-performance`, `security-privileges`, `schema-foreign-key-indexes`, `query-missing-indexes`, `query-composite-indexes`, `schema-data-types`, `schema-constraints`, `lock-short-transactions`, `monitor-explain-analyze`.

Findings, by rule (first 6 of 12)

| # | Severity | Rule | Finding |
|---|---|---|---|
| 1 | CRITICAL | `security-rls-basics` | `orders_insert ... with check (true)` lets anyone who can insert write an order for any `user_id`. Combined with finding 2, an anonymous visitor holding only your public anon key can create orders on behalf of any user. |
| 2 | CRITICAL | `security-privileges` | `grant select, insert, update ... to anon`. Orders belong to signed-in users, so `anon` needs no privilege at all. None of the three policies has a `to` clause, so each applies to every role, including `anon`. |
| 3 | HIGH | `security-privileges` | `authenticated` can `update` every column of its own rows: the owner can still run `update orders set status = 'paid', total_cents = 1` from the browser. |
| 4 | HIGH | `security-rls-basics` | The insert path also trusts `status`: a client can insert a row that is already `status = 'paid'`. |
| 5 | HIGH | `security-rls-performance` | All policies call `auth.uid()` bare, so it is evaluated per row. Wrap it as `(select auth.uid())` so it is evaluated once per statement. |
| 6 | HIGH | `schema-foreign-key-indexes`, `query-missing-indexes` | No index on `user_id`. It is the foreign key, the RLS filter column and the column every "my orders" query filters on. Each RLS-filtered select over 1.8M rows is a sequential scan. |

Fixing migration (file 1 of 2, excerpt)

```sql
set local lock_timeout = '5s';

revoke all on public.orders from anon;
revoke update, delete, truncate, references, trigger on public.orders from authenticated;
grant select, insert on public.orders to authenticated;

drop policy if exists orders_select on public.orders;
drop policy if exists orders_insert on public.orders;
drop policy if exists orders_update on public.orders;

create policy orders_select on public.orders
  for select to authenticated
  using ((select auth.uid()) = user_id);

create policy orders_insert on public.orders
  for insert to authenticated
  with check ((select auth.uid()) = user_id and status = 'pending');
-- No update or delete policy: denied for every role except service_role.
```

File 2 holds only `create index concurrently if not exists orders_user_id_created_at_idx on public.orders (user_id, created_at desc);` because `concurrently` cannot run inside the transaction the Supabase CLI wraps around each migration.

[The full answer continues with findings 7–12, the lock plan for 1.8M rows, the status and total_cents check constraints added `not valid` then validated, an `explain analyze` to run before and after, and one RLS test per role.]
SkillCodePro
  • Antigravity
  • Claude Code
  • Codex
  • +3
Coding

Postgres Rules for Supabase Projects

Use it to make your coding agent follow Supabase's 31 Postgres rules for RLS, indexes, schema and migrations before it touches your database.

0 installs
$9.99
PILLAR — "The async standup playbook: how 14 distributed teams dropped the 9 AM call"
Keyword: async standup (~1,900/mo) · Intent: informational, late-stage
Gap in current top results: none give a template by team size; all assume 5–8 people.
H2s: Why the sync standup breaks past 3 time zones / The 3 formats by team size / Slack + Notion templates / What to do when nobody posts / Daily vs weekly / Tools compared honestly

Supporting articles
1. "Async standup template (Slack and Notion versions)" — async standup template (~720) · transactional · links to H2 #3
2. "Why your async standup is being ignored — and the 3-line fix" — async standup not working (~210) · informational · H2 #4
3. "Daily or weekly async standup for a 6-person team?" — daily vs weekly standup (~140) · comparison · H2 #5
4. "Async standup across 5+ time zones: what actually works" — async standup timezone (~95) · informational · H2 #1
...
Publishing order: 1, 2, 4 first (quick wins, low competition), pillar in week 3, remaining support weeks 4–6.
PromptDataPro
  • ChatGPT
  • Claude
  • Gemini
Marketing

SEO Content Cluster Map

One pillar page plus eight supporting articles, each a real search question with keyword, intent and link map.

0 copies
$3.99
Top 5 unmet needs (67 interviews)

1. Onboarding takes too long — 41 customers
   "I gave up before my first usable result." (I-12) · "Two evenings to set up something I wanted to try in ten minutes." (I-38)
   Trigger: trying the product between meetings, on a phone.
2. Sharing with the team is friction — 33
   "I ended up screenshotting the dashboard into Slack." (I-05)
3. Integration with the existing stack — 29
4. Pricing surprise in month two — 24
5. Progress does not sync between devices — 18

Early signals
- Offline mode — I-12, I-38, I-51: "I'd pay for it to just work on the train." Unprompted in three separate interviews; not noise.
- Public API — I-22 only.

Contradictions
- 14 customers want fewer notifications; 9 want a daily nudge. Both groups are under 30 days in.

Say vs. want
- Say: "more features." Want, from behaviour: the three they already use to be faster. (I-07, I-44)

Follow-ups for next round
1. "What did you expect to have working within ten minutes?"
2. "Who else looks at this, and how do they see it today?"
PromptDataPro
  • Claude
  • Gemini
Research

Cluster 400 Pages of Interviews

Feed every transcript at once; get ranked unmet needs with verbatim quotes, early signals, contradictions.

0 copies
$5.99
Ranked causes

1. Creative launch pushed spend into a worse-converting audience (fit: HIGH)
Mechanism: three new creatives entered learning Monday; Meta over-delivers early impressions to cheap, low-intent placements.
Supports: spike begins the same day; recovery by Sunday matches a 5–7 day learning window.
Contradicts: nothing in the inputs — but you have not split CAC by creative yet.

2. Competitor promo raised auction prices Tue–Thu (fit: MEDIUM)
Supports: Tuesday start; CPM data would show it.
Contradicts: the spike started Monday, a day before the promo.

3. +30% budget scale on the top campaign reset learning (fit: MEDIUM-LOW)
Supports: scaling same day. Contradicts: a 30% step rarely resets learning on its own.

Next data cut: CAC and CPM by creative, by day, Mon–Sun. If the three new creatives carry a CAC over $90 on Mon–Wed while legacy creatives stay near $48, cause 1 is confirmed.

Not considered: a tracking gap — check whether the pixel fired normally Mon–Wed before trusting any of this.
Do not: pause the new creatives today. You would destroy the data that tells you which of them is fine.
PromptDataPro
  • ChatGPT
  • Claude
Marketing

CAC Spike Diagnosis

Three ranked causes for a metric anomaly, the one data cut that confirms the top cause, and what not to do.

0 copies
$3.99