Per-user daily quota enforcement for demo mode.
When the platform provides a shared AI key (DEMO_GOOGLE_API_KEY), users
who have NOT configured their own AI provider are subject to daily limits
on expensive operations (crawl, test run, AI generation).
Users who bring their own key (BYOK) bypass all demo quotas.
Quota defaults (overridable via env vars)
| Operation | Env var | Default |
|---|---|---|
| Crawl | DEMO_DAILY_CRAWLS |
2 |
| Test run | DEMO_DAILY_RUNS |
3 |
| AI generation | DEMO_DAILY_GENERATIONS |
5 |
Counters reset at midnight UTC. Stored in-memory (single instance) or Redis (multi-instance) when available.
- Source:
Example
import { demoQuota } from "../middleware/demoQuota.js";
router.post("/projects/:id/crawl", demoQuota("crawl"), expensiveOpLimiter, handler);
Members
(static, constant) isDemoEnabled :boolean
Demo mode is active when a platform-owned key is set.
Type:
- boolean
- Source:
Methods
(static) demoQuota(operation) → {function}
Create a middleware that enforces demo-mode daily quotas.
Parameters:
| Name | Type | Description |
|---|---|---|
operation |
"crawl" | "run" | "generation" | Which quota bucket to check. |
- Source:
Returns:
Express middleware.
- Type
- function
(static) getDemoQuotaStatus(userId) → {Promise.<Object>}
Get the current demo quota status for a user. Used by the dashboard/config endpoint so the frontend can show remaining quota.
Parameters:
| Name | Type | Description |
|---|---|---|
userId |
string |
- Source:
Returns:
Quota status per operation.
- Type
- Promise.<Object>
(inner) cleanupMemCounters()
Remove stale entries from yesterday or earlier.
- Source:
(inner) serverHasConfiguredKey() → {boolean}
Check whether any AI provider key has been configured on this server (beyond the platform-owned demo key). When true, all users bypass demo quotas — this is a SERVER-GLOBAL check, not per-user.
Rationale: Sentri stores AI keys at the server level (env vars or
Settings page), not per-user. If an admin configures a key via
POST /api/v1/settings, ALL users benefit from it. In the intended
demo deployment, no admin keys are set — only DEMO_GOOGLE_API_KEY.
If per-user key storage is added in the future, this function should be updated to check user-scoped keys instead.
- Source:
Returns:
- Type
- boolean