iziwerk — the product
Same product, the hard half: a secure, multi-tenant SaaS where a freelancer runs every client — proposals, invoices, files, messages, documents — in one place. Built in deliberate phases, security-first, where every phase had to prove itself before the next was allowed to start.
// the spine
Row-Level Security, at the database
The spine of the whole thing is Row-Level Security — confidentiality enforced in the database, not in app code that could carry a bug. A client on one project physically cannot read another client's invoices, files or messages, even with a valid token hitting the API directly. And I didn't take that on faith. Every phase shipped with an adversarial isolation test — a script that logs in as a hostile tenant and tries to break in, asserting every attempt is denied.
| Phase | What it added | Isolation suite |
|---|---|---|
| A1 · Foundation | schema + RLS + auth (passwordless email code, mandatory TOTP, one-time recovery codes, passkeys; clients via magic-link, invite-only) | 34 |
| A2 · Workspace | dashboard, one-time client invites, per-project workspace (proposals, invoices, files, messages), tier gating | 69 |
| File security | server-side file-type allow-list (blocks executables), DB-enforced per-tier storage quotas | 82 |
| Documents + Support | document engine (17 types × 3 styles × 2 brands, PDF), help centre + ticketing, server-locked admin | 130+ |
| Billing + Email | Stripe subscriptions (plan set only by the signature-verified webhook, idempotent, out-of-order-safe), transactional + auth email | 161 |
161 / 161 passing — tenant confidentiality holds at the database.
// auth
Auth done right, not hand-rolled
Passwordless by design. Freelancers get a mandatory authenticator (TOTP) plus optional passkeys and saved recovery codes; clients get a frictionless magic link with optional TOTP — invite-only, always. The recovery path is built so an email inbox can never be a single master key.
// the decisions
The decisions that separate real from fake
The ones that matter are the unglamorous ones: privilege columns like plan and is_admin that are physically un-writable from the client and only ever set server-side; a white-label flag generated off the subscription tier so it can't be forged; payment status that changes only on a verified webhook, never on a browser redirect; uploads that can't be bypassed with a direct storage call. Every one of those is asserted in the test suite.
// documents
The document engine
The feature I'm proudest of. One variable-driven system renders every document a freelancer sends — proposals, invoices, quotes, contracts, receipts — in three styles the user picks, in their own branding, exportable to PDF. Free and mid tiers ship a tasteful default; the top tier unlocks full white-label — the same identity system, swapped by a few tokens. Seventeen types, three styles, two brand modes.
// the method
Directed, not vibe-coded
I ran this as a director, not a vibe-coder. An AI-orchestrated pipeline did the heavy lifting of code; I made every architectural and product call, red-teamed every plan, and ran the verification myself. A planning layer turned intent into exhaustive, bulletproof build instructions; an AI implementation layer built against them in plan-then-review-then-execute cycles; and I sat in the middle refusing anything that wasn't accounted for. When the isolation gate came back one assertion short of clean, I didn't ship it — I found the one, fixed it, and re-ran until every assertion passed. That discipline is the entire reason a days-long build is trustworthy instead of a liability.




// status
Honest status
The product is functionally complete and its security is proven. It is not yet publicly launched — real payments and real users are correctly gated behind company formation (SIA), legal (GDPR terms/privacy/DPA), and live-payment verification. That's not a gap; it's the honest order of operations. The hard, easy-to-get-wrong part — a secure, coherent, on-brand product — is done. What remains is paperwork and a launch, not engineering risk.