# Quota Enforcement System

**Last Updated:** April 27, 2026

## Overview

Stratofusion enforces subscription-based quotas and plan limits for data
transfer and search operations. Quota state is persisted in the environment's
PostgreSQL database—Compose PostgreSQL in production and the retained
development database elsewhere—so usage survives restarts, redeploys, and
multi-instance traffic.

## Gated Actions

### Quota-Enforced

- Uploads count toward both daily and monthly transfer quota windows.
- Copy, move, backup, and sync launches count toward both daily and monthly transfer quota windows when byte estimates are available.
- Downloads count toward the same daily and monthly transfer quota windows.
- Search requests count toward the daily search quota.
- Upload, copy, move, backup, sync, and download flows also enforce plan-level `max file size` and `files per batch` limits before launch when the selected files can be resolved.
- AI search remains plan-gated and requires Pro or Unlimited.

### Not Gated

- Browse and list operations.
- Rename operations.
- Delete operations.
- File metadata reads and previews.

## Tier Limits

| Capability | Free | Pro | Unlimited |
| --- | --- | --- | --- |
| Daily data transfer | 1 GB | 50 GB | 500 GB |
| Monthly data transfer | 10 GB | 200 GB | 15 TB |
| Daily searches | 10 | 200 | Unlimited |
| Max file size | 100 MB | 2 GB | 10 GB |
| Files per batch | 100 | 1,000 | 10,000 |
| AI search | No | Yes | Yes |

## Warning And Block Behavior

- At `80%` usage, the UI shows warning state in the header and billing dashboard.
- At `100%` usage, the API blocks the operation.
- Blocked quota requests return HTTP `402 Payment Required`.
- Plan-limit failures for file size or files-per-batch also return HTTP `402 Payment Required`.
- Quota errors include usage, limit, reset time, tier, and upgrade path metadata when available.

## Persistence Model

Quota state is stored in two Postgres tables:

- `user_quota_usage`.
  - One row per `(user, month)` for current transfer, download, and daily search state.
- `quota_usage_history`.
  - Append-only audit trail for subscription quota consumption and provider/account transfer windows.

## Reset Schedule

- Daily upload/download usage and daily search usage reset at `00:00 UTC`.
- Monthly upload/download usage resets at `00:00 UTC` on the first day of the next month.
- Resets are lazy and automatic. The application creates or reuses the current month record and clears stale daily counters when the stored UTC date no longer matches today.

## Main API Surfaces

- `GET /api/quotas/status`.
  - Returns live quota state for the current data transfer window plus daily/monthly transfer snapshots, search, and AI search.
- `GET /api/subscription/usage`.
  - Returns billing-oriented daily/monthly data transfer usage and daily search usage for the authenticated user.
- `GET /api/transfer-quotas`.
  - Returns provider/account upload and download quota snapshots derived from Postgres history.
- `POST /api/google/upload`.
- `POST /api/onedrive/upload`.
- `POST /api/dropbox/upload`.
- `POST /api/download/resolve`.
- `POST /api/jobs/backup`.
- `POST /api/jobs/sync`.
- `POST /api/search/enhanced`.

## UI Surfaces

- `QuotaProvider`.
  - Polls quota status and exposes live quota data to the client.
- `QuotaWarningBadge`.
  - Shows compact `80%+` warnings in the header.
- `UpgradePromptModal`.
  - Provides an in-context upgrade path to `/user/billing`.
- `SubscriptionUsageDashboard`.
  - Shows detailed daily/monthly data transfer usage and search usage in billing settings.

## Error Shape

Quota failures use `CloudStorageErrorCode.QUOTA_EXCEEDED` in server code and surface structured API metadata to clients.

Example response:

```json
{
  "success": false,
  "error": "Monthly transfer limit exceeded for free plan. Used: 10 GB / 10 GB. Resets at: 2026-04-01T00:00:00.000Z.",
  "errorCode": "QUOTA_EXCEEDED",
  "metadata": {
    "httpStatus": 402
  }
}
```

## Current Implementation Notes

- Data transfer quota enforcement is hard-blocking. No overage is allowed.
- Google Drive uploads create server-side Fly gateway sessions and stream browser file bytes through the rclone service to avoid Google Drive CORS limits.
- Provider-level quota checks still run after subscription quota checks where relevant.
- Plan file-size and files-per-batch limits are checked before data transfer quota consumption so rejected operations do not burn monthly allowance.
- If a provider-side check fails after a subscription reservation, the reserved subscription bytes are rolled back.
- Sync launches roll back subscription quota reservations if a later reverse-direction quota check or Fly.io launch step fails before an operation ID is created.
- Some folder and sync flows rely on pre-flight size estimation. If the size cannot be resolved, the route cannot fully pre-block based on bytes.
