📊 Project Completion Progress

83%
17%
Complete 39 of 47 active weeks · 83%
Remaining 8 weeks · 17%

Remaining work breakdown

  • Sprint 19 — Repairs Pro data migration scripts + production dry-run · 1.5 weeks
  • Sprint 20 — Security hardening + accessibility audit · 1.5 weeks
  • UAT + cut-over · 2 weeks
  • Hyper-care · 3 weeks

📋 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 (17 items)

📐 Amendments 17/17 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-mapretired S17 B1; plugin never built; deferred to B-006
A16FORCE ROW LEVEL SECURITY on all 26 tenant tables
A17withTenant must SET LOCAL ROLE ram_app — superusers bypass all RLS; role switch enforces isolation regardless of connection privilege

🏃 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 + CI all-green✓ CompleteCI verified (4 jobs)
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 Phase 3 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
  • 424/424 unit tests passing — 27 spec files, tsc EXIT 0 (+13 repair-codes unit tests in Part B Item 3)
  • e2e Test 3 (unmapped path) added to drfone-parse.e2e.spec.ts and passing
  • CI all 5 jobs green (runs 17–19) — lint, unit, integration, e2e, build · e2e 5/5 · migration 0005 applied cleanly · actions @v6 (Node 24) · B-005 closed 3/3

🧪 Test Coverage Snapshot

424/424
Unit tests passing
27 spec files
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
B-005 Remove --passWithNoTests from e2e CI step ✅ Closed — 3/3 (runs 17–19) Flag removed; e2e job now fails on zero specs discovered
B-006 Build eslint-plugin-ram-custom as workspace package Deferred Second engineer onboarding (same trigger as B-003)

🚦 Outstanding Operational Items

  • PAT push complete · runs 17–19 green · actions @v6 clean · B-005 closed 3/3
  • CI run 19 — green · B-005 closed 3/3 · --passWithNoTests removed
  • QC Workbench Unmapped Codes tab + resolve flow (Item 1a) + create-new-canonical two-step flow (Item 1b) — complete
  • Order 32 GB IONOS VPS + domain (needed before UAT)
  • Sprint 19 kickoff — Repairs Pro migration scripts pre-read

🎯 Remaining to Project Completion

  • Sprint 17 Part B — ✅ Closed · Item 2 ✓ · Item 1a ✓ · Item 1b ✓ · Item 4 ✓ · B-007/B-008/B-009 deferred with triggers · CI stable runs 17–22 · e2e 5/5 without safety net since run 20
  • Sprint 19 — Repairs Pro migration scripts (B-004 strategy, dry-run, rollback)
  • Sprint 20 — Security hardening + accessibility audit
  • UAT — Data migration, staff training, production cut-over
  • Hyper-care — Post-launch support window
  • Phase 3 (post-launch) — AI Bridge integration (Sprint 18 deferred · see backlog B-010)
Source of truth: docs/STATUS.md in saigates/ram-app-v2.0  ·  Update this page by editing docs/index.html