/** * roster.ts — fetch the named-writer roster from the server. * * GET /api/sdk/roster?app_id=&room_id= * Response: { roster: Record, avatars?: Record, * roles?: Record } * * The roster endpoint requires the same SDK JWT the widget already uses * for message reads. The returned Map is the client's * only source of truth for writer names + avatars + roles; SSE `type:"roster"` * events are invalidation signals that trigger a re-fetch (they carry no data). * * The `avatars` map is ADDITIVE (T18-avatar): a server that predates avatar * support simply omits it, and every member's `avatarUrl` resolves to `null`. * * The `roles` map is ADDITIVE + SPARSE (P5): only members with a privileged * role (`moderator`/`owner`) appear — the default `member` role is implied by * absence, same sparse convention as `avatars`. A server that predates role * support omits the key entirely, and every member's `role` resolves to * `undefined`. An unrecognised role string (future server-side role we don't * yet know) is dropped at parse time — fail closed to "no badge", never * surface an unknown value to the UI. * * These are UX-only presentation hints. The server remains the sole source of * truth for authorization — callers MUST NOT use `role` to gate privileged * operations client-side, only to show/hide affordance hints. */ /** Privileged roster roles. Absence (`undefined`) means the default `member` role. */ export type PrivilegedRole = 'moderator' | 'owner'; /** * One roster member: their display name plus optional avatar URL and role. * * `avatarUrl` is `null` when the member has no avatar (the common case) or * when talking to a server that predates avatar support. * * `role` is `undefined` for a plain member (the common case), a server that * predates role support, or an unrecognised role string. */ export interface RosterEntry { displayName: string; avatarUrl: string | null; role?: PrivilegedRole; } /** Injectable fetch for tests. */ export interface FetchRosterOptions { baseUrl: string; appId: string; roomId: string; jwt: string; fetchImpl?: typeof fetch; } /** * Fetch the roster for a room. * * Returns a Map — empty on 404 (roster not yet seeded). * Throws SDKChatError on network or server error. */ export declare function fetchRoster(opts: FetchRosterOptions): Promise>; /** * Return the display name for an epid from the roster map. * Miss fallback: first 8 chars of the epid (e.g. "ep_12345" → "ep_12345"). * Never blank, never the raw full epid when it is long. * * XSS note: callers MUST assign via textContent (not innerHTML). */ export declare function rosterDisplayName(roster: Map, epid: string): string; /** * Return the avatar URL for an epid from the roster map, or `null` when the * member has no avatar (or is absent from the roster). * * Security note: the URL is caller-supplied roster data. Callers MUST assign * it via `img.src` (the property), never via innerHTML, and should treat it as * untrusted (the server validates the scheme, but be defensive). */ export declare function rosterAvatar(roster: Map, epid: string): string | null; /** * Return the privileged role for an epid from the roster map, or `undefined` * for a plain member (or when the epid is absent from the roster). * * UX-only: never use this to gate a privileged operation client-side — the * server is the sole source of truth for authorization. */ export declare function rosterRole(roster: Map, epid: string): PrivilegedRole | undefined; //# sourceMappingURL=roster.d.ts.map