Files
tilbudgivern/docs/architecture-quickwins.md
T

103 lines
5.5 KiB
Markdown

# Architecture & Quick Wins (Maintainability First)
Last updated: 2026-03-13 (implemented baseline quick wins + P1 tooling + duplicate-route cleanup)
## Product North Star
Maintainability work should support the product mission, not drift away from it.
Tilbudgivern's core mission is:
- let carpenters create a strong quote draft in the field with very few inputs
- reuse as much real history as possible from Tilbudgivern and Ordrestyring
- use Smart Packages as editable operational templates
- use AI to improve wording and structure, not to invent facts
This means architecture decisions should favor:
- structured project data over free-text-only AI flows
- reusable local historical data over one-off API calls
- mobile-friendly, low-friction request/response shapes
- clear persistence of package choice, suggestion source, and quote learning signals
## 1) Current Architecture Snapshot
### Runtime topology
- **Frontend:** React app in `frontend/src`, built to `frontend/build`.
- **Backend:** Unified Express + Socket.IO server in `backend/unified-server.js`.
- **Database:** MariaDB/MySQL via `mysql2` pools.
- **Service layer:** Domain modules in `backend/src/services` (pricing, geometry, OpenAI, Ordrestyring, PDF, imports).
- **Route layer:** Mixed model:
- many inline handlers inside `backend/unified-server.js`
- mounted routers from `backend/src/routes` and `backend/routes`.
### Request/data flow
1. Browser UI (React) issues Axios API calls.
2. Express middleware applies CORS, security headers, request/session logging.
3. Route handler executes inline logic or delegates to a service.
4. Service calls DB/external systems (Ordrestyring/OpenAI/etc.).
5. Response returns JSON to UI.
6. Socket.IO optionally emits project updates for real-time collaboration.
7. Non-API requests are served from `frontend/build/index.html`.
## 2) Key Findings (Maintainability Risks)
1. **Monolithic API surface**
- `backend/unified-server.js` is still ~11,634 lines with ~200+ `/api` route registrations.
- High change collision risk and difficult ownership boundaries.
2. **Mixed route ownership**
- Same domains are handled inline and via mounted routers.
- Example: `analytics`, `customer-projects`, `calendar`, and `ordrestyring` now have dedicated routers, while adjacent domain logic still lives inline in `backend/unified-server.js`.
- The active duplicate registrations called out in the first pass have now been removed, but ownership is still split across `backend/unified-server.js`, `backend/src/routes`, and `backend/routes`.
3. **Runtime loading patterns**
- Multiple handler-time `require(...)` calls increase hidden coupling and make dependency flow harder to reason about.
- A bootstrap service container now centralizes core startup wiring, but legacy handler-level dependencies still exist in parts of `backend/unified-server.js`.
4. **Script drift in root package**
- The immediate script drift has been fixed, but root scripts still proxy into nested packages and can drift again if backend/frontend package commands change without updating the root wrapper.
5. **CI lint gate is weak**
- CI now runs a real lint gate, but the frontend stage is still warning-tolerant.
- The repo has 25 existing frontend lint warnings that should be cleared before tightening enforcement to fail on warnings.
## 3) Prioritized Quick Wins
### P0 (Do first)
1. **Fix root scripts (high impact, low effort)**
- Update root `package.json` scripts to valid entrypoints/commands.
- Definition of done: `npm run dev`, `npm start`, and `npm test` all execute real targets.
2. **Consolidate health route ownership (high impact, low effort)**
- Choose one owner (`backend/src/routes/healthDashboard` router or inline block) and remove duplication.
- Definition of done: one route source of truth; no endpoint behavior regressions.
3. **Start modular extraction from unified server (high impact, medium effort)**
- Extract one domain first (recommended: `health` + `analytics`), preserving existing API contracts.
- Definition of done: extracted router passes existing tests and route smoke checks.
### P1 (Next)
1. **Introduce service bootstrap/container**
- Initialize dependencies once at startup, then inject/use references instead of ad-hoc lazy `require`.
- Definition of done: startup wiring is explicit; handlers stop resolving core services dynamically.
- Status: baseline implemented via `backend/src/services/bootstrapServiceContainer.js`.
2. **Add API surface inventory check**
- Add a script that lists all registered `/api/*` endpoints and flags duplicates.
- Definition of done: inventory output is generated in CI or as a local validation step.
- Status: implemented via `scripts/api-inventory.js`; use `npm run api:inventory` for summary and `npm run api:inventory:full` for the full route table. Current baseline: 275 endpoints, no duplicate method+path registrations detected.
3. **Strengthen CI quality gate**
- Add actual lint scripts in frontend/backend and make lint a required CI signal.
- Keep security audits informative but separate from core merge-blocking checks.
- Status: implemented as a baseline gate. Backend uses syntax linting, frontend uses ESLint, and CI runs `npm run lint`.
## 4) Guardrails for Refactoring
- Preserve current external API contracts (`/api/*` paths and response shapes) during quick-win refactors.
- Prefer “extract without redesign” in first pass.
- Validate each extraction with:
- `cd backend && npm test -- --coverage --passWithNoTests`
- `cd tests && PLAYWRIGHT_BASE_URL=http://localhost:4032 npx playwright test` (smoke subset acceptable initially)