The choices behind the PCB Validator spoke, the trade-offs I accepted, and what I deliberately left out. This is the short version of the architecture and the mockups.
The validator is not an editor and not a second source of truth. It interprets a package, runs profile-specific checks, and returns findings and priceable items. The customer fixes the design in their EDA tool and uploads a new revision. The spoke earns trust by being deterministic and traceable, not by hiding the work in the browser.
Decision. A browser-based viewer, a FastAPI spoke API, and an asynchronous Python validation worker.
Parsing and DFM rules need one authoritative implementation. If they run in the browser, results depend on the client, the device, and how much geometry it can hold in memory. The server keeps that deterministic, and the worker isolates the slow, stateful part so the API can still serve order context and progress. The browser only renders normalized geometry, which keeps layer toggling and finding focus immediate.
Decision. Parse Gerber and Excellon, normalize geometry, run profile-specific DFM checks, and return findings.
Gerber and Excellon are terse and stateful. A wrong aperture, polarity, or drill unit changes the geometry silently, so there has to be one parser and one normalized representation in board units. Rules then evaluate that geometry against the manufacturing profile assigned to the order, not against a permissive default. A finding carries the rule id, measured value, required threshold, unit, layer, and a geometry reference.
Decision. Trace owns orders, original files, identity, assigned manufacturing profiles, and checkout. The spoke owns validation runs, findings, rules, and derived artifacts.
Original files and the money path stay in the hub. Interpretation and engineering truth stay in the spoke. Findings are authored by the spoke but scoped to the order, so checkout can block on them. The worker fetches files with its own authorized Hub API access; it does not download through the API and it does not talk to Postgres. It reports metadata and findings to the API, and the API persists run state.
Decision. Customers fix designs in their EDA software, upload a new revision, and rerun validation. Acknowledgement is not resolution.
A validator that can edit geometry becomes a second source of truth and a much larger product. The honest loop is: understand the constraint, change the board in the tool that owns the design, upload a revision, and let a new run prove the fix. Acknowledgement, will address, and request manufacturing review are tracking states. A finding closes only when a later run confirms the geometry is gone.
Decision. Revision-scoped validation runs, persisted state and findings, and object storage for larger derived artifacts.
Every revision is immutable and identified by a content hash. Every run records the revision hash, parser versions, ruleset version, profile snapshot, worker image, timestamps, and outcome. Findings link back to the run, the rule, and the geometry. A re-run creates a new run, never an in-place edit, so "why did this pass last week" stays answerable. Postgres holds run state and findings; object storage holds normalized geometry and larger artifacts, and the API reads it when serving the browser.
Decision. Ship the core loop: the supported file formats, layer viewing, a focused set of DFM checks, findings, and order-item handoff.
The MVP is one package shape (RS-274X Gerber plus Excellon), initial support for a defined four-layer board configuration, explicit layer mapping, normalized geometry, a board viewer, a small rule set, revision upload and revalidation, findings, and priceable items posted back to Trace. The checks I would start with are clearance, annular ring, drill aspect ratio, soldermask sliver, and copper to board edge. That is enough to prove the loop and enough to be wrong in useful ways.
Design exercise for Alpha Machines. The mockups and architecture diagram are linked from the overview.