carlos@cesaints: ~/projects/luxury-registry.md — zsh

Command: cat projects/luxury-registry.md

projects/luxury-registry.md · 2.1 KB

A luxury vehicle and asset registry, from editorial site to sales console

Two generations of a product for an international client in the luxury sector: an editorial register with its own CMS, two-factor login and cookieless audience measurement, then a vehicle storefront with a console for the sales desk. Neither generation was deployed; this case is about the engineering and the product decisions, not business results.

open the demoa simulation of the system with fictional data · 6 screens

Role
Sole engineer, from the visual system to the sales console
Period
Jul 2026 – Sep 2026
What I did

Me: Product, visual system, architecture, data model, CMS, audience measurement, storefront, the sales desk console, access rules, security tests and the interface truthfulness review.

Private project, described without identifying the client, product or company.

Diagram

From editorial register to storefront with a sales console

In the first generation, the editorial register with its catalog feeds the cookieless audience measurement, which keeps the IP only as a hash, and the CMS, with a second factor and a publish gate, shows the audience panel. In the second, the storefront is rendered on the server, and only each car's public type goes to the browser; a buyer's interest goes to the database. The sales desk console checks roles in the middleware, the page and the action. Both use a Postgres with RLS, holding cars, leads and team profiles, and the audit trail is written only by a function that derives the author from the session.

Context

An international client in the luxury sector sells vehicles and other goods discreetly. The product had to feel like a private register rather than a dealership, and give the sales desk a place to work its leads. It went through two generations: an editorial register with a CMS, from July to August 2026, and a storefront with a sales console, from August to September. Neither generation was deployed. The first runs entirely on a local machine; the second has a complete CI but no deployment target. There is no traffic, no sale and no other business result to show.

What I built

  • The editorial register. A home page with a geometric lattice drawn in CSS only and a band of light that crosses the pattern, numbered departments, an automobile catalog with search and filters in the URL, a provenance page for each lot, and a per-lot enquiry in which the browser sends only the lot’s identifier.
  • The CMS. Two-factor login, lot editing with a publishing gate, photos checked and re-encoded, and the “who is on the register” panel: the enquiry funnel, the most viewed lots, the filters in use and the searches with no result, which point at what the inventory lacks.
  • The storefront. Search by marque, model and engine, prices in two currencies at a fixed rate, filters by category, price and power, a server-rendered page for each car, and an enquiry form that arrives with the car attached and gives the buyer a reference to quote when the desk calls.
  • The sales desk console. A lead pipeline in the desk’s time zone, with saved status changes and CSV export, and fleet management with verified or estimated specifications and a preview of each listing as the buyer sees it.

What I would do differently

I would start with the truthfulness review instead of ending with it. In the first generation the home page claimed things the catalog did not have, and the search metric was never filled in; in the second, the unbacked claims only came out at the very end. And I would write tests from the first generation, which ended with types and lint in its CI but no tests at all.

Constraints

  • Discreet sales, so the site has to feel like a private register, not a dealership.
  • What the sales desk reads about a car or a lot must not come from the visitor's browser.
  • Audience measurement with no cookie and no persistent identifier.
  • A price appears only once the car's specification has been checked.
  • A team with three roles, and accounts created with a temporary password.

Decisions

Our own audience measurement, with no cookie

Context
The house needed to know what visitors look for and cannot find, without a cookie or a persistent identifier in the way of a discreet buyer.
Choice
First-party events with a session that lives only in the tab for 30 minutes, Do-Not-Track and GPC respected, the IP kept only as a daily-salted hash and erased after 30 days, free text stripped of e-mails and phone numbers, and events kept for 13 months.
Gains
  • The panel shows the enquiry funnel and the searches with no result, which become inventory gaps.
  • No personal data is stored in the clear.
Costs
  • Without a persistent identifier there is no way to tell whether the same visitor came back another day.

A lot as a state machine, with a publishing gate

Context
A lot moves through draft, available, in closing, acquired and withdrawn, and a sold lot still counts as part of the house's track record.
Choice
Explicit transitions, "acquired" as a terminal state, and publishing blocked until the lot has a provenance story of at least 180 characters and at least one photo.
Gains
  • The catalog never shows a lot without a story or a photo.
  • A sold lot stays on the register as realized provenance, without an enquiry button.
Costs
  • Fixing an acquired lot means withdrawing it, since that is the only way out of the terminal state.

A measured boundary between server and browser

Context
The internal record of each car has 30 fields, and the server-rendered storefront sent all of them to the browser.
Choice
A public type with 17 fields, built on the server, and a test that fails any client component importing the internal type.
Gains
  • The storefront's serialized data dropped by 28.7%.
  • A new field on the internal type cannot leak by accident.
Costs
  • Two types to keep in sync whenever the storefront starts showing a new field.

Authorization in three layers, on purpose

Context
The console has three roles (admin, sales management and inventory staff), and every account starts with a temporary password.
Choice
Checks in the middleware, the page and the action or route; the temporary password change is enforced in the same three layers; sessions are signed with a fixed algorithm and a validated issuer and audience.
Gains
  • Forgetting the check in one layer does not open the screen or the action.
Costs
  • The same rule lives in three places and has to change together.

The interface only states what is true

Context
The storefront showed claims about processes, facilities and services that did not exist, invented transactions as social proof and vehicle data generated from a hash.
Choice
Remove everything without backing, show a price only on listings with a verified specification, and flag estimated specifications in the console until someone checks them.
Gains
  • Buyers never see a number nobody checked.
  • The desk knows which listings still need checking.
Costs
  • More cars stay "on request" until someone checks their specification.

Stack and why

Next.js
Both generations: server-rendered pages, on-demand revalidation and a tested boundary with the browser.
TypeScript and Zod
Validation at every boundary; inventory coming from outside goes through the same schema and fails closed.
Supabase (Postgres with RLS)
Cars, leads and staff profiles, with an audit trail written only by a function that derives the actor from the session.
jose
Signed console sessions, with a fixed algorithm and a validated issuer and audience.
sharp
Re-encoding the photos uploaded to the CMS, without GPS or EXIF.
Tailwind CSS v4
The register's visual system as tokens, with the lattice drawn in CSS only.
GitHub Actions
Types and lint in the first generation; in the second, also security tests, secret scanning, a dependency audit and a bundle scan.

Results

  • Second-generation CI with types, warning-free lint, 21 security test cases, secret scanning, a dependency audit and a build with a bundle scan.

    audited private repositoryThe repository's workflow and tests(Audit of the private repository, Sep 2026)
  • An adversarial review of my own code before closing the second generation: 44 findings fixed, 1 of them critical.

    audited private repositoryThe repository's history(Audit of the private repository, Sep 2026)
  • Storefront serialized data down from 193,016 to 137,580 bytes (−28.7%) by sending only 17 of the 30 fields of each car.

    self-reportedMeasurement recorded in the project
  • Photo archive down from 663.8 MB to 51.2 MB (−92.3%) after converting to WebP, and image requests on first load down from 306 to 66.

    self-reportedMeasurement recorded in the project

Security angle

Attack surface

  • A public enquiry form that stores leads with contact details.
  • An internal console with three roles and accounts created with a temporary password.
  • The register's CMS, with login and photo uploads.
  • Audience events collected from the browser.
  • CSV export of the sales pipeline.

Controls in place

  • A 16 KB cap counted in bytes before parsing, strict validation, two rate limits per IP and a trap field on the public form.
  • Control and bidirectional-override characters refused; the IP is derived on the server and never used to authorize.
  • Leads written only by the server, with RLS in the database and an audit trail written by a function that derives the actor from the session.
  • CMS login with scrypt hashing and TOTP with a one-step tolerance that refuses reuse of the same code.
  • Enquiries that send only the lot's identifier; the server resolves its title and code from the register.
  • Photos checked by content and re-encoded without metadata; CSV exports with formulas neutralized.

What I would test today

  • A public sign-up trying to become staff with the migrations applied together, the kind of escalation the review found and closed.
  • Bypassing the per-IP limit with forged proxy headers.
  • Reusing the same TOTP code within the tolerance window.

Evidence

  • audited private repositoryTwo audited private repositories(Audit of the private repository, Sep 2026)