AZ
Back to constellation
CommercePublished

Chekka

A Nigerian professional car-inspection platform — a Next.js 16 monolith built on the Managerenta conventions, with a locked-report integrity model and a live inspection feed.

Next.js 16TypeScriptMongoose 9Redis (cache + pub/sub)AWS S3Zod@react-pdf/rendererPlaywright
Read the write-up

Overview

What it is

Chekka ("before you buy — Chekka") is a Nigerian car inspection and verification platform. A buyer books an inspection; a professional inspector verifies the vehicle and files a structured report; the buyer gets a report they can trust before handing over money. Five roles — buyer, inspector, consultant, manager, admin — live in one users collection discriminated by a role enum, with granular permissions attached to the manager role only.

Descended from the reference architecture

Chekka is explicitly "built on the same conventions as managerenta-client" — its README says so on line 5, and the spec's "Tech Stack & Code Conventions" section embeds the exact skeletons the build then follows verbatim: the same server-only src/server/ triad, the identical withApiHandler(withAuth(...)) route shape, and the same Mongoose model conventions (pre/post("aggregate") hooks, per-*DB databaseResponseTimeHistogram timers, select:false soft-delete, mongoose.models[...] memoization). The infrastructure is deliberately unsurprising so the surprise budget can all go to the domain.

The inspection lifecycle is a state machine

The core inspections collection embeds the car, buyer contact, pricing (price, platformFee), the full lifecycle timestamp set (assignedAt, acceptedAt, startedAt, reportDeadline, completedAt, reportLockedAt, …), the embedded report sub-schema, and a photoCount. Its status field is a constrained enum that advances in one direction:

StatusMeaningEnters via
submittedbooked, awaiting assignmentcreateInspection
assignedan inspector is attachedassign (or at creation → stamps assignedAt)
declinedinspector rejected — excluded from every dashboard bucketdecline
scheduledinspector accepted; date setaccept
in_progressinspection underway (currentSection tracks the live section)start
report_processingphysical done; report being filed (reportDeadline runs)complete-physical
completedreport locked & filed (reportLockedAt set)submitReport(lock)

Pricing is computed server-side in createInspection.ts from an admin-tunable siteConfig.pricing (standard / premium; special_request = 0) plus a flat URGENT_SURCHARGE = 10_000; assigning an inspector at creation stamps assignedAt and jumps the status straight to assigned.

Report integrity is the product

A report a buyer paid to trust must be immutable once filed, and its numbers must be the server's — not the client's. On submit, Chekka recomputes the summary counts from the checklist item statuses across all four sections and refuses to touch a locked report:

if (current.reportLockedAt) throw ErrReportLocked;
const all = [...report.exterior, ...report.interior, ...report.mechanical, ...report.roadTest];
const summary = { ...report.summary,
  passed:  all.filter((i) => i.status === "good").length,
  minor:   all.filter((i) => i.status === "minor").length,
  serious: all.filter((i) => i.status === "serious").length };
if (lock) { patch.status = "completed"; patch.reportLockedAt = new Date(); patch.completedAt = new Date(); }

Locking also publishes a report_filed event to the admin live channel and emits the buyer's "report ready" notification best-effort. Sharing a finished report is a read-only, self-expiring capability: an unguessable uuidv4() nonce maps to the inspection id in Redis under a 7-day TTL, so the link grants unauthenticated read access to one report and the inspection id never appears in the URL:

const SHARE_TTL_SECONDS = 60 * 60 * 24 * 7; // 7 days
const nonce = uuidv4();
await redisUpdateKeyString(shareKey(nonce), { inspectionId }, true, SHARE_TTL_SECONDS);
return { nonce };

Media and real-time

Photos are a separate append-only inspectionPhotos collection with a denormalized photoCount maintained by atomic $inc — the decrement clamped { photoCount: { $gt: 0 } } so a race can't drive it negative — and stored S3 filenames are swapped to signed URLs (24-hour expiry) in the aggregate hook. A live inspection feed rides Redis pub/sub → SSE (inspector-side actions publish; buyer and admin consume), with currentSection tracking which report section is in progress. Report PDFs are rendered with @react-pdf/renderer. Overdue enforcement queries status: "report_processing", reportDeadline < now for the admin "Overdue Reports" view.

Testing & security posture

15 Playwright specs cover auth and auth-gating, booking, the inspection flow, inspector photo upload and report UI, the live feed, share links, consultant chat, and the admin queue/managers/site-config. Unit coverage is thinner than Managerenta's — no Vitest is configured here — so the safety story leans on the inherited spine: the shared withApiHandler (rate-limit + CSRF), withAuth (JWT + refresh rotation), Zod on every body, and report-lock immutability.

An honest correction to the internal brief: the driving spec (Chekka_Core_Features.md) is 4,728 words across 596 lines, not the "37k" the brief claimed — a dense, well-structured twelve-feature document, not an inflated one.

Related write-ups