GovernanceSecurityRBACAuth

RBAC & Tenancy

7 min read

QueryWise is multi-tenant by design. This page covers the access control and isolation primitives.

Roles

Four built-in roles, in decreasing privilege:

  • owner — billing, team management, full operational control. Can transfer ownership.
  • admin — full operational control. Cannot manage billing or transfer ownership.
  • editor — connect cloud accounts, apply recommendations, edit budgets, push tickets.
  • viewer — read-only.

Role assignments are per-user, per-tenant. A user can be a member of multiple tenants with different roles in each.

Authentication

Primary: Auth0 with RS256-signed JWTs. Supported identity providers:

  • Email + password
  • Google
  • Microsoft
  • SAML SSO (enterprise)
  • OIDC (enterprise)

The dev environment supports a bypass-login mode for local testing. It's gated by ENVIRONMENT=development and is never available in staging or production.

JWT validation happens in the auth middleware on every request. Tokens are validated against Auth0's JWKS endpoint with key caching. Expired tokens return 401 immediately.

MFA / SSO

MFA can be enforced per-tenant via Auth0. Two paths:

  • Tenant-level enforcement — admin enables MFA, all members must enroll within a grace period.
  • User-level opt-in — users can enable MFA from Settings → Security.

For enterprise plans, SAML SSO and OIDC SSO can be configured through the Auth0 management console. The tenant.settings["sso"] JSONB field stores tenant-level SSO requirements.

API keys

API keys are an alternative to user JWT for programmatic access. Properties:

  • Scoped to a tenant and a role (typically editor or viewer)
  • Generated at Settings → API Keys, displayed once at creation
  • Stored as Argon2id hashes; the plaintext is never recoverable
  • Can be rotated or revoked at any time
  • Optional expiration date

API key requests use the same auth middleware as JWT — the validation path differs but the downstream RBAC is identical.

Multi-tenant isolation

QueryWise uses PostgreSQL schema-per-tenant isolation:

  • Shared schema qw_shared holds: organizations, tenants, users, audit_logs, time-series data with tenant_id partitioning, and other cross-tenant tables.
  • One schema per tenant (qw_tenant_<uuid>) holds tenant-specific objects: cloud_accounts, recommendations, budgets, cost_centers, tag_policies, etc.

The auth middleware sets the PostgreSQL search_path on the SQL session to the tenant's schema. Every downstream query is automatically scoped — there is no application-level tenant filter to forget.

Time-series data (billing_records, query_stats, usage_metrics, query_plans) lives in the shared schema with a tenant_id column and TimescaleDB hypertable partitioning. Row-level security (RLS) policies enforce tenant isolation on these tables.

Audit logging

Every API write goes through the audit middleware, which logs:

  • Actor (user or API key)
  • Tenant
  • Action (e.g. recommendation.apply, cloud_account.create)
  • Target (entity type + id)
  • Request payload (sanitized — credentials and secrets are redacted)
  • Outcome (success / error)
  • Timestamp

Reads are sampled to keep volume manageable. The audit feed is available via:

  • Activity Log dashboard page
  • GET /api/v1/audit/events API
  • Bulk CSV export for compliance reporting

Audit logs are retained for 1 year on standard plans, 7 years on enterprise.

Credential vault

Cloud account credentials are stored in the credential vault — CredentialStore abstraction with two backends:

  • Fernet (default) — symmetric encryption with key managed in environment
  • AWS Secrets Manager — production deployments

Credentials are never logged, never returned in API responses, and never persisted in plaintext. Tasks fetch credentials at run time and pass them only to the connector that needs them.

JIRA / ServiceNow OAuth tokens use a separate _encryption.py Fernet shim because they need different rotation semantics.

Sessions

Sessions are JWT-based with a 24-hour default lifetime (configurable per tenant). Refresh tokens are stored in HttpOnly Secure cookies.

Settings → Security lets users:

  • View active sessions across devices
  • Revoke individual sessions
  • See last login time and IP

Admins can also revoke sessions for any user in their tenant.

Data retention

Default retention:

  • Time-series data: 13 months (configurable)
  • Recommendations: indefinite, but archived after apply
  • Audit logs: 1 year (standard) / 7 years (enterprise)
  • Query plans: 90 days

Retention is enforced by the data_retention.py worker, which runs daily.

Compliance

QueryWise is on a SOC 2 Type II readiness path. The current state:

  • Tenant isolation tested and audited (docs/security-audit-tenant-isolation.md)
  • Encryption at rest (database) and in transit (TLS everywhere)
  • Audit logging on every write
  • Quarterly access reviews (built into the platform)

For enterprise customers under formal compliance review, the SOC 2 readiness assessment is available on request.

Where to next

Need help with onboarding?

Design partners get full docs plus hands-on support from our engineering team.