hoangsonww / hoangsonww/Collabify-Project-Manager
Production Hardening: Auth0, API guardrails, indexes, i18n coverage, CI, and DX
- Dominant language
- TypeScript
- Stars
- 21
- Forks
- 12
- PR merge metrics
- No merged PRs in 30d
Description
## 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**
```ts
// 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**
```ts
// 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)**
```ts
// lib/rate-limit.ts
const buckets = new Map();
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)**
```ts
// 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 ``.
### 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**
```yaml
# .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; `` 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.
Contributor guide
Assessment
This issue has not been assessed yet.