📊 Project Completion Progress

91%
9%
Complete 44 of 48 active weeks · 91%
Remaining ~4 weeks (UAT + hyper-care) · 9%

Remaining work breakdown

  • ✅ Sprint 19' — CLOSED · Freight Calculator + Purchase Prices UI + Client detail page + effective_price_snapshot_aed hook + 13 migrations · 3 weeks actual (planned 1.5 weeks)
  • ✅ Sprint 19.5 — CLOSED · 6 items: Runbook coherence + CLAUDE.md #21 + My Devices + B-018 fix + Quotations list + Batch Margin (Option b) · 1 week actual · 552→573 tests (+21) · denominator 47→48 · tracker 89% (43/48)
  • ✅ Sprint 20 — CLOSED · S-01..S-05 security hardening + A-01..A-06 WCAG 2.1 AA + B-013 backup/restore · 573→605 tests (+32) · CI #44 green · tracker 91% (44/48) · b84389c
  • UAT + cut-over · ~2 weeks
  • Hyper-care · ~1.5 weeks

91% → 44 of 48 active weeks (Sprint 20 closed). Denominator: completed 39 + 3 (Sprint 19') + 1 (Sprint 19.5) + 1 (Sprint 20) = 44; remaining UAT (2w) + hyper-care (1.5w) = 3.5w; total 48 (rounded). 44/48 = 91.7% ≈ 91% conservative. Percentage advances at UAT close.

📋 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

605/605
Unit tests passing
35 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)
B-007 Consolidate 12 hand-rolled confirmation dialogs to @ram/ui ConfirmationDialog Deferred On page touch or standalone cleanup sprint
B-008 Extract proxyToApi() helper; migrate 63+ proxy routes Deferred When proxy bug requires multi-file touch, or count crosses ~100
B-009 Consolidate duplicate repair-codes catalogue endpoints Deferred Before QC vs owner UI discrepancy appears
B-011 Per-model colours column + 32-model count correction Open Before device intake UI ships
B-016 Override notification upgrade (Postmark email/digest) Open > 3 override requests/week observed in production
B-017 Extract shared ROLES constant to @ram/shared package (web + API unified) Deferred Third mirrored constant added, or shared package needed for another reason
B-013 Database backup/restore — B2 multipart export + FK-ordered restore (owner-only) ✅ Closed — 2026-06-02 · commit 6540fae
B-018 listPurchasePrices silent zero-rows (Prisma query-path errors) ✅ Closed Sprint 19.5
B-023 JWT refresh token flow — replace 8h fixed expiry with refresh/access split Deferred Multi-shift warehouse use or token theft concern
B-024 Radix Dialog migration — replace hand-rolled modals with @radix-ui/react-dialog Deferred On page touch or standalone cleanup sprint
B-025 Backup cron automation — scheduled daily B2 export via BullMQ Open After B-013 manual backup proven stable in production
B-026 Fastify v5 upgrade — bump @nestjs/platform-fastify + @fastify/helmet v11→v13; remove @ts-expect-error in main.ts:44 Deferred Sprint 21+ cleanup, or Fastify ecosystem forces v5 bump
B-029 Resource monitoring on VPS — Netdata/Grafana; alert if RAM >60% sustained Open UAT Day 3 / post-launch operational baseline
B-031 Pre-existing any type cleanup — proper Prisma types in batches/ber-reviews/clients/expected-batch (4 files, ~14 warnings) Deferred Sprint 21+ cleanup; remove file-level eslint-disable

🚦 Outstanding Operational Items

  • Sprint 20 closed 2026-06-02 · CI #45 green on 15e27d3 · tracker 91% · 605 tests
  • B-013 backup/restore shipped — B2 multipart upload + FK-ordered restore · owner-only guard
  • Hostinger VPS order (4 vCPU / 16 GB / 200 GB NVMe) — required for UAT entry
  • Production domain registration + DNS configuration — required before SSL
  • Backblaze B2 account + ram-platform-backups bucket + application key — required for B-013 production use

🎯 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' — CLOSED 2026-06-01 — 13 migrations · FreightCalculatorService · Client detail page (3 tabs) · effective_price_snapshot_aed hook (B-D5) · ROLES mirror + /api/me · 552/552 unit + 18/18 integration · tsc 0 errors · Tab 2/Quotations deferred → Sprint 19.5
  • Sprint 19.5 — CLOSED 2026-06-01 — Runbook coherence pass ✅ · CLAUDE.md #21 ✅ · My Devices tab ✅ · B-018 fix ✅ · Quotations list page ✅ · Batch Margin report ✅ (Option b) · 1 week actual · 552→573 tests (+21) · denominator 47→48 · tracker 89% (43/48)
  • Sprint 20 — CLOSED 2026-06-02 — S-01..S-05 security hardening ✅ · A-01..A-06 WCAG 2.1 AA ✅ · B-013 backup/restore ✅ · 4 working days · 573→605 tests (+32) · CI #45 green · tracker 91% (44/48) · 15e27d3
  • UAT — Data migration, staff training, production cut-over
  • Hyper-care — Post-launch support window
  • Phase 3 (post-launch) — AI Bridge integration (Sprint 18 · B-010) · Customer portal (Phase 3 · B-015)
Source of truth: docs/STATUS.md in saigates/ram-app-v2.0  ·  Update this page by editing docs/index.html