|
| 1 | +# Design — `warn-curl-mutating-supabase-rest` |
| 2 | + |
| 3 | +## Pattern |
| 4 | + |
| 5 | +``` |
| 6 | +'curl.*-X[[:space:]]+(POST|PATCH|PUT|DELETE).*\.supabase\.co/rest/v1/' |
| 7 | +``` |
| 8 | + |
| 9 | +Rationale: |
| 10 | + |
| 11 | +- Anchor on the explicit `-X <METHOD>` form. `curl` defaults to `GET`, and |
| 12 | + any author using a mutating method invariably types it as `-X POST` / |
| 13 | + `-X PATCH` / `-X PUT` / `-X DELETE`. (Curl also accepts `--request`, but |
| 14 | + the long form is uncommon enough that we accept the false negative — |
| 15 | + authors using `--request` can be expected to know the rule and self-flag.) |
| 16 | +- Match `.supabase.co/rest/v1/` rather than just `.supabase.co` so we don't |
| 17 | + flag mutations against Supabase Auth / Storage endpoints (those have |
| 18 | + separate guidance) or Edge Functions (which are exempt — they're the |
| 19 | + intended outlet). |
| 20 | +- Use `i` flag for case-insensitivity on the method names. |
| 21 | + |
| 22 | +## Action |
| 23 | + |
| 24 | +`warn`, not `block`. The rule is a nudge, not a hard stop — there are |
| 25 | +legitimate reasons to issue a one-shot REST mutation (e.g. seeding a |
| 26 | +local-only fixture, debugging an Edge Function invocation chain). The |
| 27 | +`warn-psql-against-supabase-remote` neighbor uses the same severity; they |
| 28 | +are the same class of nudge. |
| 29 | + |
| 30 | +## Bypass marker |
| 31 | + |
| 32 | +`curl-supabase-rest-mutation` — kebab-case, unique. Documented as |
| 33 | +"hotfix only". |
| 34 | + |
| 35 | +## Test fixtures |
| 36 | + |
| 37 | +Use a **sanitized** Supabase host (`example.supabase.co`) — same convention |
| 38 | +as the migration-discipline rules added in PR #15 round-2. Real project |
| 39 | +refs would either leak in the public toolkit or trip the IP-leak guard. |
| 40 | +Tests required (≥5): |
| 41 | + |
| 42 | +1. `blocks-curl-post-supabase-rest` — POST mutation, expects warn. |
| 43 | +2. `blocks-curl-patch` — PATCH mutation, expects warn. |
| 44 | +3. `blocks-curl-put` — PUT mutation, expects warn. |
| 45 | +4. `blocks-curl-delete` — DELETE mutation, expects warn. |
| 46 | +5. `allows-curl-get-supabase-rest` — GET (read), expects allow. |
| 47 | +6. `allows-curl-non-supabase` — POST against `example.com`, expects allow. |
| 48 | +7. `allows-bypass-marker` — POST + bypass comment, expects allow. |
| 49 | + |
| 50 | +(Test names use the `blocks-*` prefix purely for readability symmetry with |
| 51 | +neighboring rules. Action is `warn`, so `expected_exit` is `0` everywhere |
| 52 | +and we use `expected_stderr_contains` to assert the warning fired.) |
| 53 | + |
| 54 | +## Why warn, not block |
| 55 | + |
| 56 | +A `block` would frustrate legitimate one-off REST debugging. The author of |
| 57 | +`feedback_scripts_not_db.md` is consistent: they prefer a warn for |
| 58 | +psql-against-remote (the documented neighbor rule), and the same severity |
| 59 | +logic applies here. If repeat offenders surface in code review, we can |
| 60 | +escalate the action to `block` in a follow-up PR without changing the |
| 61 | +schema. |
0 commit comments