03 — Backend Architecture
CEO Summary
The backend is the API layer that powers all tenant operations — POS, invoicing, inventory, HR, etc. It runs on Node.js/Express, connects to MySQL, and enforces tenant isolation on every request. Business value: Every feature depends on it. Key metrics: Response time, error rate, request volume. If this breaks: All tenant operations stop; POS cannot process sales.
Request Flow (Top to Bottom)
Overview
Stack: Node.js, Express, MySQL (raw queries + Sequelize). Entry: backend/server.js. Port: 4000.
Middleware Order
- CORS, body parsing, session
- Tenant resolver (on API routes)
- Auth: requireSessionAuth, optionalSessionAuth, requireFlexibleAuth, deviceAuth
- Idempotency (
middleware/idempotency.js) — mounted on the POS router (pos.routes.js): readsIdempotency-Keyand optionalX-PPO-*headers, dedupes replays, attachesreq.ppoMutationfor handlers/logging - Feature gates (where applicable)
- Route handlers
Idempotency & POS mutation envelope
Mutating POS and related calls from the browser SPA and the Node bridge send a stable Idempotency-Key (aligned with client mutation id) plus optional X-PPO-Client-Mutation-Id, X-PPO-Device-Id, X-PPO-Register-Id, X-PPO-Sequence so that offline queue replay does not double-apply business actions. backend/middleware/idempotency.js records keys and exposes structured context on req.ppoMutation where applied.
Frontend: frontend/src/lib/offline/mutationEnvelope.js, tryOnlineThenQueue.js, frontend/src/pos/api.js — see 14 — Frontend and Appendix: Data Flows.
Route Groups
| Area | Routes |
|---|---|
| Auth | auth.routes, staffAuth, tenantStaffAuth, users |
| POS | pos.routes, pos-register, pos-analytics |
| Catalog | catalog.routes.NEW, menus, preparables |
| Devices | devices, deviceCodes, kds |
| Inventory | inventory, inventory.items, inventory.ledger |
| Customers | customers, customerAnalytics |
| Payments | transactions, invoices, giftcards, loyalty |
| Crypto | doge, ltc, crypto-config, crypto-wallet |
| HR | hr, payroll, time, staff |
| Tickets | tickets, admin.tickets, appointments |
| SaaS | tenants, master-admin, plans |
| Public | public.signup, public.barcode-lookup, webhooks.*, signage playlist (GET only) |
| Signage | signage.routes — folders, ads, displays; public playlist |
| Platform catalog | platformCatalog (tenant lookup), master-admin platform-catalog (CRUD) |
Public signup API
File: backend/routes/public.signup.routes.js (mounted under /api/public with tickets and appointments).
GET /api/public/signup-status— JSON for SPAs: whether self-service signup is allowed.POST /api/public/signup— Creates org, tenant, owner user, runsprovisionTenant(three DBs). Can be disabled withDISABLE_PUBLIC_SIGNUP— see 01 — Infrastructure → Disabling public signup.GET /api/public/signup-form— Standalone HTML form; when signup is disabled, returns a notice page instead.
Platform barcode catalog — who gets what
Same master DB (platform_product_catalog), three surfaces — different billing and limits:
| Surface | Who | Billing | Notes |
|---|---|---|---|
GET /api/platform-catalog/lookup |
Logged-in tenant (session + tenant headers) | Included in Basic / Premium / normal subscriptions | Enrichment when POS or inventory scans a barcode and no local match — not an “external API product.” Unlimited for normal app use (subject to general API health). |
GET /api/public/barcode-lookup |
Anonymous visitors (public marketing site) | Free, tiny quota | Strict per-IP hourly limit (PUBLIC_BARCODE_LOOKUP_MAX_PER_HOUR / window). Abuse prevention only. |
| Future: Enterprise barcode API (e.g. API key + metering) | Paying integrators / Enterprise tier | Metered (e.g. per-call plans like Starter / Advanced / …) | Not the same as tenant session lookup. Implement with issued API keys, usage counters, and plan limits; optional separate route prefix (e.g. /api/v1/partner/...). |
Positioning: Basic/Premium merchants do not need a separate “barcode API” — they get catalog enrichment inside the app. Charged API usage targets external systems that call your platform programmatically (Enterprise / partner).
Key Services
| Service | Purpose |
|---|---|
| comprehensiveTenantProvisioning | Tenant DB creation |
| tenantEmployeeRouting | Email → tenant |
| bridgeConnectionManager | WebSocket registry; sendRequest, pushEnvelope (signage) |
| cart.service | POS cart logic |
| catalog.service | Catalog management |
| inventoryLedger.service | Ledger posting |
| coreInvoicing.service | Invoice creation |
| dogeWallet.service, ltcClient | Crypto |
| webhookDispatcher | Webhooks |
| audit.service | Audit |
Controllers
Path: backend/controllers/
auth.controller, staff.controller, time.controller, payroll.controller, products.controller, catalog.controller, inventory.controller, reports.controller, etc. Map route handlers to business logic.
Validation
Backend: backend/validation/ — Joi schemas for request validation. Used by validate() middleware.
Payments: backend/payments/validators/ — webhooks.schemas.js, invoices.schemas.js for webhook and invoice validation.
POS: backend/schemas/pos.schemas.js — POS cart, items, tender schemas.
Auth Flows
Platform: POST /api/auth/login → Session → X-Tenant-Slug, X-Org-Id on requests.
POS Register: POST /api/pos/register/authenticate — email + PIN. Requires platform session first.
API Client: frontend/src/api/client.js — Axios, withCredentials, X-Tenant-Slug, X-Org-Id from localStorage.