You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CENTRAL.md
+7-7Lines changed: 7 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ Living doc kept by Claude across sessions. Update after each big change. If you'
4
4
5
5
## Project shape
6
6
7
-
DBSMO is a Next.js 15 (App Router) Postgres+Prisma platform for self-paced math olympiad training at Diocesan Boys' School. Everything is server-rendered by default; a handful of `"use client"` components handle interactive UI (typewriter greeting, theme toggle, answer grid, FTW match).
7
+
DBSMO is a Next.js 16 (App Router) Postgres+Prisma platform for self-paced math olympiad training at Diocesan Boys' School. Everything is server-rendered by default; a handful of `"use client"` components handle interactive UI (typewriter greeting, theme toggle, answer grid, FTW match).
8
8
9
9
Stack: Next.js, NextAuth (Google + dev bypass), Prisma, KaTeX for math, Lucide icons, Vitest. No Tailwind — single 5k-line `app/globals.css`.
10
10
@@ -19,7 +19,7 @@ Stack: Next.js, NextAuth (Google + dev bypass), Prisma, KaTeX for math, Lucide i
19
19
20
20
## Conventions
21
21
22
-
-Page files do their own `getServerSession` + permission gate; no shared middleware.
22
+
-`proxy.ts` provides the broad signed-in/staff boundary; every page and API remains responsible for its exact permission or visibility gate.
23
23
- Permission keys in `lib/permissions.ts` — `admin:view`, `admin:content`, etc. Use `hasPermission(role, key)`.
24
24
- LaTeX statements rendered through `<LatexStatement>` (KaTeX auto-render).
25
25
- Answer normalisation lives in `grading.ts`; do not roll your own comparison.
@@ -29,10 +29,11 @@ Stack: Next.js, NextAuth (Google + dev bypass), Prisma, KaTeX for math, Lucide i
29
29
30
30
### Now (this session)
31
31
32
-
- No active half-finished feature after the current mobile/classes/animations update lands.
32
+
- No active half-finished feature after the safety and maintainability pass landed.
33
33
34
34
### Recently landed
35
35
36
+
- **Application-wide safety and maintainability pass** — all API JSON/multipart bodies now use bounded streamed readers and route-specific schemas; auth uses exact school-domain matching and an explicit non-production bypass opt-in; staff routing and private-profile/leaderboard authorization use the documented permissions. Submission, friendship, role mutation, problem-set asset, and FTW room transitions are race-safe; FTW room codes use cryptographic randomness. Grading preserves exact large integer/fraction/decimal identity instead of collapsing through IEEE-754. Imports stage storage before atomic metadata attachment, server and browser ZIP paths enforce actual expanded-byte limits, replacement/deletion paths compensate for failures, and file reads verify size/checksum under hard limits. Exports/restores are paginated and capped, CSV formula cells are neutralized, expensive GETs reject cross-site browser requests, and formerly unbounded assignment/practice-tag scans are computed in bounded SQL. Formerly floating `latest` dependencies are pinned, full and production dependency audits report zero vulnerabilities, and response security headers are enabled. The UI, feature set, and database schema are unchanged. Regression coverage spans 29 test files/195 tests, including policy, body, grading, concurrency, storage, and import cases.
36
37
- **Hand-drawn visual system** — `app/globals.css` now provides paper/ink design tokens, graph-paper backgrounds, asymmetric squircle cards and controls, marker-color accents, and irregular badges/tabs. Shared surfaces use native asymmetric borders instead of `border-image`, which created rigid grey rectangles outside rounded controls. Metric cards use the same neutral border on every edge instead of decorative colored strips. Dark structural borders are intentionally quieter, search inputs are borderless at rest with one cyan focus stroke, and selected problem-set tag counts use opaque ink/paper colors for readable contrast. Global wavy eyebrow/title underlines remain removed. A signed-in production Chrome audit of `/problem-sets/1991-ajhsme` also removed percentage shape paths from variable-height panels, fixed oversized panel-header geometry, and removed the blue statement band. Desktop navigation is a 64 px icon rail that expands to 240 px on hover/focus, while mobile retains the stable off-canvas sheet. The simplified Sigma in `public/dbsmo-mark.svg` is shared by favicon metadata and the landing brand. `app/layout.tsx` loads Shantell Sans for display/control text while Inter remains the body and math font. Route-specific coverage was visually audited across dashboard, problem catalog/detail, writeups, practice, classes, leaderboard, users/profiles, settings, and admin surfaces; FTW and Playground were intentionally excluded. Unsupported browsers retain ordinary border/radius fallbacks; details are in `docs/visual-system.md`.
37
38
-**Mobile/classes cleanup** — fixed mobile `/problem-sets` hiding task rows by restoring the responsive card table, stabilized the mobile sidebar grid to avoid icon reflow on tap/focus, and made dashboard auth/actions render as a compact mobile account card. `/classes` now has a teacher/admin `Announcements` subtab that lists existing class messages and supports author/admin deletion. Display-name fallbacks now treat literal `"null"`/`"undefined"` strings as empty via `lib/display-name.ts`.
38
39
-**Mobile sidebar focus fix** — mobile sidebar sheet geometry now remains stable under `:hover`, `:focus`, and `:focus-within`, preventing the nav grid from jumping upward when a mobile tap focuses one of the upper links (source: `app/globals.css`).
@@ -82,14 +83,13 @@ Then read the file, reconcile with what's in memory, keep going.
82
83
83
84
## Deploy
84
85
85
-
VPS deploy is documented in `SETUP.md` (npm + pm2 + nginx + certbot + cron backups). After a code push, the redeploy flow on the VPS is `git pull → npm ci → npx prisma migrate deploy → npm run build → pm2 reload dbsmo`.
86
+
VPS deploy is documented in `SETUP.md` (npm + pm2 + nginx + certbot + cron backups). After a code push, the redeploy flow on the VPS is `git pull → npm ci → npx prisma generate → npx prisma db push → npm run build → pm2 reload dbsmo`.
86
87
87
88
## Open questions / followups
88
89
89
-
- Room realtime is poll-based (1.5s). Fine for a classroom; would migrate to SSE/WebSockets if scale warrants. The DB does the locking via `advanceRoomIfDue`, which is the canonical way to advance — call it from `state` and `submit`.
90
-
-`lib/storage.deleteFile` is best-effort on rollback; an orphan-sweeper job would catch any leaks.
90
+
- Room realtime is poll-based (1.5s). Fine for a classroom; would migrate to SSE/WebSockets if scale warrants. Mutating room routes must preserve the parent-row locks in `lib/ftw-locks.ts` and the canonical transitions in `lib/ftw-room-transition.ts`/`lib/ftw-room-server.ts`.
91
+
-Storage compensation removes staged or unreferenced objects best-effort; an orphan-sweeper remains useful for process crashes or storage outages.
91
92
- Migration: schema gained `Writeup`, `WriteupImage`, and `WriteupVote` models in `prisma/migrations/20260628090000_add_writeups/`. Deploy needs the normal Prisma migration step before the app starts serving writeup routes.
92
93
- Migration: schema gained `Announcement` and `_AnnouncementToClass` in `prisma/migrations/20260629110000_add_announcements/`. Deploy needs the normal Prisma migration step before the app starts serving class announcement routes.
93
-
-`/api/practice/tags` is referenced from `practice/page.tsx` but I haven't reviewed it; check before touching.
94
94
-`globals.css` has a "2026 refresh" overlay starting around line 2175 and two final hand-drawn override sections at the tail. Edit the tail for visual changes and preserve the fallback-before-experimental-property ordering.
95
95
- Never use percentage-based `border-shape` paths on variable-height content. Keep shape paths to bounded decorative surfaces and test shared panel changes against a tall problem set.
Copy file name to clipboardExpand all lines: DBSMO/Projects/dbsmo/00 Start Here.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
date: 2026-06-26
3
-
updated: 2026-06-28
3
+
updated: 2026-07-18
4
4
type: project-index
5
5
tags:
6
6
- project
@@ -33,10 +33,10 @@ This is the starting index for the [[dbsmo]] codebase knowledge base, generated
33
33
34
34
-[[dbsmo]] is a Next.js App Router app for DBS mathematics olympiad practice with problem sets, automatic answer grading, practice mode, class assignments, analytics, imports/exports, feedback, and FTW game modes (sources: `README.md`, `app/`, `lib/`, `prisma/schema.prisma`).
35
35
- The database is PostgreSQL via Prisma Client with the Prisma PG adapter; the shared client is exported from `lib/db.ts`, and the schema lives in `prisma/schema.prisma`.
36
-
- Authentication uses NextAuth with Google OAuth plus a non-production credentials bypass unless disabled; route protection starts in `proxy.ts` and continues in API/page-level checks (sources: `lib/auth.ts`, `proxy.ts`, `lib/permissions.ts`).
36
+
- Authentication uses NextAuth with exact-domain Google OAuth plus a credentials bypass that requires an explicit `AUTH_DEV_BYPASS=true` outside production. Route protection starts with the broad boundary in `proxy.ts` and continues with exact API/page permissions (sources: `lib/auth.ts`, `lib/auth-policy.ts`, `proxy.ts`, `lib/permissions.ts`).
37
37
- Most business logic sits in `lib/`: grading, visibility, permissions, imports, storage, FTW scoring, classes, analytics, and exports.
38
38
- Main UI routes live under `app/`; API handlers live under `app/api/`.
39
-
- Current import notes include optional same-name image ZIPs for JSON imports, per-problem image uploads in the problem maker, and tolerant JSON editor drafts(sources: `lib/import/json-import.ts`, `lib/import/image-zip.ts`, `app/admin/create/page-client.tsx`).
39
+
- Current import notes include optional same-name image ZIPs for JSON imports, per-problem image uploads in the problem maker, tolerant JSON editor drafts, and compressed/actual-expanded archive limits shared through `lib/import/zip-entry.ts`(sources: `lib/import/json-import.ts`, `lib/import/image-zip.ts`, `lib/import/zip-dry-run.ts`, `app/admin/create/page-client.tsx`).
40
40
- Current class/community notes include authored tasks, a mastery heatmap, problem-set writeups with image uploads/voting/deletion, and class announcements pinned on dashboards (sources: `app/users/[username]/page.tsx`, `app/problem-sets/[slug]/writeups/page.tsx`, `app/writeups/page.tsx`, `app/classes/announcement-composer.tsx`, `app/dashboard/page.tsx`, `prisma/schema.prisma`).
41
41
42
42
## Source Inspection Basis
@@ -49,4 +49,4 @@ This vault was built from:
49
49
50
50
## Staleness Note
51
51
52
-
The original scan reported git commit `f7e0c74` with a dirty worktree. Treat the writeups/profile notes as source-verified as of 2026-06-28, but re-run CodeGraph or inspect source before editing behavior.
52
+
The original scan reported git commit `f7e0c74` with a dirty worktree. Auth, API bounds, imports/storage, submissions, exports, profiles, and FTW concurrency were source-verified again on 2026-07-18 using CodeGraph plus direct inspection; still verify current source before editing behavior.
0 commit comments