Skip to content

Facts above, choices below

The physical worldScanDashboardHTTPpresentfactschoicesPOST /api/scan-codes/execute-choice

One lifelong code serves many intents: the station states what is true about the row and offers the actions that fit.

The situation

Some objects carry one code for their whole life, such as a bin tag. One code, many possible intents, and the right one depends on where the object is in its journey. The person at the station decides, but only after seeing the facts.

The recipe

A present step locates the row, renders up to 12 labeled facts against it, and returns a configured choice list.

rule 13:0 Bin tag
{
"query": { "roles": ["binning", "shipping"] },
"verb": "present",
"facts": [
{ "label": "Bin", "value": "{item.binCode}" },
{ "label": "Bags", "value": "{item.accumulate_count}" },
{ "label": "Ship by", "value": "{item.releaseAt}", "format": "date" }
],
"choices": [
{ "label": "Claim & start", "verb": "claim", "requireActingIdentity": true, "code": "CLAIM" },
{ "label": "Complete", "verb": "resolve", "requireActingIdentity": true,
"confirm": { "prompt": "Mark this bin complete?" },
"params": { "resolverPayload": { "outcome": "complete" } } },
{ "label": "View details", "verb": "show-detail" }
]
}

The scan answers choices with the row and the list. A choice whose identity requirement is unmet carries withheld: true. A choice’s code is a short printable token, so a person can scan the object, then scan an action card. A token the row cannot fill renders as a dash.

The guarantee

Picking a choice sends a pointer (scheme, category, step, choice, escalation id) to POST /api/scan-codes/execute-choice, and a pointer is never authority. The server re-reads live config, re-locates the row under the step’s query, re-applies the identity gate, and writes the exact row the screen presented, by id. A row that moved on between render and tap answers conflict. See Scan codes.