FRQN®

Work / Wheelness Technologies LLP

Veynity

The second product I built at Wheelness Technologies, for the same gated communities as the first. It decides who gets into a residential society and on what basis: the visitors who park, the workers who come in every week, and the companies that send them. One Cloudflare Worker, no front-end framework, and most of the design went into deciding how it is allowed to fail.

Sole engineer2026Visit live site ↗
Roles that can sign in
5
Tests holding the behaviour
403
Languages on every visitor page
3
Front-end frameworks
0

01 / The problem

A car blocks a gate. A resident is shouting. The guard has no way to reach whoever parked it. The usual answer is an app everyone installs, which guarantees it is never the thing in anyone's hand when it matters. A sticker with a QR code is the thing that works, because anyone who can point a camera at it can file a report with no account and no download.

The harder half arrived after that. The same gate also admits maids, drivers, plumbers and cleaners, sent by companies the society has no relationship with, carrying identity documents somebody has to check and then store. Nobody in that chain can be trusted to remember a rule, and the whole thing runs through an old phone held by a guard with a queue behind him.

02 / What I built

The whole platform is one Cloudflare Worker in TypeScript. Data in D1, documents in R2, and pages that are just functions returning HTML. No React, no build step beyond Wrangler. Images are resized in the browser before they are sent, which is what keeps the server's work small enough to stay inside the free tier, and that constraint is the reason there are no payments and no SMS.

Five roles sign in: an owner over the whole platform, an admin per society, guards at the gate, service companies who manage their own staff, and the workers themselves. Visitors and residents never get an account at all. Every change appends to a log of events, and every figure on the admin dashboard, including the median time to clear a report, is counted from that log rather than a total somebody has to keep up to date.

Car cleaning is read live from Wheelness rather than copied, so the two products share one truth about a society instead of two that drift.

03 / Deep dive

An account starts out able to do nothing

A platform where a company signs itself up is a platform where strangers create accounts all day. The safe version of that is not a longer checklist on each page. It is an account that can do nothing until a person with the authority decides otherwise.

So a new account is pending, and one line in one function refuses a pending session. Every guard, admin and owner route sits behind that function, which makes it a property of one place rather than something each new page has to remember. The only two screens a pending account reaches are its own waiting screen and a single document upload. Everything else returns the same 404 a stranger would get.

Two smaller rules do the rest. A worker whose identity document is already on record is admitted straight away with a badge; without one they wait in a review queue. And a company can ask for its worker to be let into a society but cannot approve it, because the company is not the party taking the risk.

  • Pending is the default, and it is refused in exactly one place
  • An owner is deliberately not let through the company and worker guards
  • An empty scope on a scoped query is how one company reads another's staff
SIGN UPself, or createdPENDINGcan do nothingREVIEWERadmin or ownerACTIVEbadge issuedWAITING SCREENand one uploadNO ID ON FILEjoins the queueID ON FILEALL IT MAY REACHEVERY OTHER PAGE RETURNS 404, FROM ONE LINE IN ONE FUNCTIONA COMPANY MAY ASK FOR ITS WORKER, AND MAY NEVER APPROVE ONE
Fig 01 · An account that starts with nothing

04 / Deep dive

Rules a person cannot forget

Two rules hold this up. A visitor's phone number never appears anywhere you can reach without being a guard or an admin, and every query only ever sees one society. Both are the kind of rule that holds for months and then quietly breaks in one new function written in a hurry.

So neither one relies on anybody remembering. SQL is only allowed to exist in one folder, and every function in it takes the society as its first argument and refuses to run without one. The thing that writes events rejects any payload containing ten digits in a row, and it throws rather than quietly stripping it out, because silently cleaning up would hide the mistake that put a phone number there.

The same instinct runs through what each person is shown. A guard sees the kind of identity card and its last four digits, never the document. The console releases a flat's phone number only after the guard has recorded that the driver did not answer. And a tag that does not exist and a tag nobody has assigned return the same response, so the page cannot be used to work out which tokens are real.

  • Society id is the first parameter of every repository call
  • A phone number in an event payload is a thrown error, not a redaction
  • Documents sit under a random key and are served private, no-store
ROUTEsession, communityREPOSITORYcommunity id or throwDATABASEthe only sql in the appEVENTSappend only, never editedSCOPED QUERYEVERY CHANGEA PAYLOAD HOLDING A TEN-DIGIT RUN IS THROWN, NOT QUIETLY REDACTEDREPORTING READS THE EVENTS, NEVER A COLUMN SOMEBODY KEPT IN SYNC
Fig 02 · Scope and secrecy the code cannot forget

05 / Deep dive

Failure, ranked in advance

Most systems fall over in whatever order the code happens to break. This one has a written ladder, and the rule is that nothing further down may take out anything above it.

So the printed tag carries the gate's phone number for the case where none of the software is running. A four character code is printed large, for when the camera will not read the QR. Every page except the photograph works with JavaScript switched off. If the document store is unreachable the report still files and quietly goes without a picture, because a report with no photo is worth enormously more than no report. With no flat list the flat becomes a free text box. With no phone number the report still opens and the console says to use the flat instead.

Wheelness sits at the bottom of that ladder on purpose. If it cannot be reached, every gate page is untouched and only the cleaning pages change, and they say which of the four possible reasons it is rather than showing an empty list. There is a test that serves those screens against a dead Wheelness and expects them to load.

  • The required path: scan, report recorded, guard console shows it
  • Photograph upload can fail without failing the report
  • English, Hindi and Kannada on every visitor page and printed tag
THE SERVICE IS DOWNthe gate phone number is printed on every tag, a person calls a personTHE QR WILL NOT READa four character code is printed at 28pt, the guard searches itDOCUMENT STORE IS DOWNthe report files and quietly goes without a photographWHEELNESS IS UNREACHABLEevery gate page is untouched, cleaning says which failure it isCRITICAL PATH: SCAN, ROW EXISTS, GUARD SEES ITA LOWER RUNG MAY NEVER TAKE OUT A HIGHER ONE
Fig 03 · Ranked failure, decided in advance

06 / Outcomes

  • A guard with no app and no account can reach a driver from a sticker on a windscreen
  • Workers, the companies that send them and their identity documents are handled by one system, and no company can approve its own staff
  • 403 tests cover the pages, the rules and the ways it is meant to break
  • It fits inside Cloudflare's free tier on purpose, which is also why there are no payments

Stack

Runtime
Cloudflare Workers, Hono, TypeScript, Wrangler, no bundler
Data
Cloudflare D1, an append-only event log, one scoped data layer
Storage
Cloudflare R2, images resized in the browser, unguessable object keys
Quality
Vitest on the Workers pool, 403 tests, automated rule enforcement

Next case study

Sleek Interio