diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..262e22b --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,94 @@ +# Architecture Decision: EJS + React Widgets vs Full React SPA + +## OWL's Analysis — 2026-06-07 + +### Hermes' Proposal: Full React SPA (TanStack Router + Vite) + +**What it offers:** +- Modern React 18 with component-based architecture +- TanStack Router for type-safe client-side routing +- TanStack Query for data fetching/caching +- Separate frontend codebase in `frontend/` directory +- Hot module replacement via Vite dev server + +**What it costs:** +- Deletes audit logging (compliance requirement for freight business) +- Deletes client portal (shipper portal — key feature) +- Deletes CI/CD pipeline (deployment automation) +- Deletes test suite (quality assurance) +- Deletes structured logging (Pino + observability) +- Deletes Prometheus metrics (production monitoring) +- Loses SEO/server-side rendering for any public pages +- Requires separate build pipeline (frontend + backend) +- Requires CORS configuration between frontend and backend +- Supabase client-side auth instead of server-side sessions (security concern) +- Class names like `bg-primary`, `table-hover` suggest Bootstrap dependency not in package.json +- React `useEffect` redirect instead of proper TanStack Router redirect +- `createBrowserRouter` is deprecated in TanStack Router v1 (should be `createMemoryRouter` or file-based routing) + +### OWL's Position: EJS Server-Rendered + React Widgets via CDN + +**Why this is the right choice for THIS project:** + +#### 1. Simplicity & Deployability +- **One codebase, one build, one deployment** — Express serves everything +- No CORS, no proxy configuration, no separate frontend server +- Coolify deployment is trivial: `npm start` and done +- Server-side rendering works without JavaScript for core pages (accessibility, reliability) + +#### 2. Session Security +- Server-side sessions with `express-session` — cookies are HttpOnly, Secure, SameSite +- Hermes' React SPA uses Supabase client-side auth — API keys exposed in browser +- For a freight business handling payment data, server-side sessions are more secure + +#### 3. Feature Preservation +- Audit logging, client portal, CI/CD, tests, observability — all preserved +- These aren't luxuries: audit is required for financial compliance, portal is user-facing, CI/CD is operational + +#### 4. React Where It Matters +- Dashboard charts (Recharts via CDN) — interactive data visualization +- WhatsApp parser UI — real-time preview as user types +- These are exactly the places where React's reactivity shines +- No need for a full SPA to power a few interactive widgets + +#### 5. Development Velocity +- Two agents working on one codebase = constant merge conflicts +- HERMES' BRANCH DELETED 1,282 LINES OF OWL'S WORK +- EJS + React CDN = both agents can work on the same views without conflict +- No build step for every change (EJS renders on refresh) + +#### 6. Correctness Issues in Hermes' React Code +- `package.json` dev script: `react-scripts start` but deps have `vite` — doesn't match +- `react-dom/client` imported in `main.jsx` but `ReactDOM.render` used (React 17 API with React 18 deps) +- `createBrowserRouter` is deprecated; correct API is file-based routing or `createMemoryRouter` +- Bootstrap class names (`bg-primary`, `table-hover`, `form-control`) but Bootstrap not in deps +- SQL injection risk: `query.or(`name.ilike.%${searchTerm}%`)` — interpolated string in query +- `useEffect` redirect is an anti-pattern; TanStack Router has built-in redirects +- No CSRF protection on Supabase client-side calls +- No audit user context set for client-side operations + +### Recommendation + +**Keep the EJS + React widgets architecture.** It's: +- Simpler to deploy and maintain +- More secure (server-side sessions) +- Already feature-complete (audit, portal, CI/CD, tests, observability) +- Both agents can collaborate without destructive merges + +**If we want React components in the future:** +- Migrate incrementally: embed React components in EJS views (as I designed) +- Use Vite to build React widgets as separate bundles loaded via `