Scan to Item
Item intake turns a scanned barcode, product URL, typed description, or Arda
card QR into a reviewable Item. Enrichment builds the product draft and buying
options; blank-card binding attaches a QR to an Item. Enrichment runs as
in-process modules inside the arda-frontend-app BFF, behind
POST /api/enrichment/import, the single front door that wraps Amazon
server-side. This document covers the working flow and the remaining
decisions.
| Status | Prototype under evaluation |
| Production runtime | arda-frontend-app BFF — POST /api/enrichment/import |
| Enrichment engine | In-process modules in the BFF, src/server/lib/enrichment/, with the ported engine under src/server/lib/enrichment/engine/ |
| User entry point | Scanner and quick item form in arda-frontend-app |
| Write path | Existing Item and ItemSupply flow |
Requirements
Section titled “Requirements”The first production version should:
- accept a product barcode from the camera scanner, and accept a URL or plain text when the user starts enrichment from a form;
- reach Amazon only through server-side delegation to the Amazon BFF routes
(
/api/amazon/importfor a URL or ASIN,/api/amazon/searchfor keyword text merged with web discovery), never as a client-selectable provider; - return a reviewable draft with product details, offers, images, confidence, and field-level evidence;
- use exact identifier sources for identity and web search for supporting product or supplier information;
- keep Arda card QR codes in the card and blank-card binding flows;
- continue when an individual provider fails or times out;
- keep provider credentials out of the browser and response body;
- scope every run and tenant-owned source to the authenticated tenant; and
- leave Item and ItemSupply creation in the existing save flow; and
- return a single reviewable draft that already folds in optional offers and packaging suggestions where available, without ever overwriting a field the user has edited.
The input contract also needs room for new acquisition adapters. An image or document can be uploaded separately and referenced by an enrichment call, then an OCR adapter can turn it into text and identifier candidates. Those candidates can use the same provider and reconciliation pipeline as a typed description or scanned barcode.
For V1, a missing or uncertain result is better than a confident false match.
The UI keeps needs_review results editable and asks the user to confirm them
before saving.
Evaluation targets
Section titled “Evaluation targets”These are prototype gates rather than contractual SLOs.
| Measure | Target |
|---|---|
| Confidently wrong identities | Zero in the evaluation set |
Precision among matched results | At least 90% |
| Useful coverage across the mixed item set | At least 70% |
| First authoritative result | p95 below 2 seconds |
| Completed enrichment call | Barcode scans at or below 5 seconds; URL and text lookups at or below 10 (enforced budgets) |
| Provider resilience | One failed provider does not prevent a usable result from another |
| Credential safety | No credential appears in a result or source trace |
Non-goals for V1
Section titled “Non-goals for V1”- Enrichment does not create or update an Arda item.
- Tenant catalogs, accepted-result memory, and durable result caching are not required for the first live flow.
- Package conversions are not inferred without explicit unit and quantity data.
System design
Section titled “System design”The component view below shows a scan moving through the in-process enrichment modules inside the BFF, while accepted item data continues through the existing Operations write path.
The frontend calls POST /api/enrichment/import, a same-origin BFF route, so
provider credentials never reach the browser. The route runs exact identity
sources in parallel, reconciles their responses, and then uses the resolved
product to search for supplier and product pages. It returns a suggestion; the
user reviews it and saves through the existing item flow.
Scanning an Arda card QR does not start product enrichment. That scan continues through the existing card lookup or blank-card binding flow, which prevents a card identifier from being mistaken for a product barcode.
Main design decisions
Section titled “Main design decisions”Separate identity from discovery
Section titled “Separate identity from discovery”Barcode Lookup is the primary identity source for a scan; UPCitemdb and Open
Food Facts add catalog coverage. Exa contributes supporting search evidence
rather than deciding exact identity by itself. Amazon is not an engine adapter:
the BFF reaches it directly — an Amazon URL or ASIN delegates to
/api/amazon/import for exact lookup, and freeform text fans out to
/api/amazon/search alongside Exa discovery, merged by the reconciler.
After identity resolves, an optional small-model adapter suggests unit type, units per package, minimum order, and order increment. Those fields keep their own evidence and remain suggestions in the form.
Return evidence with the draft
Section titled “Return evidence with the draft”The response keeps the provider, authority, and cache policy for each selected
or competing field. Offers stay separate from product identity and are marked
exact, equivalent, or related. This gives the UI enough information to
show uncertainty instead of flattening every provider response into one opaque
answer.
Keep writes in the existing flow
Section titled “Keep writes in the existing flow”Enrichment prepares form values but does not own Arda item state. This keeps validation, authorization, audit history, and ItemSupply creation in the existing Operations path.
One synchronous call
Section titled “One synchronous call”The frontend calls POST /api/enrichment/import once per scan and waits for
the response. There is no run resource, no polling, and no Prefer header —
the route runs every adapter and returns the reconciled draft. The frontend
can still show its own loading state while the request is in flight; that is
UI-only, not a second round trip to the BFF.
Current prototype
Section titled “Current prototype”The working local demo uses the in-process engine in the arda-frontend-app
BFF, plus the frontend scanner and quick item form.
The automated live corpus has nine cases: two barcode matches, a negative
short-code case, and six supplier-URL cases. Unit tests cover the reconciler
and normalization in depth (source precedence, corroboration, confidence,
package mismatches, image selection), the orchestrator’s budget deadline, Exa
search targeting and acceptance, OpenAI packaging output limits, supplier
catalog matching, and model extraction; the import route covers auth,
validation, success, and error mapping; and the QR resolve/bind mocks have
their own suite. Live provider behavior end to end is exercised by the corpus
(npm run eval:live). A local run has also exercised the OpenAI adapter
against the real API; that is not yet a
representative model evaluation.
The next evaluation step is a set of 30–50 physical items from real Arda environments, with ground truth recorded before enrichment runs. Promotion beyond an internal pilot should require the precision, coverage, latency, and credential-safety gates above.
Design documents
Section titled “Design documents”- Frontend and UX describes scan routing, loading and review states, form mapping, mobile and desktop behavior, and production UX work.
- Backend service describes the import contract, provider pipeline, reconciliation, ranking constants, tenancy, persistence, observability, and endpoint alternatives.
- Adapters and source authority describes how to author a new adapter and how identity, discovery, and tenant sources are ranked.
- Evaluation and acceptance describes the physical-item test plan and the gates a pilot needs to clear.
- Bind a QR to an Item is the short version of the blank Card flow and the backend work it still needs.
Open decisions
Section titled “Open decisions”- For freeform text, does merging
/api/amazon/searchwith the engine’s Exa-search behind one enrichment front door justify enrichment depending on the Amazon route being up, versus keeping/api/amazon/importand/api/enrichment/importas composable routes and routing client-side? - Should reusable enrichment contain provider output, user-approved results, or both?
- How should tenant and supplier catalogs be ingested, updated, and owned?
- The OpenAI packaging model already runs on every scan wherever
OPENAI_API_KEYis set. Should production keep that default or require an explicit opt-in? What acceptance and edit rates would justify default-on?
- Enrichment engine — in-process modules in the BFF,
src/server/lib/enrichment/, with the ported engine undersrc/server/lib/enrichment/engine/ - Frontend application
Both live on
feature/pdev-1161-scan-to-item.
Copyright: © Arda Systems 2025-2026, All rights reserved