Skip to content

Role is the wall, facets are capability

The queue as a marketHTTPSDKCLIMCProlemetadatasearchByFacetsclaimByFacets

The role decides who can ever see a row. Metadata facets decide which consumer inside that role can take it.

The situation

Machining work is visible only to the machining team. Inside that team, some cells cut aluminum and some cut steel, and some take oversize parts. Routing needs both a hard boundary and soft preferences.

The recipe

workflows/machine-part.ts
const done = await conditional<{ ok: boolean }>(`machine-${serialNumber}`, {
role: 'machining',
priority: 2,
metadata: { serialNumber, material: 'aluminum', sizeClass: 'standard', mustCompleteBy: deadlineMs },
});
services/cell-7.ts
const { data } = await lt.escalations.searchByFacets({
role: 'machining',
status: 'pending',
available: true,
facets: { material: 'aluminum' },
block: [{ sizeClass: 'oversize' }],
orderBy: [{ field: 'metadata.mustCompleteBy', numeric: true, direction: 'asc' }],
limit: 10,
});
Concern Expressed as
Capability, hard role
Capability, soft facets containment, block exclusions
Preference orderBy over columns and metadata.<key>
Capacity the limit of a claim

The guarantee

A consumer bound to one role can never see another role’s rows; a role it does not hold matches nothing. Facets are GIN-served containment, and every value is a bound parameter. Only validated keys and a fixed operator set are interpolated. See Faceted routing.