The Part Timer: Designing a Gig Marketplace with 42 Drawings Before the Code
Held payments, a 72-hour release window, dual control and API-level masking — how a system drawing set shaped a Sri Lankan work marketplace.

Gig marketplaces rarely fail on the happy path. They fail on Tuesday morning, when a crew of six is booked to unload a 40-foot container, two people don't show, the client disputes the milestone, and somebody has already been paid.
The Part Timer is a multi-role work marketplace for Sri Lanka — heavy labour, ground handling, cleaning, trades, design, events, IT and back-office work, for individuals, crews and companies. Before writing much code, I drew it: a 42-sheet system drawing set. This post is about why.

The one rule everything follows
The client's money is held at a licensed payment provider from the moment a milestone is funded, and moves only after the client confirms the work is right — and then not immediately.
A 72-hour window sits between approval and release, so a problem found the next morning can still stop the payment. The platform keeps a ledger; it never holds funds. That single rule shapes the data model, the state machines, the admin roles and the compliance sheet.
Drawing before coding
| Section | Sheets |
|---|---|
| A · Architecture | D-01 – D-06 |
| B · Domain and data | D-07 – D-12 |
| C · Admin and security | D-13 – D-15 |
| D · Core flows | D-16 – D-22 |
| E · State machines | D-23 – D-28 |
| F · Realtime chat | D-29 – D-32 |
| G · Search, ranking and AI | D-33 – D-35 |
| H · What is shown to whom | D-36 – D-37 |
| I · Crews and companies | D-38 – D-39 |
| J · Compliance and navigation | D-40 – D-42 |
The editable source is Mermaid in docs/system-diagrams.md. The rendered set, system-diagrams.html, is fully self-contained — every diagram is a pre-rendered SVG embedded as a base64 data URI, so it needs no Mermaid runtime, no CDN and no network. Open it from disk on a site laptop and it works.
Two gotchas I hit re-rendering:
;terminates a statement in Mermaid, so named HTML entities like—silently truncate unquoted sequence-diagram text. Use literal characters.- An SVG in a data URI is parsed as XML, which only knows
& < > " '. Any other named entity breaks the image.
A prototype that proves the rules
prototype/app.html is a working interface with seeded data — one file, no build step, no dependencies. A role switcher re-renders every screen through different eyes, which is the fastest way to see access rules work:

| Try this | What it shows |
|---|---|
| View a job as Guest, then as a member | Budget masking — hidden figures are absent from the response, not CSS-hidden (D-36) |
| Request a worker's contact details, switch to the worker and approve | Time-boxed, revocable, logged PII consent (D-37) |
| Approve a milestone and watch the ledger | Approval moves no money — it only arms the 72-hour timer (D-18) |
| Fast-forward the window | Release posts one balanced pair: net to wallet, fee to revenue (D-20) |
| Raise a dispute before the timer fires | Timer cancelled, escrow frozen (D-25, D-26) |
| Type a phone number in chat before funding | Masked, with an escrow-loss warning (D-32) |
| Open payout batches as two finance users | Self-approval refused — dual control (D-15) |
| Open payout batches as Super Admin | Super admin governs access but cannot move money (D-13) |
Every row is an edge case that would otherwise become a support ticket — or a fraud.
Design decisions
Separate dispatch from money. Geolocation and crew dispatch scale with the morning shift call-out; the escrow subsystem scales with nothing and must never be wrong. They're isolated so one can be scaled, restarted or rewritten without touching the other.
Masking in the API, not the UI. If a budget is hidden from a guest, the field is not in the JSON. CSS-hidden data is public data.
AI recommends, humans decide. docs/ai-verification-pipeline.md specifies twelve agents that fact-check registrations, identity documents, licences, portfolios, job posts and chat — with full production prompts, output schemas, deterministic checks, routing, guardrails, evals and a cost model. The rule is the same everywhere: the AI writes a recommendation; a human approves.
Compliance as an engineering sheet. D-40 maps Sri Lankan statutory obligations onto concrete controls. It's not legal advice — the PSP structure and contractor terms still need a practitioner — but it means compliance questions have a place in the design.
The running service
service/ is a real build: FastAPI + SQLAlchemy 2.0 over SQLite (Postgres-swappable through five adapters) behind a static HR portal, packaged with Docker. It implements dynamic multi-team membership — one person, many active teams, leader or member per team — gated by a lightweight identity-verification workflow with the AI-assisted cross-check implemented, not only specified.
| Layer | Choice |
|---|---|
| Frontend | Plain HTML + CSS + JS, multi-page, no build step |
| API | FastAPI |
| Data | SQLAlchemy 2.0 over SQLite now, Postgres later |
| Realtime | FastAPI WebSockets, in-process pub/sub → Redis at scale |
| Money | Licensed PSP trust account; platform holds a ledger |
Deployment is GitHub Actions to Cloud Run with path filters — push to hr-platform/api redeploys only the API, push to hr-platform/web only the web. Auth is keyless via Workload Identity Federation. See How I Ship 23 Projects.
Finished this one?
Progress is saved in this browser.

