auth/actor_lookup_action_specs.ts

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 detail - email, password/credential fields β€” never queried - created_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:

1. rate-limit (per-account, see above), 2. {@link ACTOR_LOOKUP_IDS_MAX} cap per call, 3. actor-uuid intractability (122-bit random), 4. hard-deleted actors are indistinguishable from never-existed (no tombstone oracle β€” see actor_lookup_queries.ts).

Response order is unspecified β€” callers index by id when needed.

Declarations
#

6 declarations

view source

actor_lookup_action_spec
#

auth/actor_lookup_action_specs.ts view source

{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; }; side_effects: false; input: ZodObject<{ ids: ZodArray<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>; output: ZodObject<...>; async: true; rate_limit: "account"; description: string; }

ACTOR_LOOKUP_IDS_MAX
#

ActorLookupEntryJson
#

auth/actor_lookup_action_specs.ts view source

ZodObject<{ id: $ZodBranded<ZodUUID, "Uuid", "out">; username: ZodString; display_name: ZodOptional<ZodString>; }, $strict>

One resolved actor row. display_name omitted when blank.

ActorLookupInput
#

ActorLookupOutput
#

all_actor_lookup_action_specs
#

auth/actor_lookup_action_specs.ts view source

readonly [{ method: string; kind: "request_response"; initiator: "frontend"; auth: { account: "required"; actor: "none"; }; side_effects: false; input: ZodObject<{ ids: ZodArray<$ZodBranded<ZodUUID, "Uuid", "out">>; }, $strict>; output: ZodObject<...>; async: true; rate_limit: "account"; description: string; }]

All actor_lookup action specs β€” independent opt-in registry. Consumers spread alongside all_standard_action_specs if they want the labels arc; not folded into the standard bundle because consumers without a byline surface can skip it.

Imported by
#