This document describes tenant-level configuration options that affect the behavior of AISentinel. It focuses on which settings are available in the Dashboard UI, which are only available via the API, the default values used by the system, and the role requirements that control who can change a setting.
High-level summary:
GET /api/config and PATCH /api/config are used to show and update general, non-sensitive tenant settings (for example, rate limits and API timeouts). The UI also proxies calls to backend tenant-config endpoints for a number of per-tenant overrides.GET /api/v1/tenant-config/{key} and PUT /api/v1/tenant-config/{key} handle per-tenant overrides stored in the backend's encrypted tenant config storage (the tenant_configs table). Only the keys listed in the server's _TENANT_CONFIG_DEFAULTS are accepted by these endpoints.Where to edit (examples):
{ "value": ... } to set or { "value": null } to clear the override and revert to defaultAuthorization & role restrictions:
The sections below list keys that are either exposed via the Dashboard UI, or only accessible through the API. Each entry indicates whether it is modifiable in the Dashboard and the role required to change it.
Note: The server determines which tenant-config keys are recognized by looking at the _TENANT_CONFIG_DEFAULTS table in the backend implementation (src/AISentinel_auditor/app.py). The Dashboard exposes a subset of these keys via the UI.
Dashboard UI (fields shown on the Configuration page)
rateLimit — (dashboard: UI top-level) requests per minute; patchable via PATCH /api/config.apiTimeout — (dashboard: UI top-level) API request timeout in seconds; patchable via PATCH /api/config.estimatorPerTokenUsd ↔ ESTIMATOR_PER_TOKEN_USD — per-token USD estimator; editable by any tenant member via tenant-config API.estimatorToolBaseCosts ↔ ESTIMATOR_TOOL_BASE_COSTS — JSON object of base tool costs; editable by any tenant member.safeDocsUrl ↔ SAFE_DOCS_URL — Admin-only; trusted doc fallback for the LLM.urlWhitelist ↔ URL_WHITELIST — Admin-only; domain patterns allowed by web tools.llmSkipLowRiskTools ↔ LLM_SKIP_LOW_RISK_TOOLS — Comma-separated list of tools to skip LLM checks; user preference.llmFeatureWeights ↔ LLM_FEATURE_WEIGHTS — Admin-only; JSON weights for LLM assessments.llmModel ↔ LLM_MODEL — Admin-only; selects the LLM for assessments.enableResearchEndpoint ↔ ENABLE_RESEARCH_ENDPOINT — Admin-only boolean that enables autonomous research features.maxMemoryUsageMb ↔ MAX_MEMORY_USAGE_MB — Admin-only; resource limit in MB.maxDiskUsageMb ↔ MAX_DISK_USAGE_MB — Admin-only; resource limit in MB.maxToolExecutionTime ↔ MAX_TOOL_EXECUTION_TIME — Admin-only; maximum per-tool execution time in seconds.ssoProvider, ssoOktaClientId, ssoOktaIssuer, ssoAzureAdClientId, ssoAzureAdTenantId, ssoGoogleClientId, ssoAuth0Domain, ssoAuth0ClientId — SSO-related client IDs/metadata; CMS-style UI editing is supported for client IDs and issuer fields; secrets remain server-level protected data and are provisioned via POST /tenants/provision-sso.General (UI: Patch /api/config)
rateLimit) — Number (requests per minute)
PATCH /api/config (frontend Prisma TenantConfig.rateLimit)RateLimitMiddleware in the backend. This key is a typical UI-controlled setting, and changes take effect immediately for that tenant.apiTimeout) — Number (seconds)
PATCH /api/config (frontend)Estimator & cost settings (UI & API: tenant-config)
ESTIMATOR_PER_TOKEN_USD) — Decimal
PUT /api/v1/tenant-config/ESTIMATOR_PER_TOKEN_USD for user-level override; can be changed by any tenant member.ESTIMATOR_TOOL_BASE_COSTS) — JSON
PUT /api/v1/tenant-config/ESTIMATOR_TOOL_BASE_COSTS (UI shows a JSON field; the backend stores it as a string)Security & LLM settings (Dashboard UI shows these; many require Admin/Owner)
SAFE_DOCS_URL) — string (URL)
PUT /api/v1/tenant-config/SAFE_DOCS_URL (Admin-only).URL_WHITELIST) — string (comma-separated patterns)
PUT /api/v1/tenant-config/URL_WHITELIST (Admin-only)docs.example.com, .gov, .edu)LLM_MODEL) — string
PUT /api/v1/tenant-config/LLM_MODEL (Admin-only)LLM_SKIP_LOW_RISK_TOOLS) — string (comma-separated)
PUT /api/v1/tenant-config/LLM_SKIP_LOW_RISK_TOOLS (User preference: any tenant member)LLM_FEATURE_WEIGHTS) — JSON
PUT /api/v1/tenant-config/LLM_FEATURE_WEIGHTS (Admin-only)Resource limits (Admin-only)
MAX_MEMORY_USAGE_MB) — integer MB
PUT /api/v1/tenant-config/MAX_MEMORY_USAGE_MB (Admin-only)MAX_DISK_USAGE_MB) — integer MB
PUT /api/v1/tenant-config/MAX_DISK_USAGE_MB (Admin-only)MAX_TOOL_EXECUTION_TIME) — seconds
PUT /api/v1/tenant-config/MAX_TOOL_EXECUTION_TIME (Admin-only)SSO & Identity
POST /tenants/provision-sso (Admin-only). The provisioning flow stores secrets in AWS Secrets Manager when AWS_SECRET_NAME is set, or falls back to encrypted tenant config.SSO_PROVIDER, SSO_OKTA_CLIENT_ID, SSO_OKTA_ISSUER, SSO_AZURE_AD_CLIENT_ID, SSO_AZURE_AD_TENANT_ID, SSO_GOOGLE_CLIENT_ID, SSO_AUTH0_DOMAIN, SSO_AUTH0_CLIENT_ID, SSO_DOMAIN_ALLOWLIST.SSO_OKTA_CLIENT_SECRET, SSO_AZURE_AD_CLIENT_SECRET, SSO_GOOGLE_CLIENT_SECRET, SSO_AUTH0_CLIENT_SECRET are sensitive and require the Admin/Owner API flow to set.Other keys (API-only / Not shown in Dashboard)
CONTRACT_SEARCH_API_KEY and CONTRACT_SEARCH_API_URL — these are API-backed configuration values for contract-search / research integrations. They are sensitive and require Admin/Owner permissions.CIRCUIT_BREAKER_FAILURE_THRESHOLD, CIRCUIT_BREAKER_RECOVERY_TIMEOUT, CIRCUIT_BREAKER_SUCCESS_THRESHOLD — API-only in most setups; they can be adjusted via PUT /api/v1/tenant-config/....OFFLINE_MODE_ENABLED, DEFAULT_REPORT_EMAILS, EMBEDDED_TOOLS_DEFAULT, and other advanced keys are available in _TENANT_CONFIG_DEFAULTS but aren't necessarily surfaced in the Dashboard UI — you can still set them via the backend API if needed.Changing configuration via API — Examples
Read a key (returns effective value and the source—either tenant or default):
GET /api/v1/tenant-config/URL_WHITELIST Response: { "key": "URL_WHITELIST", "value": "docs.example.com,.gov,.edu", "source": "tenant" }
Set a key via API (clear override by sending value: null). This requires a valid tenant API token and may require Admin/Owner role based on key sensitivity.
PUT /api/v1/tenant-config/URL_WHITELIST Body: { "value": "docs.example.com,.gov,.edu" }
or
PUT /api/v1/tenant-config/SAFE_DOCS_URL Body: { "value": "https://internal.example/safe" }
To clear an override and fall back to default: PUT /api/v1/tenant-config/SAFE_DOCS_URL Body: { "value": null }
SSO Provisioning (Admin-only)
Provision SSO for a tenant and persist secrets (preferred) with AWS Secret Manager or an encrypted override in tenant config:
POST /tenants/provision-sso Body: { "name": "My Tenant", "provider": "okta", "client_id": "", "client_secret": "", "issuer": "https://dev-xxxx.okta.com", "domain_allowlist": ["example.com", "*.myorg.com"], "confirm_test": true }
This will create a tenant (or prepare one if it already exists), store the SSO client ID and client secret in a secret store (when available), and optionally run an OIDC discovery and test.
Permissions & enforcement (important)
PUT /api/v1/tenant-config/SAFE_DOCS_URL requires an API key created by an ADMIN or OWNER user (or a system token). All tenant-config changes are audited by the backend.Validation & safe defaults
PUT /api/v1/tenant-config/{key} endpoint validates values for some keys (for example numeric thresholds, booleans, or JSON weights) and returns 400 on invalid data.value: null), the system uses the default value from _TENANT_CONFIG_DEFAULTS or environment variables.Testing & propagation
Debugging note for operators
_TENANT_CONFIG_DEFAULTS, _SENSITIVE_CONFIG_KEYS, and _USER_CONFIG_KEYS in src/AISentinel_auditor/app.py in the backend codebase. The Dashboard inspects a subset of these keys.Below is a concise table summarizing the tenant-config keys, followed by code examples for each key.
| Key | Type | Default | Validation/Notes | UI Endpoint | Admin required |
|---|---|---|---|---|---|
| rateLimit | integer | 60 | UI: integer >= 10 (requests per minute) | PATCH /api/config | No |
| apiTimeout | integer (s) | 30 | UI-enforced: 1-600s | PATCH /api/config | No |
| ESTIMATOR_PER_TOKEN_USD | decimal | 0.0001 | Numeric, >= 0 | PUT /api/v1/tenant-config/ESTIMATOR_PER_TOKEN_USD | No |
| ESTIMATOR_TOOL_BASE_COSTS | JSON | {"web":0.001,"python_exec":0.01} | JSON object with numeric values | PUT /api/v1/tenant-config/ESTIMATOR_TOOL_BASE_COSTS | No |
| SAFE_DOCS_URL | URL | "" | If non-empty must be http(s) URL | PUT /api/v1/tenant-config/SAFE_DOCS_URL | Yes |
| URL_WHITELIST | CSV string | "" | Comma-separated patterns; UI validates pattern rules | PUT /api/v1/tenant-config/URL_WHITELIST | Yes |
| LLM_SKIP_LOW_RISK_TOOLS | CSV string | "" | Allowed tools: calc, web, search, python_exec, browser | PUT /api/v1/tenant-config/LLM_SKIP_LOW_RISK_TOOLS | No |
| LLM_FEATURE_WEIGHTS | JSON | "" | JSON mapping to numeric weights (keys: llm_confidence, llm_expected_impact, llm_policy_risk) | PUT /api/v1/tenant-config/LLM_FEATURE_WEIGHTS | Yes |
| LLM_MODEL | string | "" | Model id string | PUT /api/v1/tenant-config/LLM_MODEL | Yes |
| ENABLE_RESEARCH_ENDPOINT | boolean | false | Bool-like (true/false etc) | PUT /api/v1/tenant-config/ENABLE_RESEARCH_ENDPOINT | Yes |
| MAX_MEMORY_USAGE_MB | integer | 512 | > 0 | PUT /api/v1/tenant-config/MAX_MEMORY_USAGE_MB | Yes |
| MAX_DISK_USAGE_MB | integer | 100 | > 0 | PUT /api/v1/tenant-config/MAX_DISK_USAGE_MB | Yes |
| MAX_TOOL_EXECUTION_TIME | integer (s) | 300 | > 0 | PUT /api/v1/tenant-config/MAX_TOOL_EXECUTION_TIME | Yes |
| MASK_PII_AUTOMATICALLY | boolean | true | Bool-like | PUT /api/v1/tenant-config/MASK_PII_AUTOMATICALLY | No |
| OFFLINE_MODE_ENABLED | boolean | false | Bool-like | PUT /api/v1/tenant-config/OFFLINE_MODE_ENABLED | No |
| DEFAULT_REPORT_EMAILS | CSV string | "" | Each entry must be a valid email | PUT /api/v1/tenant-config/DEFAULT_REPORT_EMAILS | No |
| EMBEDDED_TOOLS_DEFAULT | CSV string | calc,web | Allowed tool set: calc, web, search, python_exec, browser | PUT /api/v1/tenant-config/EMBEDDED_TOOLS_DEFAULT | No |
| CONTRACT_SEARCH_API_KEY | string | "" | Sensitive; treat as secret | PUT /api/v1/tenant-config/CONTRACT_SEARCH_API_KEY | Yes |
| CONTRACT_SEARCH_API_URL | URL | https://search.contract/v1/query | Ideally a valid URL | PUT /api/v1/tenant-config/CONTRACT_SEARCH_API_URL | Yes |
| CIRCUIT_BREAKER_* | integer | 3/60/2 | Positive integers | PUT /api/v1/tenant-config/CIRCUIT_BREAKER_* | No |
| SSO_DOMAIN_ALLOWLIST | CSV string | "" | Comma-separated domain patterns; UI & backend validate patterns | PUT /api/v1/tenant-config/SSO_DOMAIN_ALLOWLIST | Yes |
| SSO_*_CLIENT_SECRET | string (secret) | "" | Sensitive secret - provision via POST /tenants/provision-sso (preferred) | POST /tenants/provision-sso | Yes |
Below are per-key code examples; replace placeholders with your tenant host and authorization credentials.
curl -X PATCH "https://<HOST>/api/config" \
-H "Authorization: Bearer <FRONTEND_TOKEN_OR_COOKIE>" \
-H "Content-Type: application/json" \
-d '{"rateLimit": 1000}'
curl -X PATCH "https://<HOST>/api/config" \
-H "Authorization: Bearer <FRONTEND_TOKEN_OR_COOKIE>" \
-H "Content-Type: application/json" \
-d '{"apiTimeout": 45}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/ESTIMATOR_PER_TOKEN_USD" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": 0.00012}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/ESTIMATOR_TOOL_BASE_COSTS" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": {"web": 0.001, "python_exec": 0.01}}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/SAFE_DOCS_URL" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": "https://docs.example.com/safe"}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/URL_WHITELIST" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": "docs.example.com,.gov,.edu"}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/LLM_SKIP_LOW_RISK_TOOLS" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": "calc,search"}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/LLM_FEATURE_WEIGHTS" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": {"llm_confidence": 1.5, "llm_expected_impact": 1.0, "llm_policy_risk": -2.0}}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/LLM_MODEL" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": "gpt-4"}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/ENABLE_RESEARCH_ENDPOINT" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": true}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/MAX_MEMORY_USAGE_MB" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": 1024}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/MAX_DISK_USAGE_MB" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": 512}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/MAX_TOOL_EXECUTION_TIME" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": 300}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/MASK_PII_AUTOMATICALLY" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": false}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/OFFLINE_MODE_ENABLED" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": false}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/DEFAULT_REPORT_EMAILS" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": "ops@example.com,reports@example.com"}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/EMBEDDED_TOOLS_DEFAULT" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": "calc,web"}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/CONTRACT_SEARCH_API_KEY" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": "<api-key>"}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/CONTRACT_SEARCH_API_URL" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": "https://search.contract/v1/query"}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/CIRCUIT_BREAKER_FAILURE_THRESHOLD" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": 5}'
curl -X PUT "https://<HOST>/api/v1/tenant-config/SSO_DOMAIN_ALLOWLIST" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"value": "example.com,*.myorg.com"}'
curl -X POST "https://<HOST>/api/tenants/provision-sso" \
-H "Authorization: Bearer <API_KEY>" \
-H "Content-Type: application/json" \
-d '{"name":"TenantName","provider":"okta","client_id":"cid123","client_secret":"s3cr3t","issuer":"https://dev-xxxx.okta.com","confirm_test":true}'