One thesis: object → performer is the product; performer → objects is refused. The two are the same join read in opposite directions, and a work door that answers one must refuse the other at the point where a query is built, not at the point where a report is styled. That refusal is not a missing feature. It is what makes the first question answerable at all.
The two directions
Start from a bag of lettuce. A lot is under recall, and the question is: who touched this pallet, at which dock, inside which window? That is object → performer. It is the question an auditor, a customer and a chargeback panel ask, and a ledger of attested events with a task above each one answers it exactly — a real who, at a real place, inside the window.
Now start from a person. What has this receiver done this week? That is performer → objects. It is the same tables, the same join key, one WHERE clause moved from the object to the person. And it is refused.
object → performer "who touched this pallet?" PERMITTED — it is the product
performer → objects "what has this person done?" REFUSED
Why the second one cannot be allowed
Because the attested who is what makes the first question answerable, and the attested who is only present when performers have a reason to let it be. Identity on this door is regime-scoped. Where a regulation requires the performer be identified — 21 CFR Part 11, OSHA 1910.178(l), FAA 14 CFR 43.9, HACCP monitoring — who-completeness is a compliance metric and it is legitimate. Where nobody requires it, it is not sold. A scope with no cited authority does not get the metric.
The moment a door will answer what has this person done, every performer on it has a reason to make sure the answer is flattering, and the cheapest way to do that is to stop scanning honestly. The per-person report poisons the ledger it is drawn from. Refusing it is how the ledger stays worth reading.
Where the refusal lives
A rule that lives in the rendering layer is a rule somebody regresses by adding a column. So this one is enforced where queries are constructed, at the four places a person-key can hide — the same four the console's metric gate reads:
- The grain. A query whose row grain is a performer is refused.
- The group-by. A query that groups by a performer, role, team, department, crew, approver or warrantor is refused.
- The parameters — names and values. The leak arrives as a reasonable-looking filter: ?performer=... is obvious; a person hiding in a param value is not, and the package's test suite carries a poison fixture for exactly that.
- The rendered keys. A face that would print a person as a column is refused before it renders.
src/refusal/person-dimension.json in the package copies the console's token artifact byte-for-byte and adds this door's own terms, each with its reason. A test fails if the copied half ever drifts.
What is permitted, and checked to be permitted
Rendering an assignee or a role on a task is permitted and is not checked. A task's own record shows who holds it; trace on a task shows its assignments. That is object → performer, and it is the product. Half of the package's rule-6 tests assert the permissive side, because a gate that quietly refused the legitimate direction would be a regression dressed as hardening.
Two further consequences for the integrator:
- A worklist query has no assignee member. "Me" comes from the auth rail; you cannot construct a query for someone else's list.
- A failed claim says held. It does not say who holds it, because that is performer → objects one task at a time.
Never a per-unit-time figure
A per-person report is one shape of the refused direction. A per-unit-time figure is the other, and it is refused even when it is not keyed by person, because it becomes one the moment anyone groups it. The door computes no duration, no per-unit-time count, nothing that can be summed across people and compared — not to the worker, not to any customer, not in any export. A count is allowed. A timestamp is allowed. A step indicator within one task is allowed.
For the vendor
Your customer will ask for the per-person report, and will describe it reasonably. The answer this door gives is that the report and the evidence cannot both exist, and the evidence is what they are paying for. Who touched this pallet is answered fully, with attestation, on a bag of lettuce or a lot of ten thousand. What did this person do is a query the package refuses with a typed problem, at construction, with a fixture proving it.
Get started by writing a query grouped by object and then by performer, and reading the two responses. One is the product.