SYSTEM_MAP customer corpus, run 13 Sep 2026 · 68 EXAMPLE BOMS LOCAL · SINGLE_USER
Adesio · Intake

How Intake works

Every object, field, source and destination — one map. Intake is the client-facing front door to Adesio’s matching engine: it ingests messy BOM files, learns each format, resolves every line to an MPN or a structured generic, and hands one clean canonical BOM across a fixed contract. This page traces what flows through it, and exactly where the portal stops and the Adesio Stack begins.

Resolution coverage — customer corpus, run 13 Sep 2026
83.8%
of 6,230 sourceable lines can go straight to matching — 77.1% by manufacturer part number, 6.7% as a generic with a structured value and package. 16.2% need review here before they go on. 6,323 lines across 68 BOMs; 68 / 68 auto-recognised by a learned format.
A map, not the source of truth. The project docs are — this page is schematic. The figures above are one measured run on a date, not a live counter, and they move with every corpus pass.
01 · The pipeline

Extract → Transform → Load → [ match · enrich · risk · price ]

BOM import is the first step of a longer process already built in the Adesio Stack. The portal owns Extract + Transform + the Load contract; everything past the canonical handoff already exists downstream. The canonical schema is the boundary object between the two.

Input · client

Sources

Any messy BOM format, dropped or uploaded. A file that is not a bill of materials is refused rather than analysed. .ebom · .xlsx · .xls · .csv

Portal · Extract

Read

A reader per format turns the file into raw tables. New formats are new readers in front of the same pipeline. readBomFile → RawTable[]

Portal · Transform

Resolve

Encoding, column roles, two-track resolution, canonical manufacturer, generics, noise removal — with a confidence and a basis on every line.

The contract

Canonical BOM

One fixed schema. Any format in, one clean canonical BOM out; Adesio never sees a raw format. adesio.bom.canonical/v1

Portal → Adesio · Load

Hand off

Emit the project and its BOMs; each line becomes a bomLine, joined on IdTech. PLANNED

Adesio Stack · built

Core engine

Authoritative match, enrich, risk and price — then RFQ and PO off the project. This is where a line the portal could not resolve gets resolved.

The portal’s KPI is resolution coverage and a clean Load. The anti-goal is rebuilding a second matching, risk or pricing engine downstream.

02 · Sources

What comes in the door

Real customer formats, each with its own quirks. Encoding is decided first — over the whole buffer, never a sniff — before any structure is read.

.ebom

Cadence Allegro

Semicolon-delimited; the MPN sits inside DESCRIPTION at a different position per family. Per-family extraction took this fixture 68% → 88% → 94%. BUILT

.xlsx / .xls

Excel workbooks

Read via SheetJS. A multi-sheet workbook becomes one project with several BOMs; non-BOM tabs are skipped. BUILT

.csv

ERP nomenclatures

Multi-level French exports: MPNs packed as MANUFACTURER (MPN), decimal commas, and printed reports whose nested sub-tables are folded back into their parent line by a named reshaper. BUILT

PDF · ODS · IPC-2581 · ODB++

Further readers

A reader per format in front of the unchanged pipeline. Not built. PLANNED

The encoding ladder

Byte-order mark?EF BB BF · FF FE · FE FF
Strict UTF-8 decode?whole buffer, not a 64 KB sniff
cp1252 vs latin1the 0x80–0x9F range is the tell
Encoding + confidencesurfaced, with a re-decode override

Decode before structure. Windows-1252 is decoded without ICU, so Node 20 stops silently dropping the 0x80–0x9F bytes. .xlsx is zip/XML and skips the ladder entirely.

02b · Ways in

Four doors, one Intake

The product is Intake. A drop zone, a command line, an HTTP API and a Claude connector are four ways to reach it — not four products, and not a core with integrations bolted on. Whichever door a file comes through it meets the same readers, the same resolution, the same adesio.bom.canonical/v1 contract and the same rules about what may be claimed. And the same INSTALLATION: a format learned in the app is recognised by the connector, and a part an operator confirmed anywhere is already settled everywhere.

portal

The app

Drop a file, read the report, correct a column, confirm a part. The only door with a human in front of it — and the only one that can offer the correction and confirmation gestures. BUILT

portal

The CLI

bom-analyzer <file> writes the report, the canonical document, the CSV and the search worklist. Deliberately applies NO operator confirmations: a figure it prints is about what the tool reads, not about what somebody clicked. BUILT

portal

The HTTP API

The same routes the app uses, described in OpenAPI 3.1 and rendered from the table the server dispatches on — so the description cannot drift from the API. An instance serves its own schema at /api/schema. BUILT

portal

The Claude connector

MCP over stdio: analyse, page through what needs review, export the searches, record a decision — inside a conversation. Every listing is paginated, because a real BOM does not fit in a model’s context. BUILT

What is not built, and is the same gap for three of them: there is no authentication and one client. A multi-tenant API, a remote connector added on claude.ai with OAuth, job semantics for large files and webhooks all wait on one thing — an API key that resolves to a client id. The stores are already scoped by client; nothing else is. PLANNED

03 · Resolution

Two tracks — a line resolves as one or the other

Adesio matches downstream two ways, so a line is resolved if it carries either a confident MPN or a confident value + package. Only lines with neither are review items — and even those are not lost: they carry on into Adesio.

MPN line

payload = mpn + manufacturer

Has a real manufacturer part number. An MPN guessed from inside a description lands ambiguous with its candidate attached — never found. The manufacturer is resolved through the alias subsystem without ever overwriting what the file stated.

Generic line

payload = value + package

A chip R/C or inductor has no identity beyond its value and its package, extracted as a defined parse rather than a guess. A generic maps to a set of equivalents, not one part.

Generic parametric preview BUILT

Competitors turn a description into candidate MPNs. The portal already did the hard half — structured extraction — and now wires the second half as a preview: a generic’s value and package are matched against parts the portal has already resolved confidently, offline, with no external call. Measured on the customer corpus, run 13 Sep 2026: 181 of 417 generic lines (43.4%) came back with at least one candidate. A candidate is never authoritative — the line stays ambiguous and Adesio’s matcher is the authority after Load.

04 · The canonical object

One line of the canonical BOM

The contract between portal and Adesio: adesio.bom.canonical/v1. Named fields are always present and null when unknown, so the shape is stable. Some fields carry to Adesio’s Parts view by name; the rest describe how confidently each was extracted.

Field→ AdesioWhat it carries
Identity — the payload
mpnPartManufacturer part number, where the line has one.
manufacturerExactly what the file stated, never replaced.
manufacturer_canonicaljoin halfThe maker the stated spelling resolved to — half of the natural key.
internal_pnCPNClient / internal part number.
idtechjoin keySurrogate UUID of the shared part. Null until resolved downstream.
refdesReference designator(s) on the board.
lineThe source BOM’s own line number — traceability only, never matched on.
Generic track — required where there is no MPN
valuematch inputStructured electrical value, with its basis.
packagematch inputStructured package / footprint.
parametric_candidatesadvisoryThe preview set — ordered, tiered, never an override.
Status envelope — extraction basis, not a catalog match
mpn_statusbomLine statusfound · ambiguous · not_found · not_sourceable · placeholder.
mpn_status_basisenvelope flagSays this is what the FILE states, so nothing downstream reads it as a catalog confirmation.
mpn_sourceWhere the identity came from — a column, a description position, an alias.
resolutionmpn · matchable_generic · needs_review · not_sourceable.
review_reasonWhy a line is in review — and whether that is our gap or the file’s.
Context & passthrough
quantityReq. Qty.Quantity, decimal-comma tolerant.
descriptionDescriptionThe original line description, preserved.
custom_fieldspassthroughOperator-labelled columns — carried through, explicitly non-matching.
05 · Column roles

Reserved vocabulary vs. custom passthrough

Sourcing is driven by which map a column lands in, never by its label. Reserved roles are a fixed, closed vocabulary that maps to Adesio; a custom header is preserved but can never drive matching. The two maps never collide.

Reserved · columnRoles — drive matching
MPNPACKED_MPNMANUFACTURERINTERNAL_REF → CPNEXTERNAL_REFDESIGNATIONDESCRIPTIONQUANTITYQUANTITY_UNITSIDESUPPLIER_NAMESUPPLIER_REFLINE

A hierarchy-depth column (Level / Niveau) and a parent-assembly code (code père) are vetoed out of the identity roles: neither is a weaker identity, they are not identities at all.

Custom · customFields — passthrough
any labelProjetZoneNote atelier

An operator can name any other column. It is carried into canonical as labelled passthrough — preserved and saved into the format profile, but it never reaches the classifier, and a custom label may never collide with a reserved role name.

06 · The handshake

Why the portal never says “Found”

The portal reports what it extracted, and on what basis — it does not confirm a part against a catalog. It uses Adesio’s status words but limits itself to extraction-basis outcomes; Adesio’s matcher produces the one authoritative FOUND. IdTech is the join.

Portal emits

Basis-limited status

found here means the FILE states one unambiguous part number — never that a catalog confirmed it. The basis flag on every line says so.

The join

IdTech

A surrogate UUID for the shared part, which absorbs normalisation and merge churn. The portal resolves or creates it; Adesio reads by it.

Adesio produces

The authoritative match

Only the core matcher, after Load, turns a line into a confirmed catalog FOUND.

The worst error. A fabricated MPN is the worst thing this system can output. Placeholder junk like [NoParam] is filtered before it can be reported as confident or reach a shared tier, and a single uncertain candidate is ambiguous — never found.
07 · Data model

Three tiers, by sharing rule

The storage model is defined by what may be pooled across clients and what may not. A client’s BOMs and their part linkage never leave their boundary; how to read a format, and universal facts about a part, are shared — which is what makes the system get better with every file.

Tier 1 · private

Client data

Raw BOMs, the CPN → IdTech linkage, quantities, board side, reports and canonical outputs. Isolated per client, never pooled. Never committed to this repo — fixtures are synthetic and structure-only.

Tier 2 · pooled structure

Format profiles

How to read a format — headers, delimiter, column roles. No part data, so it is pooled: learned once, reused for every client using that exporter. The assumption is stated rather than assumed: a BOM’s column HEADERS are not treated as confidential.

Tier 3 · the facts, pooled

Shared parts catalog

Part number, manufacturer, family and the value+package it has been seen with. Universal — true whoever sent the file — so pooling them is the network effect: every BOM processed makes the next client’s generic line more resolvable.

Tier 1 · the provenance, private

Who bought what

The report, the FILENAME, the quantities, the dates. Never pooled, and the filename is why: BOM 40-00000001-001-F.CSV is a project code. Stored as a per-client ledger against the pooled facts, joined only for that client’s own view.

A bad row in a shared tier poisons every client, so a class-level change passes a confidence and provenance gate before any create or merge.

08 · Learning

Learn a format once, recognise it from then on

Format learning lives at the edge, so Adesio’s core only ever sees normalized data. Corrections feed the profile; nothing is ever silently self-applied.

Fingerprint

Recognise the format

The identity key is STRUCTURE only — headers, delimiter, column count, header row — and describes the file as it ARRIVES. 68 / 68 auto-recognised on the second pass of the corpus run.

Profile

Apply the mapping

Delimiter, column roles, refdes-prefix → family map, per-family description layout, and a named reshaper where a file is not one table. A recognised format brings its customer profile with it.

Confirm

An operator decides

A near match is never auto-applied: every override is by column index, and a near match has shifted columns. It is proposed instead.

Manufacturer aliases

One canonical maker

Many spellings resolve to one maker, keyed off the MPN rather than fuzzy name matching, against an 84k-row world-manufacturer reference. An inferred maker is badged and never overwrites the file.

09 · Downstream leverage

Feed and preview — don’t rebuild

Risk, alternates and sources already exist in the Adesio Stack. The portal’s leverage is upstream: hand them better inputs, and preview a lightweight version at intake. The authoritative numbers are always Adesio’s, after Load.

Layer 1

Risk & compliance

Feed a clean, canonical manufacturer to the existing risk engine — country-of-origin risk is only as good as that identity — and carry file-stated RoHS/SVHC through canonical. PLANNED

Layer 2

Alternates

The parametric candidate set is exactly this object; file-declared Équivalent columns feed the same surface. BUILT

Layer 3

Sources

A clean, resolved BOM is what makes availability, price and RFQ run well downstream. PLANNED

10 · Invariants

The rules that never bend

Never a fabricated or placeholder MPN. A fake MPN is the worst error; junk is filtered before it is ever reported or pooled.
Never overwrite an engine-stated MPN or manufacturer. An inferred value is additive and badged, never a replacement.
Never assert on an ambiguous line — no grade, risk, alternate, price or candidate is claimed as confident on one.
Never commit a real client BOM. Fixtures are synthetic and structure-only.
A shared-tier row is gated by confidence and provenance, because a bad row poisons every client.
The analyzer is deterministic and offline. No network in the analysis path; enrichment is a separate step behind an interface.
Green before commit: every change goes through a branch, a pull request and CI on Node 20 and 22.
11 · Where we are

From “runs on your Mac” to “clients use it”

Phase A · done

Analyse & resolve

Encoding detection, two-track resolution, the coverage headline, structure analytics, canonical export, and per-family MPN extraction from a fixed-layout description.

Phase B · in progress

Learn & persist

Fingerprint → format profile → auto-recognition, a JSON format store, the correction loop, the manufacturer alias subsystem, the Tier-3 catalog and the parametric preview.

Phase C · ahead

The real portal

Login, per-client isolation, hosting, object storage, encryption, the shared parts database — and the Load handoff to Adesio over an API. Deploy targets promote by tag. PLANNED

12 · The cycle, by scenario

Four ways a file travels the same nine steps

The map above says what the parts are. This says what HAPPENS, in order, and where four real scenarios diverge from each other. It is a process frise, not a calendar: the steps are in sequence, and nothing here is a duration. Only the cells that differ from the standard run are written out — a blank cell means that scenario does exactly what scenario A does, which is the point of laying them side by side.

ScenarioImportClientEncodingPortalFormatPortalResolutionPortalReportPortalLearningPortalCanonical BOMPortalLoadPortalAdesio downstreamAdesio
A · Standard BOMA known format, already learned. The path the portal is built to make ordinary.One file, dropped.Decided over the whole buffer, before any structure is read.Fingerprint matches a saved profile; its column roles are applied with no prompt.Each line resolves as an MPN or as a structured generic.Coverage headline, the six sections, and the lines still waiting on a human.Skipped — there is nothing new to learn about this format.One document, every named field present, null where unknown.Handed over the fixed contract.Match, enrich, risk, price — Adesio resolves what intake could not.
B · New formatNobody has seen this exporter before. The extra work happens once; the second file of this shape is scenario A.same as Asame as ANo fingerprint match. Column roles are decided from the content alone, and the report says so.same as AAn operator corrects a column; the file is re-read and the whole analysis re-runs.The corrected reading is saved as a named format, keyed on STRUCTURE — so the next file of this shape needs no prompt.same as Asame as Asame as A
C · Part listA client whose policy forbids exporting a full BOM. The same parts without the structure — inherently reverse-engineering-safe, and the natural fit for a zero-egress sovereign deployment.A flat list of part codes, with no reference designators and no placement.same as Asame as AUnchanged. The resolver never needed structure — most corpus fixtures state no board side anyway.Missing structure is EXPECTED, not a gap: coverage is computed on what a part list can carry, and nothing is docked for absent design fields.same as AThe design fields are null — not omitted. The shape stays identical.same as Asame as A
D · Multi-sheet workbookOne file, several boards. The unit that arrives is a project, not a BOM.One workbook, or a folder. Tabs that are not bills of materials are skipped.No encoding decision — a workbook is zip/XML and stores its text as UTF-8.same as Asame as Asame as Asame as AOne project carrying N BOMs, each one a document of its own.The project is the unit handed over, with its BOMs under it.same as A
Adesio · Intake — the client-facing BOM front door · contract adesio.bom.canonical/v1 · repo ades-io/bom-analyzer
A map, not the source of truth — the project docs are. Figures are schematic, and the corpus numbers are one measured run (customer corpus, run 13 Sep 2026), not a live counter.