forked from EduCraft/curriculum-project-hub
feat: org capacity policy admin surface
ADR-0022 / Spec.System.Capacity pins layered capacity limits: a platform ceiling per dimension is unbreakable, and each organization may only set a lower `organizationLimit`. The effective limit is the minimum of the two (`LayeredLimit.effective`); dimensions with no org override fall back to the platform ceiling. No dimension may be unlimited (a ceiling must exist before an org limit can be set, `LayeredLimit.Valid`). Add the backend: the pinned 23 CapacityDimension set + labels (src/capacity/dimensions.ts), platform ceilings sourced from existing runtime env vars plus `HUB_CEILING_<DIMENSION>` (src/capacity/ceilings.ts), the OrganizationCapacityPolicy prisma model + migration, the getCapacityPolicy/setCapacityPolicy service enforcing LayeredLimit.Valid, and org-admin GET/PUT /api/org/:orgSlug/capacity-policy routes wired into the org route tree. Add the admin-web surface: CapacityDimension/CapacityPolicyView api client types, capacityPolicy/setCapacityPolicy methods, a `容量` nav entry, and a capacity page that lists every dimension with its platform ceiling (or `未配置` when unset), an org-limit input (disabled until a ceiling exists), and a live effective-value column. Saving sends the partial limits map; the service rejects values above the ceiling or for unconfigured dimensions.
This commit is contained in:
@@ -188,6 +188,42 @@ export interface UsageReport {
|
||||
totals: UsageTotals;
|
||||
}
|
||||
|
||||
export type CapacityDimension =
|
||||
| 'requestRate'
|
||||
| 'requestBodySize'
|
||||
| 'agentConcurrency'
|
||||
| 'admissionQueueLength'
|
||||
| 'admissionQueueWait'
|
||||
| 'fileSize'
|
||||
| 'attachmentCount'
|
||||
| 'archiveExpansion'
|
||||
| 'projectStorage'
|
||||
| 'organizationStorage'
|
||||
| 'memberCount'
|
||||
| 'projectCount'
|
||||
| 'teamCount'
|
||||
| 'folderCount'
|
||||
| 'sessionCount'
|
||||
| 'runWallTime'
|
||||
| 'runTurns'
|
||||
| 'runToolCalls'
|
||||
| 'toolWallTime'
|
||||
| 'runOutputSize'
|
||||
| 'processMemory'
|
||||
| 'processCpu'
|
||||
| 'processCount';
|
||||
|
||||
export interface CapacityDimensionRow {
|
||||
dimension: CapacityDimension;
|
||||
platformCeiling: number | null;
|
||||
organizationLimit: number | null;
|
||||
effective: number | null;
|
||||
}
|
||||
|
||||
export interface CapacityPolicyView {
|
||||
dimensions: CapacityDimensionRow[];
|
||||
}
|
||||
|
||||
// --- API ---
|
||||
|
||||
export const api = {
|
||||
@@ -297,4 +333,9 @@ export const api = {
|
||||
) => put(`${orgBase(slug)}/feishu-application-connection`, body) as Promise<FeishuApplicationConnection>,
|
||||
disableFeishuApplication: (slug: string) =>
|
||||
del(`${orgBase(slug)}/feishu-application-connection`) as Promise<FeishuApplicationConnection>,
|
||||
|
||||
capacityPolicy: (slug: string) =>
|
||||
get(`${orgBase(slug)}/capacity-policy`) as Promise<CapacityPolicyView>,
|
||||
setCapacityPolicy: (slug: string, body: { limits: Partial<Record<CapacityDimension, number | null>> }) =>
|
||||
put(`${orgBase(slug)}/capacity-policy`, body) as Promise<CapacityPolicyView>,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user