Skip to content

Tenancy

The DX-correct surface for future hard multi-tenancy. Today the proto and stores scope rows by (app_name, user_id, session_id); hard_multi_tenant mode is design-only and tape doctor warns loudly about it.

import tape

cfg = tape.TenancyConfig(mode=tape.TenancyMode.HARD_MULTI_TENANT, tenant_id="acme")
for w in cfg.warn_if_hard_but_unenforced():
    print("warn:", w)

See Tenancy guide for the deployment-level discussion.

Tenancy — the DX-correct surface for future hard multi-tenancy.

Today, the proto/storage layer doesn't carry a first-class tenant_id; rows are scoped by (app_name, user_id, session_id). That's fine for single or trusted_multi_app. It is NOT enough for hard_multi_tenant (where the tenant boundary is also an authorization boundary).

This module gives the SDK and CLI a single place to:

  • declare the project's tenancy mode (config-driven, validated);
  • pick a tenant_id for the current process / request;
  • tag log records and span attributes consistently;
  • warn loudly when hard_multi_tenant is requested but the runtime can't enforce it.

tape doctor reads this and turns it into a check.

TenancyConfig dataclass

TenancyConfig(mode: TenancyMode = TenancyMode.SINGLE, tenant_id: str = 'default')

warn_if_hard_but_unenforced

warn_if_hard_but_unenforced() -> list[str]

Return a list of human-readable warnings if hard_multi_tenant is requested but the runtime can't enforce it. Empty list means OK.