Skip to content

Add rate limiting to public API endpoints (J0dI3 proxy, contact, health) #1064

Description

@jeromehardaway

Problem

Public API routes under src/pages/api/** have no rate limiting. The J0dI3 proxy endpoints (/api/j0di3/**) are particularly concerning because they proxy to a paid AI backend — an authenticated attacker (or a misbehaving client) could drive costs up quickly. The contact endpoint could be abused for spam, and /api/health could be pinged in a tight loop.

Expected behavior

Every public API route enforces a sensible per-IP and per-session rate limit, and returns 429 Too Many Requests with Retry-After when exceeded.

Acceptance criteria

  • Rate limiter chosen (recommend: Upstash Redis-based limiter or @vercel/kv, since deployment target is Vercel).
  • Centralized middleware or helper so each route opts in with one line.
  • J0dI3 endpoints: stricter limits + per-troop quota (not just per-IP).
  • Contact/form endpoints: stricter limits + Gemini-based spam filter already present, coordinate.
  • Health endpoint: either require auth or cap to a sensible rate.
  • Documented limits in docs/ so frontend knows what to expect.

Risk if not done

  • J0dI3 cost overrun (paid AI calls).
  • Contact form spam.
  • Accidental DoS from a buggy client in a tight loop (happens more often than malicious attacks).

Suggested approach

// src/lib/rate-limit.ts
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";

export const j0di3Limiter = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(20, "1 m"),
});

Then in each route:

const { success } = await j0di3Limiter.limit(`j0di3:${session.user.id}`);
if (!success) return res.status(429).json({ error: "Rate limit exceeded" });

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions