📋 Phase 1 — Operational Blueprint 10/10

  • Business context & actor roster locked
  • End-to-end device flow (10 stages + branch states)
  • 14 master-data entities defined
  • 10 workflows locked (#9 Client Portal deferred to v2)
  • 20 critical business rules locked
  • Battery health thresholds (<80 / 80–84 / ≥85)
  • Batch ID format spec (YYMMDD-CLIENT-COURIER-AWB5-QTY)
  • SLP dispatch_rule = BATCH_LOCKED
  • Aging flags (>14d repair, >21d warehouse)
  • Free-zone tax = 0% VAT, USD primary / AED reference

🏗️ Phase 2 — Technical Blueprint 13/13

  • #1 System Architecture (modular monolith)
  • #2 Tech Stack (Next.js 15, NestJS 11, Prisma 6, PG16, Redis 7)
  • #3 Data Model (Prisma schema + RLS policies)
  • #4 API Spec (OpenAPI 3.1 conventions)
  • #5 Auth & Security Model
  • #6 Project Structure (pnpm + Turborepo monorepo)
  • #7 File Storage Strategy (MinIO + B2 backup)
  • #8 Background Jobs (BullMQ queue design)
  • #9 DevOps & Deployment
  • #10 Repairs Pro Migration Plan
  • #11 Acceptance Criteria (Gherkin)
  • #12 Sprint Roadmap
  • #13 Amendments Appendix (16 items)

📐 Amendments 16/16 locked

A1withTenant wrapper mandatory — no bare Prisma calls
A2Late-append blocked when invoice.status = sent
A3Generalised numbering_sequences + sequence_definitions
A4expected_batches.session_count column
A5daily_metrics_snapshots table
A6Duplicate completed repair-code assertion (defence-in-depth post-Mig 0003)
A7FX rate snapshot read order
A8Magic-link auth stubs (501)
A9BullMQ concurrency=1 (per-org upgrade → backlog B-001)
A10'migrated' source enum on device_repair_codes
A11finalizeDispatch idempotency (FOR UPDATE + early return)
A12INSERT + UPDATE same Prisma transaction, callback form only
A13sequence_definitions seed table (global, no RLS)
A14Prisma $transaction callback form only (no array form)
A15ESLint: no-bare-prisma, no-withtenant-in-iteration, no-async-array-map
A16FORCE ROW LEVEL SECURITY on all 26 tenant tables

🏃 Sprint Execution — S0 → S17

Sprint Scope Status Verification
S0Foundations (monorepo, Docker, CI skeleton)✓ CompleteUnit tests
S1Tenancy & Auth (JWT + RLS)✓ CompleteIntegration ✓
S2Master Data CRUD✓ CompleteUnit tests
S3Asset Receiving✓ CompleteUnit tests
S4QC Workbench (triage, BER review)✓ CompleteUnit tests
S5Inventory & Parts Issue✓ CompleteUnit tests
S6Worksheets & Team Build✓ CompleteUnit tests
S7Outbound Dispatch✓ CompleteUnit tests
S8Invoicing & Pricing✓ CompleteUnit tests
S9Reports & Owner Dashboard✓ CompleteUnit tests
S10TypeScript polish (19 errors resolved)✓ Completetsc clean
S11Stub pages (Repairs, Technicians, Settings)✓ CompleteUnit tests
S12Devices page + pagination retrofit✓ CompleteUnit tests
S13drfone-parse BullMQ processor✓ CompleteUnit tests
S14bulk-upload processor + Team page✓ CompleteUnit tests
S15Infra catch-up (PG16, Redis, RLS idempotent)✓ CompleteIntegration ✓
S16Idempotent RLS + BullMQ e2e + CI tracked✓ CompleteE2E verified
S17 B1DrfoneCodeMapping + unmapped queue + reports count✓ CompleteE2E verified
Verification key:   Unit tests = code compiles + all jest unit tests pass  ·  Integration ✓ = exercised against live Postgres + Redis with RLS enforced  ·  E2E verified = full job → BullMQ worker → Prisma write chain validated  ·  Live-run verified = exercised against real external dependency (none yet — AI Bridge in Sprint 18 will be first)

🚀 Sprint 17 B1 Achievements 13/13

  • Migration 0004 — repair_codes catalogue table + 24 canonical codes seeded
  • drfone_code_mappings table + RLS + FORCE + UNIQUE(org_id, drfone_code)
  • device_repair_codes.repair_code_id FK (nullable) added
  • Source enum extended: drfone_mapped, drfone_unmapped
  • Legacy backfill for existing drfone / drfone_auto rows
  • DrfoneCodeMappingService — TenantContext for CRUD, explicit orgId for BullMQ worker (Rule #18)
  • DrfoneMappingsController — 7 routes including resolve endpoint
  • GET /initial-qc/unmapped-queue endpoint
  • GET /reports/drfone-unmapped-count endpoint
  • 30 demo mappings seeded for demo org
  • 428/428 unit tests passing — 25 spec files, tsc EXIT 0
  • e2e Test 3 (unmapped path) added to drfone-parse.e2e.spec.ts and passing
  • Commit 2dd95ca — 21 files, 2,230 insertions, 216 deletions

🧪 Test Coverage Snapshot

428/428
Unit tests passing
25 spec suites
14/14
Integration tests
4 suites · live PG + Redis
5/5
E2E tests passing
bulk-upload 2/2 · drfone 3/3
EXIT 0
TypeScript clean
apps/api + apps/web
  • RLS isolation verified — zero rows returned without valid tenant context
  • reserveNumber: 20 concurrent callers → sequential 1–20, no gaps, no duplicates
  • First-call race: 5 concurrent callers on absent row → 1–5, no duplicates (DELETE approach)
  • drfone-parse e2e: mapped path (source=drfone_mapped, repair_code_id non-null) ✓
  • drfone-parse e2e: unmapped path (source=drfone_unmapped, repair_code_id null) ✓
  • drfone-parse e2e: idempotency (second run, same XML → same row count) ✓

📦 Backlog

IDItemStatusBlocking trigger
B-001 BullMQ per-org concurrency upgrade Deferred Before second paying tenant
B-002 reserveNumber first-call TOCTOU race ✓ Resolved S16-1b
B-003 Shared-packages tsconfig missing Deferred Second engineer onboarding
B-004 Migration 0004 backfill performance (production scale) Deferred Sprint 19 production migration

🚦 Outstanding Operational Items

  • Manual push of 7 queued commits via PAT with workflows scope
  • First CI run on GitHub Actions — triage any failures
  • QC Workbench "Unmapped Codes" tab — UI not yet built (Sprint 17 Part B)
  • VPS order: 32 GB IONOS instance + domain registration

🎯 Remaining to Project Completion

  • Sprint 17 Part B — QC unmapped tab + repair_codes catalogue management + dashboard widget
  • Sprint 18 — AI Bridge integration (DrfoneCodeMapping inference layer, vLLM via WireGuard)
  • Sprint 19 — Repairs Pro data migration scripts + production dry-run
  • Sprint 20 — Security hardening + accessibility audit
  • UAT — Data migration, staff training, production cut-over
  • Hyper-care — Post-launch support window
Source of truth: docs/STATUS.md in saigates/ram-app-v2.0  ·  Update this page by editing docs/index.html