# Usage & Limits Dashboard

The tenant-scoped **Usage & Limits** dashboard presents committed outbound SMS consumption and durable quota configuration. It reads through `UsageQueryService`; it does not derive a second usage total from messages or delivery receipts.

## SMS units and UTC periods

One SMS unit is one SMS segment. Multipart SMS messages consume multiple units according to the accepted message's authoritative `total_parts` value.

- A daily period runs from 00:00:00 UTC up to the next UTC midnight.
- A monthly period is a UTC calendar month.
- Today and This Month always refer to those UTC periods, not the browser timezone.
- The daily series is bounded to 7, 30, or 90 UTC days and explicitly includes zero-use days.

The page shows its last-refreshed UTC timestamp. A normal refresh reads the latest committed counters; the page does not imply streaming or poll in the background.

## Limits

Tenant and application daily/monthly limits support:

- a positive integer for a finite allowance;
- zero to block new outbound usage;
- null, entered by leaving the field blank, for Unlimited.

An application's finite limit cannot exceed the corresponding finite tenant limit. When the tenant limit is Unlimited, an application can use any valid finite value or Unlimited.

Reducing a limit below current usage is allowed. It does not alter usage records or reset counters; new submissions remain blocked until the applicable UTC period advances. Each save requires an explicit operational-impact confirmation.

## Presentation states

The labels are display-only and do not modify enforcement:

- below 70%: Normal;
- 70% to below 90%: Approaching limit;
- 90% to below 100%: Near limit;
- 100%: Limit reached;
- no finite limit: Unlimited.

Every state is rendered as text and does not rely on color.

## Permissions and tenancy

Active tenant members with existing workspace visibility can view the dashboard. Tenant administrators, platform administrators in an authorized tenant workspace, or users with the established `applications.manage` permission can configure limits. Other roles receive no mutation controls, and direct mutation requests fail with 403. Cross-tenant tenant and application references use generic 404 responses.

Limit changes are recorded by `DatabaseAuditLogger` with the actor ID, previous/new values, and an application public ID when applicable. Message content, recipients, Sender IDs, credentials, and individual usage rows are never included.

## Scope boundary

This dashboard does not implement wallet balances, money, pricing, billing, payments, subscriptions, plans, user management, public usage APIs, or analytics beyond the bounded daily series and current-month top applications.

## Local verification checklist

1. Log in as TenantAdmin and open **Usage & Limits**.
2. Confirm today/month usage matches known accepted SMS parts, including multipart usage.
3. Save tenant daily/monthly limits, then application limits.
4. Clear a field and confirm it displays Unlimited; set zero and confirm new usage is blocked.
5. Reduce a limit below current usage and confirm existing counters remain unchanged.
6. Submit under the limit, then reach the limit and confirm `USAGE_LIMIT_EXCEEDED`.
7. Confirm a rejected single or bulk request creates no message, SMS row, usage record, event, outbox record, or partial counter update.
8. Confirm the next UTC period uses its new counter and effective allowance.
9. Log in with a read-only tenant role and confirm limit controls are absent and direct mutation is forbidden.
10. Confirm a different tenant cannot view the page or update an application.
11. Repeat navigation and form saves through local, LAN, and public-IP URLs with any detected subdirectory base path preserved.

Do not deploy as part of this checklist.
