/** * Quota dimensions (ADR 0011, issue #22). Each value resolves on the * three-level ladder: pond override → user override → instance default — * the most specific wins, mirroring the permission philosophy. */ import { z } from 'zod'; export const QUOTA_KEYS = [ 'editors_per_pond', 'readers_per_pond', 'additional_ponds', 'storage_bytes', 'max_file_bytes', ] as const; export type QuotaKey = (typeof QUOTA_KEYS)[number]; /** Which subject a quota override applies to (data-model.md §Quotas). */ export type QuotaSubject = 'user' | 'pond'; /** * One quota dimension for a subject in the admin UI (issue #58): the effective * value on the ladder (pond/user override → instance default), the override at * this level if any, and current usage where the dimension is metered. */ export interface QuotaLineView { key: QuotaKey; /** The override set at this subject level, or `null` (falls back). */ override: number | null; instanceDefault: number; effective: number; /** Current usage for metered dimensions (storage/seats/ponds), else `null`. */ usage: number | null; } /** The resolved quota picture for one user or pond. */ export interface QuotaSubjectView { type: QuotaSubject; id: string; label: string; lines: QuotaLineView[]; } export const setQuotaOverrideSchema = z.object({ value: z.number().int().min(0) }); export type SetQuotaOverrideInput = z.infer;