Skip to content

Production Hardening: Auth0, API guardrails, indexes, i18n coverage, CI, and DX #17

@hoangsonww

Description

@hoangsonww

Summary

Polish Collabify for “team-ready” deployments by tightening auth, adding API guardrails, indexing Mongo, finishing i18n coverage, and smoothing CI/release flows. This is intentionally a bundle of small, safe changes that deliver outsized stability and UX wins.


Scope & Tasks

1) Auth0 & API guardrails

  • Enforce JWT validation on API routes with issuer/audience checks (RWA & M2M).
  • Add role/permission gates (RBAC) in route handlers.
  • Add rate limiting (per IP/user) to sensitive endpoints.
  • Ensure logout clears app state & tokens.

Next.js middleware sketch

// middleware.ts
import { NextResponse } from "next/server";
import { jwtVerify } from "jose";

const ISSUER = process.env.AUTH0_ISSUER_BASE_URL!;
const AUD = process.env.AUTH0_AUDIENCE!;

export async function middleware(req: Request) {
  const url = new URL(req.url);
  if (!url.pathname.startsWith("/api")) return NextResponse.next();

  const token = req.headers.get("authorization")?.replace(/^Bearer\s+/i, "");
  if (!token) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  try {
    const { payload } = await jwtVerify(token, /* your JWKS or secret */, {
      issuer: `${ISSUER}/`,
      audience: AUD,
    });
    // Optional: role checks
    const roles = (payload["https://collabify/roles"] as string[]) ?? [];
    (req as any).auth = { sub: payload.sub, roles };
    return NextResponse.next();
  } catch {
    return NextResponse.json({ error: "Invalid token" }, { status: 401 });
  }
}

Route guard example

// pages/api/admin/roles.ts
export default async function handler(req, res) {
  const roles: string[] = req?.auth?.roles ?? [];
  if (!roles.includes("admin")) return res.status(403).json({ error: "Forbidden" });
  // ...
}

Rate limit (simple token bucket)

// lib/rate-limit.ts
const buckets = new Map<string, { tokens: number; ts: number }>();
export function allow(key: string, rate=10, perMs=10_000) {
  const now = Date.now();
  const b = buckets.get(key) ?? { tokens: rate, ts: now };
  const refill = Math.floor(((now - b.ts) / perMs) * rate);
  b.tokens = Math.min(rate, b.tokens + refill);
  b.ts = now;
  if (b.tokens <= 0) return false;
  b.tokens -= 1; buckets.set(key, b); return true;
}

2) MongoDB indexes & data hygiene

  • Add indexes for projects, tasks, and user lookups.
  • Consider TTL index for logs/audit if stored.
  • Add migrations or a startup check that ensures indexes exist.

Index examples (Mongoose)

// models/Task.ts
TaskSchema.index({ projectId: 1, createdAt: -1 });
TaskSchema.index({ assignees: 1, status: 1 });
TaskSchema.index({ title: "text", description: "text" }); // search

3) i18n coverage & language switch UX

  • Add missing keys to public/locales/{en,vi}; run a key linter.
  • Ensure date/number formatting respects locale (Intl APIs).
  • Persist language selection in localStorage and reflect in <html lang>.

4) Accessibility & keyboard flows

  • Ensure all interactive shadcn components have aria-labels and focus rings.
  • Add skip-to-content link and test keyboard-only navigation.
  • Verify color contrast in both themes.

5) Performance & UX

  • Use React Query cache times per view; avoid refetch storms.
  • Paginate tasks and projects; add server-side filters (status, assignee).
  • Lazy-load heavy charts; defer animations offscreen.

6) Logging & error handling

  • Standardize API errors: { error, code, traceId }.
  • Add requestId/traceId header and log it server-side.
  • Mask PII in logs; never log tokens.

7) CI/CD & release hygiene

  • GitHub Actions: install → typecheck → lint → test → build.
  • Add preview env comment on PRs (Vercel).
  • Optional: release tagging + changelog via Release Please.

Action snippet

# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
  web:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20, cache: npm }
      - run: npm ci
      - run: npm run typecheck
      - run: npm run lint
      - run: npm test -- --ci
      - run: npm run build

8) Docker & env consistency

  • Ensure Docker image uses NODE_ENV=production, runs next start behind non-root user.
  • Validate .env.local vs Vercel env parity (script to diff keys).

Acceptance Criteria

  • ✅ All protected API routes reject invalid/expired tokens; admin endpoints require admin role.
  • ✅ P95 API latencies improved via indexes (document the before/after on /api/projects & /api/projects/[id]/tasks).
  • ✅ i18n keys complete for EN & VI; language switch persists; <html lang> updates.
  • ✅ Lighthouse a11y score ≥ 95 on Dashboard & Project pages.
  • ✅ CI green on PRs; build artifacts reproducible; preview deploy comments appear.
  • ✅ Docker image runs with non-root user and minimal attack surface.
  • ✅ Error responses are consistent and include a traceId.

Nice-to-have (future)

  • Global search with Mongo Atlas Search (fuzzy) or Meilisearch.
  • Webhooks for project events; Slack/Email notifications.
  • Task activity feed with server-sent events.
  • Usage analytics (privacy-aware) and feature flags.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdocumentationImprovements or additions to documentationenhancementNew feature or requestgood first issueGood for newcomershelp wantedExtra attention is neededquestionFurther information is requested

Projects

Status

Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions