CASE STUDY · CLIENT NAME REMOVED
A walkthrough of a web app
10 defects found, 10 fixed and proven
While filming this app, the client met 10 defects. The most serious: Database setup on Postgres fails unless an optional direct-connection URL is set. Each is below: what went wrong, why, and how to avoid it in your own software.
What went wrong, and how to avoid it
- Database setup on Postgres fails unless an optional direct-connection URL is set Why: run-prisma.mjs switches the schema to postgresql and un-comments directUrl = env("LMS_DATABASE_DIRECT_URL"), but configureLmsDatabaseEnv() in scripts/lms-db-env.mjs only filled that variable from POSTGRES_* / DATABASE_URL fallbacks, never from LMS_DATABASE_URL itself.Avoid it: How it was fixed: scripts/lms-db-env.mjs: when no direct URL is configured for postgresql, use LMS_DATABASE_URL as LMS_DATABASE_DIRECT_URL. tests/lms-db-env.test.ts: new test. Add a test for the failing action and the edge case behind it, so a regression is caught before users meet it.
- Local gateway serves LMS pages without their styles and scripts Why: packages/lms-gateway/src/dev-runner.mjs sent every /_next/* request to the engine (through the ai-proxy), but lms-commerce is a separate Next.js app with its own chunk names.Avoid it: How it was fixed: packages/lms-gateway/src/asset-fallback.mjs (new): try the engine first and stream the first answer that is not 404, else lms-commerce; dev-runner.mjs uses it for GET/HEAD /_next/*. Add a test for the failing action and the edge case behind it, so a regression is caught before users meet it.
- AI tutoring chat fails for every message when the platform AI key is set on the engine server Why: packages/lms-ai-proxy/src/app/api/chat/route.ts split the model id on "/", but the engine sends "provider:model", so every request was treated as OpenAI; and when no LMS-stored key matched it refused with 400 instead of passing the request to the engine, whose server key works (the generate routes aAvoid it: How it was fixed: packages/lms-ai-proxy/src/lib/model-provider.ts (new): read "provider:model" and "provider/model"; chat/route.ts uses it and only refuses when the user chose their own keys and has. Add a test for the failing action and the edge case behind it, so a regression is caught before users meet it.
- Publish and exam pages of a classroom show 404 behind the single-origin gateway Why: dev-runner.mjs and caddy.Caddyfile sent every /classroom/* path to the engine, which only serves /classroom/[id]; the deeper pages belong to lms-commerce.Avoid it: How it was fixed: packages/lms-gateway/src/dev-runner.mjs and caddy.Caddyfile: route /classroom/[id]/[anything] to lms-commerce. Add a test for the failing action and the edge case behind it, so a regression is caught before users meet it.