# 10. Known gaps and roadmap

An honest list. Everything in "Known gaps" is either not built or built in a reduced form; nothing here blocks a pilot on one site, but several items matter before selling the SaaS broadly.

## 10.1 Known gaps in v0.1

| Area | Gap | Impact | Suggested fix |
|------|-----|--------|---------------|
| Security | No MFA / SSO for users | Medium for SaaS | TOTP (otplib) + optional OIDC at the ingress |
| Security | Rate limit per IP only; API quota eventually consistent across nodes (60 s) | Low | Redis-backed throttler and quota counter |
| Tenancy | Tenant deletion is manual (export then SQL); no self-service deletion | Low | platform endpoint that deletes by `tenant_id` in FK order |
| Inventory | Balance rebuild-from-ledger script not shipped | Low (both written in one transaction) | maintenance command replaying `inventory_movements` into `inventory_balances` |
| Inventory | Transfers between warehouses are modelled as ship + receive; no single transfer document | Medium for multi-site | TRANSFER order type with TRANSFER_OUT/IN movements (enum exists) |
| Inbound | OCR for scanned (image) PDFs not included; AI intake needs a text layer | Low | add an OCR step (Tesseract or a vision model) before extraction |
| Outbound | Carrier integrations (label/API) are not built; carrier is a master record only | Medium | adapter per carrier (DHL, Aramex) producing tracking numbers and labels |
| Outbound | Cartonisation is manual (operator decides cartons); no automatic packing suggestion | Low | pack-size heuristic from SKU dims |
| Outbound | No unpick endpoint: a picked-but-unshipped order cannot be cancelled or returned to stock without an adjustment | Medium | `POST /tasks/:id/unpick` posting UNPICK movements that restore the allocation |
| Outbound | Wave allocation runs in one transaction per wave (row locks held until commit); fine up to a few hundred lines per wave | Medium at scale | allocate per order in its own transaction with wave status tracked separately |
| Inventory | Count variance on stock that is allocated fails with INSUFFICIENT_STOCK instead of de-allocating the affected order | Low | release the allocation and re-flag the order short before posting |
| Inventory | Reason-code `requiresApproval` / `requiresPhoto` flags are informational only | Low | enforce in adjustments/receiving and add photo capture to RF |
| Integrations | `api_keys.rateLimitPerMinute` is stored but not enforced (the plan's daily quota is) | Low | per-key token bucket in ApiUsageService |
| Outbound | Wave strategies cover by-order/carrier/ship-date grouping; no zone-batch or cluster picking | Medium for high volume | batch pick tasks across orders with sorting at pack |
| Billing | Storage billing by temperature class requires tariffs per class; FX conversion not modelled | Low | contract-level currency only; add FX table if needed |
| Billing | Invoice numbering and tax are generic; no e-invoicing format (ZATCA/KSA, UAE) | Medium outside Kuwait | pluggable invoice export (XML/UBL) |
| Integrations | SAP adapter covers MATMAS and ORDERS inbound and generic outbound confirmations; DESADV/WHSCON mapping is a template | Medium | extend `sap-idoc.adapter.ts` per customer mapping |
| Integrations | SFTP/CSV and email intake connectors are defined (types, UI) but have no poller | Medium | worker job polling SFTP/IMAP into `integration_messages` |
| Reports | Occupancy by location is served by the locations endpoint; no per-location CBM capacity utilisation | Low | add capacity columns to the occupancy report |
| Documents | Templates are code (pdfmake); no per-tenant template editor or logo upload | Low | tenant branding settings + logo in document templates |
| UI | No component-level tests; i18n not wired (English only; Arabic email drafts supported) | Low | react-i18next with RTL layout, vitest component tests |
| UI | RF app runs in the device browser; no native wrapper for camera scanning | Low | PWA manifest + camera barcode (zxing) or Android wrapper |
| Notifications | `notifications` table exists; no in-app notification centre or push | Low | SSE/WebSocket feed, badge in the header |
| Observability | Logs only; no metrics endpoint or tracing | Medium | `/metrics` (prom-client), OpenTelemetry |
| Data | Demo seed creates an empty tenant; demo transactional data comes from test scripts | Low | `--demo-data` option replaying the e2e fixtures |
| Docker | Images not built in the packaging environment (no Docker daemon) | Build once in CI | first CI run on `main` |

## 10.2 Roadmap proposal

**Phase 1 (pilot, first site, 6 to 8 weeks)**
- Build and deploy images, staging with real master data, RF devices and label printers validated.
- Carrier records and manual tracking numbers; SAP mapping agreed with the group ERP team (MATMAS, ORDERS, WHSCON).
- UAT script (`docs/09-test-plan.md`) signed off; go-live with AI set to `disabled` or `anthropic` on intake + anomalies only.

**Phase 2 (hardening and second site, next quarter)**
- MFA, Redis throttling, metrics/tracing, notification centre.
- Inter-warehouse transfers, zone-batch picking, cartonisation suggestions.
- SFTP/email connectors, carrier adapters, e-invoicing export.

**Phase 3 (SaaS launch)**
- Self-service sign-up and billing of tenants (Stripe), tenant branding, i18n with Arabic UI, status page.
- Marketplace of connectors, per-tenant document templates, customer portal enhancements (order tracking, invoices, disputes).
- AI: vision intake for scanned documents, demand forecasting per SKU for replenishment, labour scheduling suggestions.

## 10.3 Decisions needed from the business

1. AI provider and data residency for production (Anthropic API vs disabled vs self-hosted model).
2. Which ERP documents are in scope for the first integration (purchase orders only, or also sales orders and confirmations).
3. Storage billing method per client contract (weekly opening plus inbound is the default used in the demo).
4. Whether the customer portal is part of the pilot (CUSTOMER role exists; UI is the same back office with scope restrictions).
