Module: middleware/demoQuota

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