Case study 05 / 10ProductIn development

Projevo

Evidence and progress platform for contractors. Small and mid-size contractors already pay for cost-estimating software, but almost nothing covers what happens after the estimate: showing the client real progress and keeping evidence that cannot be quietly edited later.

At a glance

18 / 18steps passed in the end-to-end runtime check
105tables carrying the organisation key
135row-level security policies
16 → 7admin menu items after the simplification
Period
July 2026 – present
Role
Product owner; sets scope, pricing model and release decisions; built with AI coding agents
Status
In development — not deployed yet
Links
Not public
Synthetic data Local demo with synthetic data: the owner overview compares verified with claimed progress and money paid with physical progress; on the phone, a field engineer records progress per work item. Projects, amounts and photos are fictitious; interface in Indonesian.

01Problem

Small and mid-size contractors already pay for cost-estimating software, but almost nothing covers what happens after the estimate: showing the client real progress and keeping evidence that cannot be quietly edited later.

02What I built

A multi-tenant SaaS grown from the evidence engine of CivMon, my owner-side platform: daily evidence, a hash-chained proof log with a head anchor, payment-milestone gates, red flags and a read-only view for the client.

03How it works

  1. Tenant isolation in the database itself. An organisation key on 105 tables and 135 row-level security policies with FORCE ROW LEVEL SECURITY. The tenant context is chosen on the server, set per connection at a single choke point and cleared before the connection returns to the pool; without a context the query fails closed.
  2. Tested as it runs. Runtime checks run the application as a database role with no superuser or RLS-bypass rights. PostgreSQL is used in development, CI and production, because earlier defects came from differences between SQLite test runs and PostgreSQL.
  3. CI on every pull request. API tests and a web build, with a PostgreSQL service.
  4. Cut to what contractors use. The admin menu went from 16 items to 7, other roles likewise.
Tenant isolation in the databaseA request is authenticated, the server chooses the organisation, sets it on the database connection at one choke point, row-level security policies return only that organisation rows, and the context is cleared before the connection returns to the pool. Without a context the query fails closed.Requestauthenticated usertenant never takenfrom the clientServer picks orgmembership checkedon the serverOne choke pointSET tenant contexton this connectioncleared before poolRLS policiesorg key on 105 tables135 policiesFORCE RLSRows of one orgapp role: no superuser,no RLS bypassNo context set → query fails closedPostgreSQL in development, CI and production
Swipe sideways to see the whole diagram. Tenant isolation: the organisation is chosen on the server and enforced by PostgreSQL row-level security.
Hash-chained proof log with a head anchorEach evidence entry stores the hash of the previous entry, so editing an old entry breaks every later hash. The latest hash is anchored as the head, and a verify step recomputes the chain.ENTRY #1041daily photosprev 9f3c…hash a71e…ENTRY #1042progress entryprev a71e…hash 4be0…ENTRY #1043milestone gateprev 4be0…hash c2d9…ENTRY #1044red flagprev c2d9…hash e58a…head anchor = e58a…Editing entry #1042 changes its hash, so #1043, #1044 and the anchor no longer match: verify fails.
Swipe sideways to see the whole diagram. Proof log: every entry carries the previous hash; the latest hash is anchored, so an edited entry is detectable. Hash values are illustrative.

04Results and scale

  • End-to-end runtime check passed 18 of 18 steps: a trial organisation is created, its admin completes setup, isolation holds over HTTP and the proof log verifies.
  • 52 commits and 27 merged pull requests between July and mid-September 2026; not deployed yet — being prepared for a first trial.

05Stack

  • Node.js (Express)
  • Next.js 16
  • PostgreSQL (row-level security)
  • Jest
  • GitHub Actions
Next case studyKasRapiCashier and cash book for small businesses