Developer Limits
Admins can configure per-developer and per-extension limits to control resource usage on the extension platform.
Sound limits
Each extension has three configurable sound limits. Each limit resolves in priority order:
| Priority | Source | Where to set |
|---|---|---|
| 1 (highest) | Per-extension override | Admin → Hub → Extensions → the extension's row |
| 2 | Per-developer override | Admin → Hub → Developers → developer detail → "Limit Overrides" |
| 3 (lowest) | Platform default | See defaults below |
| Limit key | Default | Description |
|---|---|---|
max_sounds_per_extension | 50 | Maximum bundled sounds per extension |
max_sound_file_size | 10 MB (10 485 760 bytes) | Maximum size per individual sound file |
max_sound_storage_bytes | 200 MB (209 715 200 bytes) | Total sound storage across all sounds in an extension |
The two size limits are stored in bytes; the admin forms take and display MB and convert on save. Every resolved limit is returned with a source marker of extension, developer, or default.
System extensions install with limit checks skipped — they are trusted and bypass sound-limit enforcement at install time.
Setting developer limits
- Navigate to Admin → Hub → Developers
- Click a developer to open their detail page
- In the Limit Overrides section, set values for the three sound limits. Max Sounds per Extension accepts 0–500; the two size fields take MB.
- Each field has its own Save button, and a Reset button appears once the field has a value — Reset clears the override back to the platform default.
The Limit Overrides section is rendered only for admins holding developer-limits:edit.
The override applies to all extensions owned by this developer (unless an extension has its own override).
Setting per-extension limits
- Navigate to Admin → Hub → Extensions
- Find the extension in the list
- Edit the limit cells inline — max sounds, file size, and storage each have their own editable cell, gated on
developer-limits:edit
Leave a field empty to use the developer's limit or the platform default.
How limits are enforced
- CLI (
lumio deploy) — fetches the resolved limits from the API and pre-flights count, per-file size, and total storage before uploading. Blocks the deploy with a descriptive error if exceeded. It falls back to the platform defaults (50 / 10 MB / 200 MB) when the limits call fails. - Server (upload endpoint) — validates the sound count, file sizes, and total storage in the manifest against the resolved limits. Returns a
PlanLimitReachederror if exceeded. - Server (install) — defence-in-depth check at install time. A sound count over the resolved limit logs a warning and truncates; total storage over the resolved limit fails the whole install. Neither should trigger if upload validation ran. Skipped entirely for system extensions.
Limit Requests
Developers can request limit increases from their own developer limits page at /account/developer/limits. Admins review them on the global Limit Requests page at /developers/limit-requests, which has no sidebar entry — navigate to it directly. A per-developer Limit Requests section also appears on each developer's detail page.
Review workflow
- Open
/developers/limit-requests(or the Limit Requests section on a developer's detail page) - Pick a status tab and open a request to see its details, including the requested value, the current value, and the developer's reason
- Approve — the requested value is applied automatically. Extension-scoped requests write the matching per-extension limit column; developer-scoped requests write a developer-level override.
- Reject — opens a dialog for review notes. The notes are optional at the API level but the reject dialog asks for them.
Every status change is written to a timeline of events and broadcast to the developer over a WebSocket channel, so the developer sees the decision without reloading.
Request statuses
| Status | Meaning |
|---|---|
open | Submitted, waiting for admin review |
in_review | An admin is reviewing the request |
approved | Approved — the limit is applied automatically |
rejected | Rejected — review notes explain the reason |
open is the submitted state. The review endpoint accepts only in_review, approved, or rejected — a request cannot be moved back to open.
The rest of the Developers area
The sidebar's Hub → Developers sub-group carries four entries. Limit work happens on the developer detail page reached from the first one.
| Page | Route | Page gate |
|---|---|---|
| All Developers | /developers | developer-verification:read |
| Developer Teams | /developers/teams | developer-limits:read |
| Developer Verifications | /developers/verifications | developer-verification:read |
| Developer Applications | /developers/applications | developer-verification:read |
Two more routes exist without a sidebar entry — navigate to them directly:
| Page | Route | Page gate |
|---|---|---|
| Limit Requests (global) | /developers/limit-requests | developer-limits:read |
| Developer Team detail | /developers/teams/\{id\} | developer-limits:read |
The developer detail page at /developers/\{id\} also carries a revenue-split control (50–100% developer share) and a delete action, next to the Limit Overrides and Limit Requests sections.
Per-extension limits are edited on the Hub → Extensions pages (/extensions and /extensions/reviews), both gated on extension-review:read, with the limit cells themselves gated on developer-limits:edit.
API endpoints
| Method | Path | Permission | Description |
|---|---|---|---|
GET | /v1/admin/developers/\{id\}/limits | developer-limits:read | List developer limit overrides |
PUT | /v1/admin/developers/\{id\}/limits | developer-limits:edit | Set/remove a developer limit override |
PATCH | /v1/admin/extensions/\{id\}/limits | developer-limits:edit | Set/clear per-extension limit overrides |
GET | /v1/admin/limit-requests | developer-limits:read | List all limit requests |
GET | /v1/admin/developers/\{id\}/limit-requests | developer-limits:read | List limit requests for a developer |
PUT | /v1/admin/limit-requests/\{id\} | developer-limits:edit | Review (approve/reject) a limit request |
GET | /v1/admin/limit-requests/\{id\}/events | developer-limits:read | Get timeline events for a limit request |
GraphQL: adminDeveloperLimits, adminSetDeveloperLimit, adminSetExtensionLimits, adminAllLimitRequests, adminDeveloperLimitRequests, adminLimitRequestEvents, adminReviewLimitRequest — see GraphQL reference.
The admin app calls these through its own proxy routes: /api/developers/\{id\}/limits, /api/extensions/\{id\}/limits, /api/limit-requests, /api/limit-requests/\{requestId\}, and /api/limit-requests/\{requestId\}/events.