PRJ-03Car brokerage

Autobroker: one number, and only one place it comes from.

A multi-tenant CRM for car brokerage. The rule for what a deal made is written once in the application and once in SQL, in the same change, so no two screens can quietly answer the question differently.

Client · American Auto Group, Staten Island NY

aagleasing.com
Det. 01 · the live productaagleasing.com
The Autobroker system in production

PRJ-03-AScope of work

What the business does.

A broker does not sell a car off a lot. He takes what a buyer wants, finds it across a network of dealers, and gets that buyer financed. The work that decides whether he earns anything is a credit application: a long, dull, legally serious form a lender will reject if one section is missing.

Multiple brokers, multiple branches, and a company that has to be able to say what each deal actually made, to the broker, to the accountant, and to itself.

The public website and the CRM are route groups in one application on one deploy. There is nothing to integrate between them because they are the same program: a form filled in on the site is a row in the pipeline a second later, with nothing retyped and nothing waiting in an inbox.

The problem shape.

Profit on a deal was computed in four different places, and they answered in three different ways on the same day: the dashboard tile, the leaderboard two rows below it, the reports page, and the broker's own row.

Four places computing one number three ways is worse than any one of the three simply being wrong, because it means no screen can be trusted. And the specific failure mode is silent: costs recorded before any commission is typed in make a deal look like a loss, which is correct as a subtraction and wrong as an answer.

PRJ-03-BDetail callouts

What was built.

Each item names the file that proves it. The paths are relative to the repository.

A

One money model, written twice on purpose

Every profit total in the product comes from one module, and the same rule exists as SQL in the database so a trigger cannot compute one formula while the screen computes another. The two move in one commit or neither moves. With no revenue recorded, profit is reported as unknown rather than as a loss, and the costs already spent are shown separately rather than dropped, hiding them would overstate profit, which is the opposite lie.

Proof

lib/deal-money.ts, supabase/migrations/*_profit_has_one_writer.sql

B

Reports that read from the same rule

The reports page, the leaderboard and the dashboard all route through the money model rather than summing a stored column each in their own way. A correction lands on every screen at once, which is the point.

Proof

app/(app)/reports/, lib/broker-payouts.ts

C

A co-applicant answers the same questions, not fewer

Most credit forms give the second applicant a cut-down version, and lenders send those back. Here the co-applicant renders the same component as the primary, so both answer the same 35 questions and both upload both sides of a licence. Four more fields become required automatically when time at the current address is under two years, because that is what the lender asks for anyway. The completeness check runs the same list server-side for each person, so a trimmed co-applicant is not something that can happen by accident.

Proof

app/(site)/credit-application/, counted in the form component

D

The Social Security number is ciphertext, and every look at it is written down

AES-256-GCM, with the key held only in the server environment, never sent to the browser, never stored in the database. There is no plaintext fallback: if the key is missing the submission is refused rather than saved in the clear. Revealing a full number writes to an access log first, and the disclosure depends on that write succeeding, so a number cannot be read without a record of it. Two keys are supported at once so rotation has no window in which an application submitted mid-change becomes unreadable. That is not hypothetical: a real application arrived during the afternoon the rotation was written.

Proof

lib/crypto-ssn.ts, lib/pii-audit.ts

E

Retention that runs on a schedule

Scheduled jobs handle the parts of handling personal data that nobody wants to depend on remembering: retention of the sensitive fields, and re-keying when the encryption key changes.

Proof

app/api/cron/pii-retention/, app/api/cron/ssn-rekey/, lib/pii-retention.ts

F

Lease milestones that chase themselves

A daily job scans open deals and creates reminder tasks at the lease milestones that matter, 180, 120, 90 and 30 days out, and flags deals that have not moved. Tasks are written idempotently against a dedupe key, so a job that runs twice does not produce the same reminder twice.

Proof

app/api/cron/automations/route.ts

G

Multi-tenant, with the client's own public site attached

Company and branch scoping runs through the data model, and the brokerage's own public website is part of the same deployment: a lead from the site arrives as a record on the pipeline rather than as an email to somebody's phone.

Proof

app/(site)/, supabase/migrations/20260804120000_website_leads.sql

PRJ-03-CReference

Where this lives.

Its own database, its own deployment. Nothing is shared with the other two systems except the code that was proven in them first.

What this sheet does not do is quote a revenue number or a lift in conversions. The build is recent, and any figure like that would be a guess dressed up as a result. Everything above describes what the software does, and all of it can be demonstrated live.

System
Autobroker
Repository
autobroker-crm
Trade
Car brokerage

Files named on this sheet

  • autobroker-crm · lib/deal-money.ts, the one money model
  • autobroker-crm · lib/crypto-ssn.ts, encryption and key rotation
  • autobroker-crm · app/api/cron/automations/route.ts, lease milestones
  • autobroker-crm · lib/stripe.ts, byte-identical in all three systems

Three separate deployments, three separate databases, and no shared data of any kind between clients. What they do share is the code that was proven in one of them first — lib/stripe.ts is byte-for-byte identical in all three repositories.

Back to the drawing index

SHT-08Issued for construction

Start with the audit.

A short video walkthrough of where your lead flow leaks and what it would take to close it. Free, and there is no call afterwards unless you want one.

Get my free audit