array | null
Who this issue is assigned to, resolved to handle + display name.
## Why this is on the list DTO at all, when it used to be forbidden
The standing objection was N+1: assignees live in `issue_assignees`,
so "serve them on the list" was read as "one query per row". **N+1 is
a property of the CALL SHAPE, not of the data.** Assignees for a PAGE
of issues are one statement — `WHERE issue_id = ANY($1)` over the ids
the listing already selected (`PgIssueStore::assignees_for_issues`) —
so the cost is one round trip per page, whatever the page size.
The cost of the old answer was paid entirely by the UI: the issue list
row had no assignee to render, so its assignee control had no resting
value to sit on, so it shipped `sr-only` with `tabindex=-1` and a
pointer user could not assign anyone from any list. Four controls were
in that state for this one reason.
**Serving it here costs the browser NOTHING.** It rides the list
response that was already being fetched, so `issues-list.fresh` in
`neosource-app/e2e/request-budget/budgets.ts` — asserted by EQUALITY —
is unchanged.
## `None` is NOT "unassigned" — and the type says so
`None` means this response did not run the enrichment; `Some([])` means
it ran and the issue has nobody on it. An `Option` rather than the
`Vec` this shipped as for one day, because the flat vec made those two
states the same value and something downstream had already started
reading the wrong one:
the SPA's optimistic label/assignee patch matches its container BY
SHAPE (`$lib/queries/issueProperties.ts`), and an always-empty
`assignees: []` on the un-enriched detail DTO matched vacuously — so a
row-side attach painted the DETAIL cache too, and the settle refetch
silently reverted it. Invisible only because `IssueDetailBody` happens
to read `labelKeys.issue(id)` instead. `Array.isArray(null)` is false,
so the `Option` makes that match unrepresentable rather than unlikely
(CLAUDE.md § "Convention → type").
Enrichment is a LIST-route concern: the routes that populate this are
the two that render `IssueListRow` — `GET /api/repos/{owner}/{repo}/issues`
and `GET /api/teams/{team_id}/issues`.
itemsIssueAssigneeResponse
object
One assignee, resolved to something renderable. This used to be a bare
`account_id` string; a UUID is not a UI, and every consumer would otherwise
have to fan out to the account store itself.