Problem
The admin and moderation subsystem is the part of the app that mutates published data, and it is almost entirely untested. The only admin test file is app/api/admin/posts/route.test.ts, which has exactly two cases: "rejects requests without the admin password" and "returns posts and tab counts when authenticated".
Untested routes:
app/api/admin/posts/[id]/route.ts (status transitions: approve, reject, and whatever else it supports)
app/api/admin/posts/[id]/edit/route.ts
app/api/admin/posts/[id]/resend-token/route.ts
app/api/admin/comments/route.ts (list and moderate)
app/api/newsletter/send/route.ts (admin gated broadcast)
Why it matters
Every one of those is an authz boundary plus a destructive or irreversible action (publishing a case, hiding a comment, emailing the whole list). A regression that drops the auth check on any of them is currently invisible to CI. The existing pattern in app/api/posts/route.test.ts and app/api/teams/waitlist/route.test.ts shows how to mock the Supabase admin client and the rate limiter, so the infrastructure exists, it just was never applied here.
Suggested approach
- Factor the Supabase admin client mock used by the existing tests into a shared test helper (something like
test/helpers/supabase.ts) instead of copying the vi.mock block a fifth time.
- For each route above add at minimum: unauthenticated request returns 401, invalid input returns 400, happy path performs the expected write, and the Supabase error path returns 500 without leaking the error body.
- For
newsletter/send, assert that the send provider is never called when auth fails.
Done when
- Every file under
app/api/admin/** and app/api/newsletter/send/ has a co-located .test.ts.
- Each has an explicit "unauthenticated is rejected" case.
npm test passes locally.
Depends on nothing, but if the admin session work lands first, use the new guard in the tests.
If you want to take this on, comment on the issue to claim it and it will be assigned. Please keep to a maximum of 2 open claims per person at a time so other contributors get a chance.
Problem
The admin and moderation subsystem is the part of the app that mutates published data, and it is almost entirely untested. The only admin test file is
app/api/admin/posts/route.test.ts, which has exactly two cases: "rejects requests without the admin password" and "returns posts and tab counts when authenticated".Untested routes:
app/api/admin/posts/[id]/route.ts(status transitions: approve, reject, and whatever else it supports)app/api/admin/posts/[id]/edit/route.tsapp/api/admin/posts/[id]/resend-token/route.tsapp/api/admin/comments/route.ts(list and moderate)app/api/newsletter/send/route.ts(admin gated broadcast)Why it matters
Every one of those is an authz boundary plus a destructive or irreversible action (publishing a case, hiding a comment, emailing the whole list). A regression that drops the auth check on any of them is currently invisible to CI. The existing pattern in
app/api/posts/route.test.tsandapp/api/teams/waitlist/route.test.tsshows how to mock the Supabase admin client and the rate limiter, so the infrastructure exists, it just was never applied here.Suggested approach
test/helpers/supabase.ts) instead of copying thevi.mockblock a fifth time.newsletter/send, assert that the send provider is never called when auth fails.Done when
app/api/admin/**andapp/api/newsletter/send/has a co-located.test.ts.npm testpasses locally.Depends on nothing, but if the admin session work lands first, use the new guard in the tests.
If you want to take this on, comment on the issue to claim it and it will be assigned. Please keep to a maximum of 2 open claims per person at a time so other contributors get a chance.