Clearing freight awards without hiding the risk
The Situation
Freight Capacity Auction Clearing Engine is a procurement decision system for freight brokers and shipper logistics teams that compares sealed carrier bids inside service, capacity, reserve, and approval rules. A team needs it when bid comparison has moved beyond a spreadsheet, yet the business still needs a human to own exceptions and final commitments.
The product accepts loads, lanes, carriers, policies, and bids, then records why each bid won, lost, or could not be used. Carrier users see only their own bid information. Operators get the wider decision record, including rejected bids, unassigned loads, policy constraints, and approval state.
This is a public specification build, not a client deployment. The repository contains no production users, freight spend, revenue recovery, or live traffic evidence. Its value claim is therefore narrow: the local release gate proves a controlled path from sealed bids to an approved, frozen export. It does not claim that a logistics team has already saved money with it.
That distinction matters. Optimization software can produce a cheap answer while leaving the buyer unable to explain the award, stop an unsafe export, or prove which policy was active. The build treats those controls as part of the product rather than administrative work after the calculation.
The Cost of Doing Nothing
No measured annual cost exists in the repository for spreadsheet comparison, email tendering, or award disputes. Publishing a salary estimate or savings figure would turn a design case into a fictional customer story.
The local release fixture uses two synthetic bids, one for $125 and one for $130. That $5 spread isn't a savings claim. It is the smallest case that exposes whether the system keeps an eligible lower bid separate from approval authority.
Financial exposure extends beyond choosing the higher bid. An unexplained award can create a carrier dispute. An exported proposal can become an operating commitment before anyone reviews the exception. A stale report can show a decision that no longer matches its approval record. Those risks are visible in the domain model, but their annual value depends on real auction volume, dispute history, and operator time. None of that evidence exists in this repository, so no annual ROI is claimed.
What I Built
I built a tenant-scoped auction service around four distinct authorities. PostgreSQL owns freight facts and state transitions. Redis carries bounded jobs, locks, and progress. The solver proposes a result and returns terminal evidence. An approval state machine decides whether a proposed award may be exported.
Imports enter staging before canonical tables. Column drift, invalid values, unknown references, and suspended carriers can quarantine a run. That prevents a malformed file from becoming a plausible auction. Once bidding closes, the worker builds a canonical input, records the configured solver and version, runs MiniZinc through a bounded child process, and stores hashes for the input and output. Awards, rejections, and unassigned loads are written together with that evidence.
The difficult part was deciding what counted as solver success. A process can exit with code 0 and still omit the final status the freight domain needs. The parser therefore requires one terminal record. Missing or repeated terminal evidence stops persistence. The worker does not swap in a second solver without saying so.
Approval creates another hard stop. Export reads only an approved snapshot, so a later policy, carrier, or auction edit cannot rewrite what the operator accepted. The Results section holds the measured response codes from the local lifecycle.
System Flow
Data Model
Architecture Layers
The Decision Log
| Decision | Alternative rejected | Why |
|---|---|---|
| Keep sealed bids tenant and carrier scoped | Show a shared comparison table | Competitor prices must not leak through carrier-facing views. |
| Require solver evidence before persistence | Treat a clean process exit as a valid award | Operating-system success says nothing about the completeness of the freight decision. |
| Store rejected and unassigned decisions | Save winners only | Operators need to explain exclusions and infeasible loads, not just the final award. |
| Block export until approval | Export proposals with a warning label | Files leave the application and can be mistaken for commitments. The boundary must hold before download. |
| Freeze each export | Rebuild reports from current auction rows | An approved record must keep the facts and explanation that existed at approval time. |
| Ship one production clearing mode | Pretend every schema mode is ready | single_round_spot has release evidence. Other modes remain explicit unsupported boundaries. |
Ecosystem Integration
The system has optional boundaries for a notification hub, a workflow engine, and a webhook ingestion engine. In this release, local event construction, outbox behavior, inbound webhook validation, and degraded health states have fixture evidence. Live outbound delivery to those services does not.
Each adapter is kept outside canonical auction authority. A failed notification cannot erase an award, and a workflow callback cannot create freight truth by itself. All three integrations are feature-flagged. The system runs standalone with no ecosystem dependency.
Results
The measured result is a local release proof dated 27 August 2026. One lifecycle submitted two sealed bids, persisted one award and one rejection, recorded solver input and output hashes, blocked the pre-approval export with HTTP 409, and returned a frozen export with HTTP 200 after approval. A separate import check read a real 432-row Parquet fixture. Browser accessibility checks covered 19 application routes, and the packaged Docker image passed its local health and lifecycle gate.
Those numbers establish control, not market adoption. There is no production throughput result, customer time saving, or freight-spend reduction to report. The public repository is the artifact, and the release gate is the evidence available today.
The next limit is measurement. The larger bid, load, and replay figures in the PRD remain targets. Before changing storage or adding worker replicas, I would measure queue contention, solver time, database pool pressure, and export latency against representative freight data. The current release proves that the decision can be stopped, inspected, approved, and replayed before it leaves the system.