← Selected work
Case study · Client project

An approval engine that knows what not to do — shipped for a public-sector field-safety operation.

Forms, multi-step approvals, training, and audit trails — not as a demo UI, but as a production system with explicit capability boundaries and delivery discipline you can verify.

Architecture

Modular monolith · React + FastAPI · versioned JSON workflows

The hard part

Approval correctness + migration without silent mock drift

Proof

Contract APIs · automated gates · multi-layer acceptance

What & Why

A real operational loop — not a document tool.

[Enterprise Client] — a large public-sector organization in construction / field-safety operations — needed the full compliance loop to run in software: people, projects, forms, approvals, training, exams, and records, with real accountability.

Off-the-shelf tools didn’t fit. A conventional multi-person agency build meant timeline and cost the program couldn’t justify.

Constraint: correctness over cleverness. An approval that “usually works” is a liability. The interesting engineering is what the system refuses to pretend it can do — and how migration from mock to real API was forced to be honest.

System design

Modular monolith on purpose.

ADR decision: do not split into microservices for this domain. One deployable backend, clear module boundaries, a versioned JSON workflow engine that freezes a definition snapshot at submit time, dual-layer RBAC, and a file-bound license model for deployment control.

Architecture topology
Operators (browser)
React SPA — forms · todo center · training · admin
↓ HTTPS
API plane — FastAPI modular monolith
auth / sessions
projects & personnel
form templates & instances
workflow engine (JSON definitions)
training / exams / standards library
files & audit trail
SQLite (WAL) — business data

One backend, many modules, one audit trail. Complexity lives in workflow rules and permissions — not in a service mesh.

Trade-offs

Five decisions, with non-goals made explicit.

Decision 1

Refuse BPMN; own a lightweight JSON DSL

Problem

Approvals needed multi-step routing, withdraw/reject, and audit — but not a full BPM suite with designers, timers, and event gateways.

Options

Camunda / Flowable (heavy for this domain) · Temporal-class orchestrators (wrong problem) · Lightweight JSON definitions

Choice

Custom versioned JSON workflow DSL. Capability boundary documented in writing — including upgrade triggers for when a real BPM engine would become justified. Countersign/or-sign reserved in schema, not fake-shipped.

Cost

No visual process designer. You get a reviewable definition and tests that match the product.

Evidence: workflow capability-boundary doc · approval-engine sprint tasks
Decision 2

Reject / withdraw rules over “magic recall”

Problem

Real operators need to pull back mistakes without corrupting history or inventing admin backdoors.

Options

Unbounded admin rewrite · Soft “recall anytime” · Explicit reject + gated withdraw + resume rules

Choice

Explicit reject rules, three-gate withdraw, and resume-from-breakpoint after reject — history stays explainable.

Cost

More state transitions to design and test; fewer silent history rewrites.

Evidence: workflow engine tests · approval service paths
Decision 3

Unassigned roles fail closed

Problem

A step with no assignee is either a stuck process or a security hole if “someone admin” rubber-stamps it.

Options

Auto-assign to admin · Silently skip approval nodes · Fail closed + operational repair path

Choice

Soft-block at start when required assignees are missing; at runtime, CC-only nodes may skip, approval nodes wait for repair; admins cannot casually proxy-approve away the gap.

Cost

Operations must keep role staffing healthy. The system will not paper over governance failures.

Evidence: form workflow services · missing-assignee handling
Decision 4

Strangler migration with three hard fences

Problem

Replacing mock APIs with real ones is where demos lie — pages keep “working” while data never hits production storage.

Fence 1

Freeze API contracts before swapping implementations.

Fence 2

In real mode, any remaining mock call throws immediately.

Fence 3

Ratchet mock-import whitelist toward zero with a CI script.

Why it matters

Migration is louder and earlier — which is the point. Silent mock drift cannot ship.

Evidence: runtime mock assertion · mock-import ratchet script · API contract
Decision 5

Delivery discipline as a product surface

Problem

“Looks done” and “proven done” are different states — especially on compliance workflows.

Layers

Automated tests → API probes → independent strict acceptance → log verification

Choice

Multi-layer acceptance on real closed loops. When acceptance language was broader than actual scope, it was corrected in writing.

Cost

Slower green-check theater; higher trust when you say shipped.

Evidence: test-system playbook · acceptance reports with scope corrections
Code & proof

What you can publish without leaking the client.

Artifact A — Capability boundary, written down

The workflow engine documents what it will not do (heavy BPMN constructs, visual designers, event-gateway zoo) and the conditions under which a mature engine should be reconsidered. Non-goals are part of the architecture, not a footnote.

Artifact B — Strangler fences in code

Real mode does not “prefer” real APIs — remaining mock usage throws. A ratchet script keeps mock imports from creeping back. Contract text freezes the surface area before implementations move.

By the numbers
  • · Live production client system — solo delivery
  • · Modular monolith · React + FastAPI · SQLite WAL
  • · Versioned JSON approval engine with frozen submit snapshots
  • · 85 workflow / form templates across staged complexity bands
  • · 100+ contract API surface · dual-layer RBAC with page permission guards
  • · 50 sprint directories of delivery record · 254 commits over ~6 months

Client identity stays at [Enterprise Client]. No project names, geographies, people, or UI screenshots.

The takeaway

Delivery you can audit — not just admire.

The transferable proof is not “we drew a workflow.” It’s an approval engine with explicit non-goals, a migration path that cannot silently stay on mocks, and acceptance discipline that corrects itself.

If you need a production operations platform — permissions, multi-step approvals, training, audit — built by one AI-native senior engineer end to end, this is that bar.