# Tenant Admin Quota Delegation v1

## Purpose

Define how tenant admins can manage quotas for projects and users without weakening platform-admin control, billing correctness, or scheduler safety.

This document covers quota authority and API/read-model implications. It does
not implement billing budgets, invoicing, payment collection, or a full policy
engine.

## Decision

Tenant admins may allocate quota within a platform-defined tenant envelope. They cannot raise the tenant envelope, publish SKUs, change global policy,
or bypass platform capacity and billing rules.

Supported first scopes:

- Tenant envelope, set by platform admin.
- Department/cost-center quota, set by tenant owner/admin within the tenant envelope.
- Project quota, set by tenant owner/admin within the department envelope.
- User quota override, set by tenant owner/admin within the project quota.

Project admins may view project quota and usage posture, but should not change quota in v1 unless a tenant admin explicitly delegates that authority
through a future role permission.

## Quota Types

Start with operational quotas that protect capacity and runaway spend:

| Quota | Tenant Envelope | Department Quota | Project Quota | User Override | Notes |
|---|---:|---:|---:|---:|---|
| Active allocation count | Yes | Yes | Yes | Yes | Extends current `allocation.max_concurrent_per_user` beyond global-only policy. |
| GPU count by SKU class | Yes | Yes | Yes | Optional | Needed for H200 vs future AMD/NVIDIA classes and slice vs bare-metal controls. |
| Storage quota bytes | Yes | Yes | Yes | Optional | Provider-neutral; WEKA first, VAST later. |
| Monthly spend/budget cap | Yes | Yes | Yes | Optional | Billing redesign owns enforcement semantics; quota surface can show planned state. |
| App entitlement concurrency | Yes | Yes | Yes | Optional | Useful for vLLM/Jupyter/training app workloads. |

Do not model network/firewall/public-IP quotas in this first version. Connectivity quotas belong under Access/Connectivity once VRF, firewall, public
IP, load balancer, and VPN shapes are real.

## Authority Model

Platform admin:

- Sets tenant-level maximums and default quota templates.
- Can override or suspend tenant/department/project/user quota.
- Owns global policy keys, SKU publication, and capacity admission rules.

Tenant owner:

- Can distribute the tenant envelope across departments and projects.
- Can set user overrides inside projects.
- Can delegate tenant-admin role to other users.

Tenant admin:

- Can distribute department quota, project quota, and user overrides unless the tenant owner disables this delegation.
- Cannot raise total tenant quota or enable SKU classes not allowed by platform policy.
- Cannot create billing commitments or payment terms; those belong to the billing epic.

Department admin:

- Future role. May manage project quota inside the department envelope when
  delegated by tenant owner/admin.
- Cannot raise department quota, move projects across departments, or create
  billing commitments unless granted separate tenant/billing authority.

Project admin:

- Can view project quota, active usage, and blocked-launch reasons.
- Cannot change project quota in v1.
- Future option: allow `project.quota.manage` permission for self-service teams where tenant policy permits it.

Project user:

- Can view effective personal quota and launch-blocking reasons.
- Cannot modify quota.

## Precedence

Effective quota is the minimum of all applicable ceilings:

```text
global/platform policy
  -> tenant envelope
  -> department quota
  -> project quota
  -> user override, if present
  -> SKU/app entitlement and regional availability
```

If a lower scope is unset, inherit from the nearest upper scope. If a scope sets a value higher than its parent, reject the mutation.

Department quota is a cost-center/governance envelope over projects. It is not a
resource container and does not own workload resources directly.

Policy-engine note: the evaluation shape should be compatible with a future
OPA/OPAL or equivalent policy engine. MVP may use in-code evaluation, but the
decision input should carry actor, tenant, department, project, requested
resource/action, current usage, requested delta, and policy source. The output
should carry allow/deny, effective ceiling, inherited-from scope, reason, and
correlation id.

## Mutations

All quota mutations must be:

- idempotent with `X-Idempotency-Key`,
- audited with before/after values,
- correlation-id tagged,
- policy-validated against parent envelopes,
- applied in a transaction with any outbox event used for read-model invalidation.

Recommended action names:

- `quota.tenant_envelope.set`
- `quota.department.set`
- `quota.project.set`
- `quota.user_override.set`
- `quota.override.clear`

## API Shape

First read models:

- `GET /api/v1/v3/access/entitlements` should expose effective quota posture for apps, SKUs, and regions.
- A future tenant-admin quota workbench should expose project and user quota rows with `effective`, `configured`, `inherited_from`, and `blocked_reason`.

Future mutation APIs:

- `GET /api/v1/tenant/quotas`
- `PUT /api/v1/tenant/departments/{department_id}/quotas`
- `PUT /api/v1/tenant/projects/{project_id}/quotas`
- `PUT /api/v1/tenant/projects/{project_id}/users/{user_id}/quotas`
- `DELETE /api/v1/tenant/projects/{project_id}/users/{user_id}/quotas/{quota_key}`

These should be contract-first additions. Do not overload platform-admin `/admin/quotas` for tenant-scoped mutation.

## Data Model Direction

Use a scoped quota table rather than adding more global policy keys:

```text
quota_assignments
  id
  quota_key
  scope_type: tenant | department | project | user
  scope_id
  value_json
  state: active | disabled
  created_by_user_id
  updated_by_user_id
  created_at
  updated_at
```

`platform_policy_values` remains for platform/global defaults.
`quota_assignments` holds delegated tenant/department/project/user settings.

## UX Implications

User mode:

- Show effective quota and blocked-launch reason inside launch wizards.
- Do not make users leave the launch wizard to understand missing quota.

Tenant admin mode:

- Landing page should surface department and project quota posture, including
  near-limit departments and projects.
- Access or Finance surfaces may link into quota, but quota management should not be hidden in platform-only Config.

Department admin mode:

- Show department envelope, child project allocation, active usage, and projects
  near limit.
- If department-admin mutation is disabled, show the tenant-admin owner/action path.

Project admin mode:

- Show project quota, active usage, and who is consuming capacity.
- If project-admin mutation is disabled, show the tenant-admin owner/action path.

Platform mode:

- Platform Config owns tenant envelope templates and SKU-level global caps.
- Platform Ops sees quota as one possible reason for launch/provisioning denial, not as the primary management surface.

## Billing Boundary

Quota is not invoice policy. Quota can prevent allocation or app launch. Billing decides pricing mode, commitment, invoice timing, delinquency, budget
alerts, payment terms, and usage accounting. Budget caps may look like quotas in UI, but billing owns money movement and legal/accounting semantics.

## Open Questions

- Should tenant owners be able to delegate project-admin quota mutation through a custom role?
- Should department admins be part of the first department capability promotion,
  or should departments remain reporting-only until hard budgets are ready?
- Should user overrides be absolute caps or only reductions from project defaults?
- Should storage quota be enforced by provider backends immediately or initially as launch/admission control?
- Which quota changes require delayed effective-at scheduling instead of immediate application?
