actor_lookup RPC spec — authenticated batched id → username/display_name
resolver, keyed by actor id.
Powers the labels arc for surfaces that stamp an actor id (bylines,
owner columns, grantor labels, audit-log "by" cells). One round trip
resolves an array of ids to display strings.
Auth + rate-limit posture
{account: 'required', actor: 'none'} + rate_limit: 'account'.
Account-grain — only that the caller is signed in matters, not which
actor is calling, so resolution skips the actor phase. The auth gate
+ per-account rate limit (default 1200/15min) + the
{@link ACTOR_LOOKUP_IDS_MAX | per-call cap} bound the batched
username-enumeration surface that the cell_list ↔ actor_lookup
pair would otherwise present.
If a public-surface byline ever lands (e.g. an unauthenticated
gallery), it should resolve via a separate public-safe mechanism
(SSR-stamped labels or a per-cell embedded actor label), not by
loosening this gate.
Wire shape — info-leak audit
Output: {actors: [{id, username, display_name?}]}. Deliberately
omitted:
account_id — the actor↔account join is a control-plane detailemail, password/credential fields — never queriedcreated_at / updated_at — timing-oracle avoidance- role / role_grants / session state — separation of concern
display_name is omitted (not null) when actor.name is blank, so
clients see undefined rather than a sentinel string. Unknown ids are
silently absent from the response — by construction this is an
existence-oracle (the caller can diff response ids against request
ids), bounded by:
- rate-limit (per-account, see above),
- {@link ACTOR_LOOKUP_IDS_MAX} cap per call,
- actor-uuid intractability (122-bit random),
- hard-deleted actors are indistinguishable from never-existed (no
tombstone oracle — see auth/actor_lookup_queries.ts).
Response order is unspecified — callers index by id when needed.