auth/actor_lookup_queries.ts

Batched actor-by-id resolver.

Joins actoraccount so callers see (username, display_name) for each actor row. The byline / owner-column / grantor surfaces stamp an actor id, so resolving "who is this actor?" lands the human label in one round trip.

Accounts may host multiple actors (multi-actor shipped in v0.55.0). The inner join still resolves one row per actor — actor.account_id is NOT NULL so every actor has exactly one account.

Info-leak posture (see auth/actor_lookup_action_specs.ts §audit):

  • Row shape omits account_id — the join is control-plane, not wire-visible.
  • Hard-deleted actors (or account-cascade-orphaned rows) drop out silently — indistinguishable from never-existed (no tombstone oracle).
  • No created_at / updated_at projected (timing-oracle avoidance).
  • Response order is unspecified — WHERE id = ANY(...) returns index-scan order in practice but callers must not depend on it.

Caller is responsible for capping ids.length — the SQL itself does not enforce a bound; the action-spec layer surfaces invalid_params via ACTOR_LOOKUP_IDS_MAX.

view source

Declarations
#

2 declarations

ActorLookupRow
#

auth/actor_lookup_queries.ts view source

ActorLookupRow import type {ActorLookupRow} from '@fuzdev/fuz_app/auth/actor_lookup_queries.js';

Row shape returned to handlers — wire mapping happens at the action layer.

id

type Uuid

username

type string

display_name

type string | null

query_actors_by_ids
#

auth/actor_lookup_queries.ts view source

(deps: QueryDeps, ids: readonly (string & $brand<"Uuid">)[]): Promise<ActorLookupRow[]> import {query_actors_by_ids} from '@fuzdev/fuz_app/auth/actor_lookup_queries.js';

Resolve a batch of actor ids to (id, username, display_name). Empty input fast-paths to []. Hard-deleted actors (or account-cascade- orphaned rows) drop out of the result silently.

deps

ids

type readonly (string & $brand<"Uuid">)[]

returns

Promise<ActorLookupRow[]>

Depends on
#

Imported by
#