Multi-Tenancy
InfraSage is built as a multi-tenant platform. Each tenant gets isolated data, independent API keys, configurable rate limits, and a full audit trail.
Tenant Isolation
Each tenant in InfraSage has:
- Separate data namespacing in ClickHouse — queries are always scoped to
tenant_id - Independent API keys with their own rate limits and permission scopes
- Per-tenant quotas — max events/month, max API keys, max users, max RPS
- Separate audit logs — every state-changing operation is recorded per tenant
- Independent billing metering — hourly event counts tracked by type
There is no cross-tenant data leakage. A tenant cannot query another tenant's metrics, anomalies, or RCA results.
Tenant Lifecycle
Register a Tenant
curl -X POST http://localhost:8080/api/v1/tenants \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SUPER_ADMIN_JWT" \
-d '{
"tenant_id": "acme-corp",
"name": "Acme Corporation",
"plan": "pro",
"contact_email": "ops@acme.com"
}'
List Tenants
curl http://localhost:8080/api/v1/tenants \
-H "Authorization: Bearer $SUPER_ADMIN_JWT"
Role-Based Access Control (RBAC)
InfraSage uses a 5-tier RBAC model. Every API request must include a valid JWT or API key. Permissions are evaluated at request time.
| Role | Level | Capabilities |
|---|---|---|
| Viewer | 1 | Read metrics, anomalies, RCA results, dashboards |
| Operator | 2 | Viewer + trigger runbooks, acknowledge incidents |
| Admin | 3 | Operator + manage users, API keys, integrations |
| Super-Admin | 4 | Admin + manage tenants, billing plans |
| System | 5 | Internal service-to-service communication only |
Assign roles when creating users or issuing JWTs:
# Get permissions for current user
curl http://localhost:8080/api/v1/rbac/permissions \
-H "Authorization: Bearer $YOUR_JWT"
API Keys
API keys are the primary way for services and CI/CD pipelines to send telemetry. See API Keys for full details.
Key scopes
| Scope | Allowed Operations |
|---|---|
ingestion | POST /api/v1/telemetry only |
readonly | GET requests — query metrics, anomalies, RCA |
full | All operations within the tenant |
Create an API key (Admin+)
curl -X POST http://localhost:8080/api/v1/apikeys \
-H "Authorization: Bearer $ADMIN_JWT" \
-d '{
"tenant_id": "acme-corp",
"name": "Production Ingestion Key",
"scope": "ingestion",
"rate_limit_rps": 1000,
"expires_at": "2027-01-01T00:00:00Z"
}'
Response includes the key (only shown once):
{
"key_id": "isage_key_abc123",
"api_key": "isage_ab...xyz",
"scope": "ingestion",
"created_at": "2026-04-10T12:00:00Z"
}
Billing Plans and Quotas
When a tenant exceeds their plan quota, new ingestion requests return HTTP 429 Too Many Requests until the billing period resets.
| Plan | Events/mo | API Keys | Users | RPS | Retention |
|---|---|---|---|---|---|
| Free | 1M | 2 | 3 | 10 | 7 days |
| Starter | 50M | 5 | 10 | 100 | 30 days |
| Pro | 500M | 20 | 50 | 500 | 90 days |
| Enterprise | Unlimited | 100 | 500 | 5,000 | 365 days |
See Billing Plans for full details.
Audit Logging
Every state-changing operation is recorded in infrasage_audit_log with a 365-day TTL:
- Tenant creation / modification
- API key creation / deletion
- User role changes
- Runbook execution (who triggered, who approved)
- Configuration changes
# Query audit log via ClickHouse
docker exec infrasage-clickhouse clickhouse-client \
--user infrasage --password infrasage-dev \
--query "
SELECT timestamp, actor, action, resource, details
FROM infrasage.infrasage_audit_log
WHERE tenant_id = 'acme-corp'
ORDER BY timestamp DESC
LIMIT 50
"
Teams
Tenants can organize users into teams for fine-grained alert routing:
curl -X POST http://localhost:8080/api/v1/teams \
-H "Authorization: Bearer $ADMIN_JWT" \
-d '{
"tenant_id": "acme-corp",
"name": "Platform SRE",
"members": ["alice@acme.com", "bob@acme.com"],
"on_call_rotation": ["alice", "bob", "carol"]
}'
Teams are used by PagerDuty and Slack integrations to route alerts to the correct on-call engineer.