Skip to content

A scan is a rule

The physical worldScanHTTPMCPscanSchemesPOST /api/scan-codes/executeexecute_scan_codeupsert_scan_rule

A code runs an ordered list of queue queries and the first match acts, so one scan both moves the item and reports where it is.

The situation

A carton reaches a bench carrying one printed code. What the scan should do depends on where the carton’s row sits right now: waiting to be collected, already collected, or in some other queue. The associate should not have to know which.

The recipe

A scan code reads version:category:target. The version picks the scheme, the category picks the rule, and the rule is an ordered list of steps over the escalation queue: event, condition, action.

start.ts
scanSchemes: [{
version: 10,
name: 'Carton serial',
target_facet: 'serialNumber',
rules: [{
category: '1',
name: 'Collect',
steps: [
{ query: { roles: ['packing'], status: 'pending', availability: 'available',
facets: { state: 'packed' } },
verb: 'resolve',
params: { resolverPayload: { outcome: 'collected' } } },
{ query: { roles: ['packing', 'shipping'] }, verb: 'show-detail' },
],
fallback: { markdown: '**No row for this serial.** Register the carton first.' },
}],
}],

Scanning 10:1:SN-123 walks the steps. The first step whose query matches runs its verb. Put the expected state first and a broad show-detail last: a carton in the wrong queue still answers the scan with where its row actually is. With no match, the station shows the fallback.

The same code runs from a keyboard-wedge scanner, the dashboard header bar, POST /api/scan-codes/execute with { "code": "10:1:SN-123" }, or the execute_scan_code MCP tool.

The guarantee

Claim, resolve and cancel steps ride single-statement by-metadata operations, with the caller’s role scope folded into the same SQL filter. Two people scanning the same code at once produce exactly one transition: the second scan reports conflict or falls through to the locator step. Every terminal state is a structured 200 outcome (executed, no_match_fallback, conflict, and so on). See Scan codes.