analytics
Portafolio de Iván
Projects chevron_right Quotes with no margin leaks

Production system · v1.2.0

shield_lock assertNoLeak() at runtime link Tokenised public link picture_as_pdf Branded PDF speed −250 MB of RAM

A public quote link that cannot leak margins

A tour operator in Chiapas used to quote with spreadsheets and text documents. Now they quote in their own app and send the customer a link where they build their own package, with the price always computed on the server.

Key numbers

1

single place where price is computed: the server

v1.2.0

version in production

SHA-256

fingerprint that invalidates a stale selection

~250 MB

of RAM saved by the stack choice

Tech stack

pnpm monorepoFastify 5DrizzlePostgreSQL 16ViteReact 19TypeScriptTailwind 4TanStack
schema

From the internal quote to the customer's link

Price is born and dies on the server. The customer's browser paints a total, never computes one, and the response passes a guard before it leaves.

  1. edit_note Internal

    The salesperson builds the quote

    Picks services and items; costs are frozen in a per-item snapshot.

  2. tag Reference

    Atomic reference, never recycled

    Each quote gets a unique reference number that is never reused.

  3. link Public

    Tokenised link

    The customer opens their link and picks occupancy and add-ons, with a live total.

  4. shield_lock Guard

    assertNoLeak()

    Every public response is inspected: cost, margin or supplier data throws an exception.

  5. picture_as_pdf Close

    Branded PDF on demand

    The document is generated on the spot, with the selection signed by its fingerprint.

store

Context

A tour operator in Chiapas sold packages by quoting in spreadsheets and pasting the result into a branded text document. Every customer change — one more room, one less transfer — meant redoing both by hand.

The goal was twofold: take repetitive work away from the salesperson, and give the customer something better than an email attachment. That is, a link where they can move the variables that actually matter to them and see the effect on their total, without having to write «what if there are four of us instead of two?».

With one underlying condition: in this business, margin is confidential. The customer must be able to play with their package without ever getting close to what that package costs the agency.

report

The problem

A public link that computes prices is, by definition, a link that can leak how they are computed.

As soon as the customer can recompute their total in the browser, the temptation appears to send them the data and let the browser do the maths. And that is where the business leaks: per-item costs, margin tiers, supplier names. It does not need to be shown on screen; it is enough for it to travel in the response.

I saw the other path up close, and its bill. In a sibling project the pricing engine was duplicated in the browser and on the server, and that duplication is today its worst debt: the two engines never match exactly, and every divergence is an argument with a customer who saw a different number from the one in the final document.

There was also the problem of time. A quote that has been sent and not answered is potential revenue going cold, and the salesperson has no way of knowing which ones are worth chasing.

rule

Key decisions

01 A guard that inspects every public response

Everything leaving through the public route passes through a function that inspects the payload and throws if it finds cost, margin or supplier data. It is not a team convention: it is a check that runs in production, on every request.

psychology Rules that depend on everyone remembering break the day someone adds a field in a hurry. A runtime guard turns «we must not leak» into «we cannot leak», and it fails loudly in development before it can fail quietly in production.

02 Price is computed on the server only

The customer's browser shows the total the server gives it; it has neither the pricing engine nor the data to reproduce it.

psychology Duplicating the engine duplicates the truth. I watched it become the worst debt in a sibling project: two implementations that never agree to the last decimal, and a recurring argument about which one is right.

03 Freeze the cost and sign the selection

Every item stores a snapshot of its cost at quoting time, the reference number is atomic and never recycled, and the customer's selection carries a SHA-256 fingerprint that invalidates it if the salesperson edits the quote afterwards.

psychology Without a snapshot, last week's quote silently changes when a rate changes. Without a fingerprint, the customer can accept a version that no longer exists, and the business ends up bound to something it never offered.

04 Choose the stack for what it consumes, not for what is fashionable

A lightweight data-access layer was used instead of the usual option, and an in-process PDF generator instead of spinning up a full browser to render. The difference is on the order of 250 MB of memory.

psychology All of this lives on a 16 GB server already running more than 60 containers. There, 250 MB is not premature optimisation: it is the margin between coexisting with the other services and starting to compete with them.

05 The screen that pays for the project

One view lists the quotes the customer opened and has not accepted, ordered by a deterministic score whose rules the interface spells out in words: «Opened 3 times · Read for 2 min · Expires in 2 days».

psychology Zero artificial intelligence, and it works from day one, because the rules are visible and the salesperson can agree or disagree with them. A score nobody understands does not get used; one that explains itself does.

construction

The solution

It is a monorepo with a Fastify backend over PostgreSQL and a React interface in TypeScript. The salesperson works in an installable app that assembles the quote; the customer receives a tokenised link that opens their own view, where they pick occupancy and add-ons and watch the total update.

When the customer confirms, the branded PDF is generated on the spot, with the selection already signed. The document is not stored in advance nor regenerated differently: it comes from the same source as the total the customer saw on screen.

And on the internal side there is the follow-up screen, which turns «I have a lot of quotes out there» into a list ordered by likelihood of closing, with the reason written next to each one.

emoji_events

Results

lightbulb

What I learned

That confidentiality is either designed in or it does not exist. Writing «do not expose margins» in a style guide prevents nothing; a check that blows up the request does.

That seeing another project's debt up close is worth more than reading about it. The duplicated pricing engine was not avoided out of doctrine, but because I had already seen the monthly bill it charges.

And that the feature which pays for the project is almost never the most sophisticated one. Here it was an ordered list with rules explained in plain language, without a single line of artificial intelligence.