v2.0.1

Multi-Organization RBAC

Kavach resolves authorization from an explicit TenantContext. Resources are never authorized from client-provided roles or permission claims.

Overview

Kavach resolves authorization from an explicit TenantContext; resources are never authorized from client-provided roles or permission claims. The REST transport accepts organization and project selectors through X-Kavach-Organization-Id and X-Kavach-Project-Id. With the development identity provider only, X-Kavach-Actor-Id may select an actor. Request IDs are generated when absent and correlation IDs are preserved.

The permission model is version 1. Built-in roles and their immutable mapping live in kavach.tenancy.permissions. Authorization denies by default, checks active membership, resolves organization-wide plus selected-project role assignments, and returns a stable reason code.

Built-in Roles

The five built-in roles are read-only definitions:

  • ORGANIZATION_ADMIN — owns all version-1 permissions.
  • GOVERNANCE_ADMIN — manages policies, decisions, evaluations, jobs, synchronization, and governance audit.
  • GOVERNANCE_REVIEWER — can read and publish review-ready governance state.
  • PLATFORM_OPERATOR — runs jobs, evaluations, retries, cancellation, and ontology reconciliation.
  • VIEWER — has project governance read access.

Tenant Context

Control-plane endpoints are rooted at /api/v1/organizations; the current resolved identity, roles, permissions, and selected scope are exposed by GET /api/v1/context. Organization and project records use archival rather than deletion. Membership and assignment removal protects the last active organization administrator.

Assignments

Organization-wide assignments use a null project_id; project assignments apply only in the selected project. Membership must be active before any role can authorize an operation. Membership or assignment revocation is immediately consistent and the last active organization administrator is protected.

Persistence and Migration

Set KAVACH_TENANCY_REPOSITORY to inmemory, sqlite, or postgres. SQLite requires KAVACH_TENANCY_SQLITE_PATH; PostgreSQL requires KAVACH_TENANCY_POSTGRES_DSN. Both relational schemas contain organization, project, membership, and assignment constraints plus tenant-aware indexes.

SQLite initialization performs an idempotent compatibility migration. Existing policy, decision, job, evaluation, experiment, registry, ontology-event, and audit rows are backfilled into the configured bootstrap scope. PostgreSQL uses idempotent ADD COLUMN IF NOT EXISTS migration statements.

Production Identity Guardrail

KAVACH_IDENTITY_PROVIDER=development logs a critical warning. A production environment rejects it unless KAVACH_ALLOW_DEVELOPMENT_IDENTITY_IN_PRODUCTION=true is explicitly set.