Skip to article
Documentation

src/lib/auth/actor.ts

Linked repository file from this build.

import { z } from "zod";

export const roleSchema = z.enum([
  "examiner",
  "supervisor",
  "pec",
  "program_manager",
  "admin",
  "statistics",
]);
export type DemoRole = z.infer<typeof roleSchema>;

/**
 * A signed-in staff member. Clerk public metadata gives the identity and scope.
 * `preferences` come from user-editable Clerk metadata, so they are never saved in records.
 */
export const actorSchema = z
  .object({
    name: z.string().min(1),
    role: roleSchema,
    staffId: z.string().min(1),
    program: z.string().min(1),
    reportsToStaffId: z.string().optional(),
    subordinateStaffIds: z.array(z.string()).optional(),
    preferences: z.record(z.string(), z.unknown()).optional(),
  })
  .strict();
export type Actor = z.infer<typeof actorSchema>;

/**
 * Who did something, as saved in review records. System writers such as the seed
 * have no staff ID. Older records can also lack it.
 */
export interface ActorRef {
  name: string;
  role: DemoRole;
  staffId?: string;
}

export function actorRef(actor: ActorRef): ActorRef {
  return {
    name: actor.name,
    role: actor.role,
    ...(actor.staffId ? { staffId: actor.staffId } : {}),
  };
}

/** Staff IDs identify people. Names only match records saved without a staff ID. */
export function sameActor(a: ActorRef, b: ActorRef): boolean {
  if (a.staffId || b.staffId) return a.staffId === b.staffId;
  return a.name === b.name && a.role === b.role;
}