SPB Git

Repository Public

dto-auth.ts 3.4 KB 101 lines typescript

1/**2 * Auth / notification / system wire shapes. The auth DTOs mirror the previous console's shapes3 * exactly (the server keeps them identical); they live here because `@aos/shared` only carries4 * the Agent OS vocabulary. System status is parsed leniently: every field the server does not5 * send renders as "—".6 */7import '@/lib/zod-config';8import { z } from 'zod';9import { Branding } from '@aos/shared';1011const iso = z.string();12const Id = z.string().uuid();1314export const AuthStatus = z.object({15  setupRequired: z.boolean(), // no administrator exists yet -> setup flow with one-time token16  authenticated: z.boolean(),17  user: z.object({ id: Id, username: z.string() }).nullable(),18  methods: z.object({ password: z.boolean(), passkeys: z.number(), totp: z.boolean() }),19  csrfToken: z.string().nullable(), // required as X-CSRF-Token on every mutating request20  sessionExpiresAt: iso.nullable(),21  branding: Branding.optional(),22});23export type AuthStatus = z.infer<typeof AuthStatus>;2425/** Password OK but second factor still needed. */26export const LoginStep = z.object({27  ok: z.boolean(),28  next: z.enum(['done', 'totp', 'passkey', 'enroll_second_factor']),29  retryAfterSec: z.number().optional(),30});31export type LoginStep = z.infer<typeof LoginStep>;32export const TotpEnrollStart = z.object({ secret: z.string(), otpauthUrl: z.string() });33export type TotpEnrollStart = z.infer<typeof TotpEnrollStart>;3435export const Device = z.object({36  id: Id,37  kind: z.enum(['passkey', 'session']),38  label: z.string(),39  createdAt: iso,40  lastUsedAt: iso.nullable(),41  current: z.boolean(),42  userAgent: z.string().nullable(),43  ip: z.string().nullable(),44});45export type Device = z.infer<typeof Device>;4647export const ApiError = z.object({48  error: z.object({ code: z.string(), message: z.string(), details: z.unknown().optional() }),49});50export type ApiError = z.infer<typeof ApiError>;5152export const Notification = z.object({53  id: z.string(),54  kind: z.string(),55  title: z.string(),56  body: z.string(),57  link: z.string().nullable(),58  readAt: iso.nullable(),59  createdAt: iso,60});61export type Notification = z.infer<typeof Notification>;6263export const AuditEvent = z.object({64  id: z.string(),65  at: iso,66  actor: z.string(),67  action: z.string(),68  target: z.string().nullable(),69  ip: z.string().nullable(),70  ok: z.boolean(),71  detail: z.record(z.string(), z.unknown()),72});73export type AuditEvent = z.infer<typeof AuditEvent>;7475/** GET /system/status — the server's shape (`apps/server/src/dto.ts`). Unknown ⇒ null. */76export const SystemStatus = z.looseObject({77  collectedAt: iso,78  version: z.string(),79  db: z.looseObject({ ok: z.boolean(), latencyMs: z.number().nullable() }),80  worker: z.looseObject({81    /** null = cannot tell (no heartbeat row and no leased run). */82    alive: z.boolean().nullable(),83    lastSeenAt: iso.nullable(),84    source: z.enum(['workers', 'leases', 'none']),85    workers: z.array(z.looseObject({ id: z.string(), lastSeenAt: iso, version: z.string().nullable() })),86  }),87  providers: z.looseObject({ anthropic: z.boolean(), openai: z.boolean() }),88  counts: z.record(z.string(), z.number()),89});90export type SystemStatus = z.infer<typeof SystemStatus>;9192/** GET /runs/:id/artifacts — assumed item shape. */93export interface ArtifactDto {94  sha256: string;95  name: string;96  size: number | null;97  mime?: string | null;98  stepSeq?: number | null;99  createdAt?: string | null;100}101
Files main
Menu

Theme