PutThrough Product engineering studio
Book a build call

Demo rescue

A marketplace where every seller could see every seller

Two-sided marketplaces make the multi-tenant failure expensive: the data that leaks is commercial, and the people it leaks to are each other’s competitors.

Built with Bolt on Firebase

A demonstration build, not a client engagement. We built this app, broke it, and repaired it to show the method. No client is named or implied, and the figures below are measurements from this build alone.

Stack
  • Bolt
  • React
  • Firebase
  • Firestore
  • Cloud Functions
Duration
[n] days

01Before

What was broken

  1. S1

    Firestore rules allowed any authenticated read

    The security rules granted read access to any signed-in user rather than scoping by seller. Any seller who created an account could query the full orders collection, including other sellers’ volumes, customers and pricing.

  2. S2

    Tenant identity came from the client

    The seller ID used to filter queries was read from a value the client sent. Changing it in the request returned another seller’s data, because the server never checked it against the authenticated session.

  3. S3

    Deployments failed unpredictably

    Cloud Functions were deployed from a local machine with environment variables that existed nowhere else. A deploy from any other machine produced a working build and a broken runtime, with no error tracking to explain it.

  4. S4

    No backups and no tested restore

    Firestore was running with default settings and no export schedule. There was no point at which data loss could have been recovered from.

02After

What we changed

  1. C1

    Security rules rewritten against the auth token

    Every rule now scopes to the seller claim on the authenticated token rather than to a client-supplied value. The rules have a test suite that runs against the Firestore emulator in CI, asserting cross-tenant reads fail.

  2. C2

    Tenant identity taken from the session only

    Seller ID is resolved server-side from custom claims. The client can no longer influence which tenant a query resolves to, and the parameter it used to send is rejected outright.

  3. C3

    Reproducible deploys and real error tracking

    Configuration moved into managed secrets, deployment moved into CI on merge, and separate projects created for staging and production. Error tracking and structured logging added, so a runtime failure now names itself.

  4. C4

    Scheduled backups and a restore we watched work

    Daily exports with retention, plus a documented restore procedure that was executed into a scratch project to prove it works. A backup nobody has restored from is not a backup.

03Measured

What it measured

Measure Before After
Collections readable across tenants [n] 0
Cross-tenant access tests in CI 0 [n]
Deploy success rate from a clean checkout [n]% 100%
Recovery point objective None [n] hours
Time to rescue — [n] days

Figures are measurements from this demonstration build. All demo rescues

Your app probably fails in one of these ways.

The audit tells you which, with evidence and a fix estimate, in two business days. If it finds nothing material you do not pay for it.

Prefer to write? Send your requirements

What do you need?

What it should do, who will use it, the must-haves, and any links. A few sentences is plenty.

Budget, if you have one in mind
When would you like to start?