Resources & Tech · Phlebotomy Solution

One funnel, one mapper, and a database that arbitrates the race.

Mobile phlebotomy runs on unreliable inputs and unreliable connections: a faxed requisition photographed in a hallway, two dispatchers looking at the same board, a phlebotomist collecting a specimen in a building with no signal. The engineering worth reading here is about those conditions — one normalized order shape that every intake path converges on, a compare-and-set assignment that lets the database settle a race, and an offline queue whose replays are provably harmless.

Overview

The engineering record behind referral intake, dispatch, the offline field app and chain of custody.

Technology stack by layer
LayerWhat runs thereWhy
APINode.js 22, Express 4, TypeScript in ESM, assembled router-per-domainA conventional, boring stack for a system whose difficulty lives in its state machines rather than its framework.
Front endNext.js 14 App Router, React 18, TypeScript, TailwindRoute groups per area, with the field application scoped to its own path so it can be installed independently.
DatabaseMySQL 8 with Prisma 6 — schema-first models, typed client, twenty-two dated migrationsSeveral migrations exist specifically to add unique indexes that turn a class of duplicate-generation bug into a database-level impossibility.
CacheRedis 7, optional, with a bounded linear reconnect backoffThe backoff replaced a strategy that told the client to stop reconnecting permanently after a single blip — which left the readiness endpoint reporting Redis down forever.
AuthA signed session token in an httpOnly cookie; bcrypt password hashing; role checks per routeSeven roles, from admin through intake and dispatch to field, facility and laboratory. The token carries identity and role only — scope is resolved server-side per request.
Partner authSHA-256-hashed API keys with a recognisable prefix, matched by hashShown to the caller once at creation and stored only as a hash. Only organizations registered as inbound-capable can use one.
Offline field appAn installable progressive web app with a hand-written service worker and a local action queueNetwork-first for navigation, cache-first for static assets, an offline fallback page, and a queue that replays writes idempotently when connectivity returns.
Document extractionAnthropic Claude with a forced tool call against a schema mirrored from the validatorThe model cannot return free-form prose; it must fill a typed structure. Model and key are both required, and without them the feature reports itself unavailable rather than degrading silently.
ValidationZod on request bodies, on the extraction schema, and on CSV import rowsOne validation library across three very different input surfaces means one place to reason about what a valid order looks like.
MessagingSMS for tech assignment and a chat integration for operations alerts, both optionalPhone numbers are masked in logs and patient identity in any outbound message is initials only.
Testing and CIType checks and a mocked-database unit suite, plus an end-to-end job that boots real database and cache containers and seeds themThe end-to-end job runs the funnel, role-based access and scope specifications against a genuinely running server rather than a mock.
Architecture

How the engine actually works

Each section describes a mechanism that exists in the codebase today, not a pattern we admire.

The spine

One funnel, one adjacency table

Every order is one record moving through a single canonical status sequence — intake, pending dispatch, assigned, accepted, collected, completed — with explicit leakage branches for service hold, cancelled, past date-of-service and rejected.

Intake

Three producers, one mapper

Two very different intake paths converge on the same normalized shape. Staff-side extraction posts a scanned requisition — image, PDF or pasted text — to a model call forced into a typed tool schema. The model is explicitly instructed that one uploaded document may contain several patients' requisitions, a facility's daily batch, and must return one entry per distinct patient without merging or splitting them.

Concurrency

Letting the database settle the race

Assignment is the single core used by both manual dispatch and auto-routing, and it layers five checks before writing: region scope on the acting dispatcher, region scope on the assignee relative to the order's region — a check the comments record as previously missing — an active-technician guard, a terminal-status guard so a collected or completed order can never be reassigned, and finally the concurrency guard.

The field day

An offline queue that cannot double-write

Every field write — accept, reject, collect, mileage, clock in and out — accepts an optional client-supplied action id. Two distinct races are closed by it. The first is a replay arriving after the original committed: the existing row is found by that id and returned as success rather than duplicated. The second is a genuine concurrent retry: both requests find nothing on the pre-check, both attempt to create, and the loser hits a unique-index violation.

Scheduling

A model that changed meaning, documented in place

This is a two-model split that changed meaning mid-project, and the schema says so. A standing order was originally a recurring visit generator. A client decision redefined it as a recurring order document — something to reprint on a cadence — and the schema comment states plainly that it must never create or change orders, schedules or dispatch.

Custody

The audit report reads the log, not the status

Chain of custody is an append-only per-order event log written at every funnel-relevant action — assignment, accept, reject, collect — carrying the event, the actor, a timestamp, free-text notes and a detail field used for specimen information on collection rows. It uses the same action-id idempotency as the mileage log.

Master data

Two names for a facility, on purpose

Reference data — services, tubes, insurers, diagnosis codes, laboratories, physicians and facilities — is managed through one router with a consistent list-and-filter shape. Nothing is hard-deleted, because everything is referenced by orders and standing arrangements; a record is retired by deactivating it.

Time

A dedicated module for the day boundary

There is one module whose entire job is the difference between the server's clock and a field technician's day. The API runs in UTC; technicians and business-day boundaries are Pacific.

Data model

The records underneath, and the rules that hold them true

Core entities and their invariants
EntityWhat it holdsRule that always holds
ReferralThe core order and visit record — the funnel unit, carrying status, scheduling links, source organization, billing block and the requisition image.A unique constraint on standing-order and service date prevents the same recurring visit being generated twice for one date.
RoutineContractThe current recurring engine: a facility-level standing shift arrangement with cadence, shift, volume range and pre-assigned technicians.Generates visit blocks, never orders directly.
VisitBlockA facility batch draw request for one date — the unit the scheduling board operates on, with its own delivery state.Unique per contract and date. Ad-hoc blocks with no contract are exempt, because the database permits repeated nulls in a unique index.
StandingOrderA recurring order document to reprint on a cadence.Explicitly must never create or change orders, schedules or dispatch — a redefinition recorded in the schema itself.
RequisitionScanA photographed paper requisition awaiting staff review, storing both the image and the raw extraction output.The raw model output is kept alongside the staff-edited result, so the two can be compared later.
ChainOfCustodyAppend-only per-order event log — the source of truth for the laboratory audit report.Never updated, only inserted. Carries a unique client action id for offline replay safety.
MileageLogMileage entries logged by a phlebotomist across a working day, alongside an auto-estimated leg distance.Same client-action-id idempotency as the custody log.
StatRecollectRequestAn urgent redraw request raised by a laboratory or facility.A communication artifact only — it never auto-creates a schedule or a dispatch on its own.
OrganizationA partner entity for inbound orders or outbound results, with a declared direction and channel format.API-key authentication only admits organizations registered as inbound-capable; result posting is restricted to laboratory and record-system types.
TestResultA minimal record that a result was received against an order.No discrete analyte values are stored here by design — those live in the laboratory system.
AuditLogAppend-only cross-cutting trail for exports, imports, integration events and funnel transitions.Write failures are swallowed rather than propagated — a failed audit write must never break the request it was recording.
FacilityA referring or receiving site, with coordinates for mileage estimation and a preferred laboratory.Two distinct names: an internal region-coded one, and a billing name that is the only one ever exposed to a laboratory.
Interfaces

What it exchanges, and in which direction

Optional integrations degrade gracefully: with no key configured the product still runs, it just does less.

Partner inbound orders

Inbound

A REST endpoint authenticated by hashed API key, body-validated, resolving the calling organization and running the same mapping function every other intake path uses. Writes an audit row and fires a PHI-safe operations notification carrying initials only.

Outbound requisition intent

Outbound

Resolves the destination laboratory, records which channel format it is registered under, and stamps the moment the requisition left — so the outbound side of an order has the same evidentiary trail as the inbound side.

Inbound results

Inbound

Narrow by design: only organizations registered as a laboratory or a record system may post results, so an order-only partner cannot write results onto someone else's order.

CSV import and export

Bidirectional

A fixed column order shared by both directions, built on the same order-mapping core, with a dry-run mode and its own validation tests.

Document extraction

Inbound

Vision extraction into a typed schema with per-field confidence, handling multi-patient batch documents and face-sheet billing fields.

SMS

Outbound

Assignment notifications to technicians. Optional, a graceful no-op without credentials, numbers masked in logs and patient identity reduced to initials.

Operations chat

Outbound

Webhook alerts and a chat integration for staff coordination, PHI-safe by convention — initials, identifiers and categorical fields only.

Security

How access is decided and recorded

Live revocation on every request
The active flag on the user is re-read from the database on each request, not just at login, so a still-valid token for a deactivated account is rejected immediately. The comment frames this as an offboarding requirement.
Scope resolved server-side
The session token carries identity and role only. The effective region filter is computed per request: a pinned user is forced to their own region regardless of what they ask for.
Deny by omission, not allow by omission
An unpinned role with no assigned location resolves to a sentinel that matches nothing, rather than to everything. That closes an entire class of information-leak-by-omission bug.
Default-deny route gate
The front-end gate was flipped from an allow-list of protected paths to default-deny after a QA finding that many real routes fell outside the old list and served an unauthenticated shell. No data reached those pages — the API still refused — but the gate was doing almost nothing.
Cross-region denial
An out-of-region record returns 404 rather than 403, so a caller cannot confirm that it exists.
PHI-safe logging
One structured line per request — method, path with the query string stripped because a search parameter can carry a patient name, status, duration and request id. Bodies, headers, cookies and query parameters are never logged.
PHI-safe errors
Unexpected errors are logged server-side and the client receives a generic message. Database error text is never echoed, since it can leak schema, SQL and file paths; known constraint codes map to clean client errors with the column names withheld.
Strict origin and proxy trust
A single exact allowed origin, required at boot — replacing an earlier reflect-any-origin fallback. Proxy trust is an exact hop count rather than a blanket setting, so a spoofed forwarding header cannot bypass rate limiting.
Offline data on devices
The field queue and cached route data live in browser local storage. Pending write payloads persist on the device until flushed, and there is no client-side encryption-at-rest layer for that queue — stated here because it is a real property of an offline-first design.
Compliance posture
Designed for HIPAA obligations under a BAA. No certification is claimed.

Infrastructure is designed for HIPAA obligations under a BAA. We document the controls and hand over the runbooks; we do not claim a certification that does not exist for software.

Reliability

What keeps it correct under load

Compare-and-set assignment
The expected prior assignee goes inside the update's where-clause, and a zero-row result becomes an explicit conflict. The database arbitrates, not the application.
Client action ids
A unique column on custody and mileage rows, with both a pre-check and post-hoc recognition of the unique-violation race, so an offline replay resolves to the original result.
Conflict, never server error
Illegal transitions and lost races answer with a client-error conflict deliberately, because the offline queue retries server errors — a correct status code is a reliability mechanism here, not a nicety.
Unique indexes over application checks
Generation dedup is enforced at the database, added after a live incident where two overlapping generation runs both read an empty set and both inserted, doubling every date.
Network failure versus rejection
The offline queue distinguishes the two: a rejected action is dropped so it cannot wedge the queue, while a network failure keeps retrying.
Liveness separate from readiness
One endpoint never touches a dependency check that could crash the response; the other genuinely queries the database and cache and holds traffic back until both are healthy.
Timezone at the boundary
The business-day module probes the offset at the day boundary rather than at the current moment — the difference only shows up on daylight-saving days and late afternoons, which is when it matters.
Bounded reconnect
The cache client backs off linearly to a cap and keeps trying, replacing a strategy that gave up permanently after one blip and left readiness reporting a permanent failure.
Development record

The documents this was built from

Analysis, design discussion, implementation notes and QA written while the work happened. These are engineering artifacts in the product repository, not published pages — listed here so you can see what exists and ask for any of it.

Development-time documentation for Phlebotomy Solution
DocumentKindDateWhat it covers
Service blueprintdocs/service-blueprint.mdDesignThe service-operations design: roles, the referral lifecycle end to end, visit types, and the definitions of service hold and every leakage state.
Delivery plandocs/delivery-plan.mdPlanThe engineering companion to the blueprint, phasing the build and mapping each phase to the delivery method.
Legacy system investigationdocs/legacy-investigation.mdAnalysis2026-06-18Findings from a walkthrough of the predecessor system, recording aggregate structure and counts only, with no patient data extracted — the method is stated in the document itself.
Next-generation design specificationdocs/superpowers/specs/2026-06-18-socal-mms-nextgen-design.mdDesign2026-06-18The foundational design derived from the legacy investigation — domain model, funnel, roles and the boundaries the build was scoped against.
Interoperability design referencedocs/interoperability.mdReferenceThe full channel matrix and field-mapping tables for every integration format in scope — the reference an additional channel is built against rather than designed from scratch.
Extraction schema specificationdocs/planning/referral-intake-extraction-schema.mdDesignField groups, vendor requisition templates, confidence routing thresholds, and how each extracted field maps into the order model.
Master QA plandocs/QA-PLAN.mdQA2026-07-13A nine-phase test plan running from cheap-and-broad to deep-and-narrow, with coverage matrices per phase.
Ten-phase QA sweep resultsdocs/reports/2026-07-13-qa-phase0..phase9/RESULTS.mdQA2026-07-13One results document per phase — environment, smoke, per-module function, integration, role-based access and negative cases, data integrity and legacy parity, security and privacy, performance, offline and responsive behaviour, and acceptance sign-off.
Security and performance rounddocs/reports/2026-07-15-security-perf/QA2026-07-15An authorization-focused round with its own findings document, recording each issue as fixed and independently verified.
Untested-surface rounddocs/reports/2026-07-18-untested-surface/QA2026-07-18A round explicitly framed as what twenty previous rounds never touched, targeting the scheduling block surface and producing its own remediation branch.
Attack-axis QA rounddocs/reports/2026-07-20-qa-gaps/QA2026-07-20The round whose findings are cited directly in the state-machine and idempotency modules' code comments — the clearest example in this repository of QA output becoming code.
Correctness-axis QA rounddocs/reports/2026-07-21-qa-correctness/QA2026-07-21A round deliberately testing along a correct-versus-incorrect axis rather than a reachable-versus-unreachable one — a different question from every prior round.
Client change specifications and before-and-after reportsdocs/planning/client-change-*.{md,html} · docs/planning/edits-06*/ · docs/reports/2026-07-*/Report2026-06-25 to 2026-07-21Dated request-to-delivery records for each change set, several in before-and-after form with screenshots, including the completed-status reversal that the end-to-end suite now covers.
Prototype setdocs/planning/*.htmlDesignSelf-contained interactive prototypes produced before implementation — dispatch console, field application, phlebotomist route and schedule, intake, reports, interoperability and the patient view — plus a role-capability matrix and acceptance-test scenarios.
Analytics researchdocs/analytics-research.mdAnalysis2026-06-18A four-dimension model for funnel, engagement, experimentation and interface auditing, designed to be privacy-safe from the outset — the research backing for how reporting is scoped.
Legacy data migration pipelinemigration/{extract,extract_referrals,load}.jsMigrationA three-step extraction and load pipeline from the predecessor system. Every script's header states that counts only are logged and never field values, and the loader documents itself as a deliberate destructive replace rather than an additive merge.
Methodology and harnessdocs/methodology.md · HARNESS.mdReferenceHow the work is actually produced — the phase loop, and the planner, generator and evaluator pipeline used to build interactive prototypes before writing implementation code.
Glossary

Terms used on this page

Referral
The core order and visit record — the unit that moves through the funnel.
Funnel
The canonical order lifecycle from intake through dispatch, acceptance and collection to completion, with defined leakage states.
Leakage state
A branch out of the happy path — service hold, cancelled, past date of service, rejected — tracked rather than deleted.
Routine contract
A facility-level recurring shift arrangement that generates visit blocks.
Visit block
A scheduled facility batch draw request for one date — the unit the scheduling board operates on.
Standing order
A recurring order document to reprint on a cadence. Deliberately not a visit generator any more.
Chain of custody
The append-only per-order event log, and the source the laboratory audit report is built from.
Date of service
The scheduled or actual draw date, distinct from the date the order was written.
Requisition scan
A paper requisition photographed on site, model-pre-filled, awaiting staff review before it becomes a real order.
Urgent redraw request
A communication-only artifact raised by a laboratory or facility; it never creates a schedule on its own.
Sample delivery
The per-specimen tracking state from pending through waiting and picked up to delivered.
Client action id
The idempotency key an offline field write carries, so a replay resolves to its original result rather than duplicating it.
Compare and set
Putting the expected prior value inside the update's where-clause so the database, not the application, settles a race.
Billing name
The only facility name ever shown to a laboratory, deliberately distinct from the internal region-coded name.
Region scope
The access model — pinned to one region, cross-region for admin roles, or scoped to nothing for an unassigned role.
Pacific business day
The field day boundary, computed from local time rather than server midnight.
Normalized order model
The single internal shape every intake path converges on before an order is created.
Progressive web app
A web application installable to a device home screen, able to run and queue work without a connection.
Questions

Asked by the people who evaluate this

Why does the offline field app matter so much here?

Because specimens get collected in basements, care-home corridors and buildings with no signal, and the collection has to be recorded at the moment it happens. Anything that requires connectivity at that instant produces either a lost record or a technician re-entering data from memory later. Both are worse than a queue.

How do you know a replayed offline write cannot create a duplicate?

Two independent mechanisms. The write carries a client-supplied action id, and there is a unique index on that column. The pre-check catches the ordinary replay; the unique violation catches the genuine concurrent one, and the code recognises that specific violation and resolves it to the existing row. Relying on the pre-check alone would look correct in testing and fail under a real retry storm.

Two dispatchers assign the same order at the same moment. What happens?

One wins and one gets a conflict telling them to reload. The losing write never lands, because the expected assignee is inside the update's where-clause and the affected row count comes back zero. The notification to the technician fires only for the winner, so nobody gets a message about an assignment that was immediately overwritten.

Is the AI reading requisitions trusted?

No, and the design says so at three levels. It is forced into a typed schema rather than free text. Every field carries a confidence score so the review interface can flag the weak ones. And nothing becomes a real patient or order until a person confirms it. The raw model output is also kept alongside the staff-edited version, so the two can be compared afterwards.

How do orders and results move between us and a partner?

Over REST with a hashed API key, in both directions, plus CSV import and export on a fixed column order. Every one of those paths — plus staff-side extraction — converges on the same normalized order shape before anything is created, so a partner integration cannot produce a record the rest of the system treats differently. Other channel formats are scoped per engagement against the field-mapping reference the repository already carries.

What does the QA history tell you about this codebase?

More than the test count does. Several state machines exist because a QA round found a state resurrecting itself or an orphaned record, and the modules cite those findings by name in their comments. That is the loop worth looking for: a round that finds a class of bug, and a structural change that makes the class impossible rather than a patch that fixes the instance.