Roles, rate limits, audit log
Understand who can do what in VisualQ FRT, the rate limits in place, and where to find the audit trail.
Role matrix
VisualQ FRT reuses the project's organization roles
(owner / admin / member / viewer).
| Action | viewer | member | admin / owner |
|---|---|---|---|
| Read features, runs, step library | ✓ | ✓ | ✓ |
Compile (/api/frt/compile) | — | ✓ | ✓ |
Recorder (/api/frt/recorder/*) | — | ✓ | ✓ |
| Create / update features | — | ✓ | ✓ |
Trigger runs (/api/frt/run) | — | ✓ | ✓ |
| Push run results to Xray | — | ✓ | ✓ |
| Edit / delete step definitions | — | — | ✓ |
| Delete a feature | — | — | ✓ |
| Delete a run doc | — | — | ✓ |
| Enable / disable public living-doc | — | — | ✓ |
Project-level access is enforced via verifyOrgProjectAccess on every
endpoint, so even a member of the org can't see another project's features
without explicit project membership.
Rate limits
LLM tokens and worker time can spiral if a client falls into a tight loop. VisualQ enforces the following caps at the API edge:
| Endpoint | Per user / minute | Per org / hour |
|---|---|---|
POST /api/frt/compile | 30 | 200 |
POST /api/frt/run | 10 | 100 |
Recorder pairing and detect endpoints (/api/frt/recorder/*) require an active
session token from the Chrome extension.
When a cap is hit, VisualQ replies 429 with a Retry-After header in
seconds. Counters live in Firestore (one doc per org/window) so they
survive Vercel cold starts.
Audit log
Every compile and run is recorded in
organizations/{orgId}/frt_audit_log/{auditId} with:
userId— who triggered the action.projectId,featureId, optionalrunId.action—compileorrun.bindings,aiGenerations,tokensUsed(compile only).browsers,scenarioFilter,triggeredBy(run only —userorci).timestamp(ISO 8601).
The collection is admin-write-only, so only the API can append rows. You can read it directly from Firestore for billing investigations or filter it through your own dashboard.
Cost knobs
If your org consistently hits the LLM limits:
- Cache — every successful compile dedupes by
hash(stepText + projectId + baseUrl). Reuse step phrasing across features and you'll get free repeats. - Project scope — putting common steps at the org or system scope means one generation amortises across every project.
- Edited-by-user steps — once a step body is hand-tuned, AI never re-generates it; you only burn tokens on truly new phrasing.
If 200 compiles/hour is too tight for your team, contact us — we lift the cap on Pro/Enterprise plans on request.