103 lines
5.5 KiB
Markdown
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)
|