iurban/stable/: iurban-tenancy-0.1.1 metadata and description

Simple index

iUrban shared multi-tenancy SDK: SQLAlchemy Base + mixins + RLS session helper (ADR-006)

author_email iUrban <dev@iurban.es>
description_content_type text/markdown
requires_dist
  • sqlalchemy[asyncio]>=2.0
  • fastapi>=0.111; extra == 'dev'
  • pytest-asyncio>=0.23; extra == 'dev'
  • pytest>=8; extra == 'dev'
  • ruff>=0.5; extra == 'dev'
  • fastapi>=0.111; extra == 'fastapi'
requires_python >=3.12

Because this project isn't in the mirror_whitelist, no releases from root/pypi are included.

File Tox results History
iurban_tenancy-0.1.1-py3-none-any.whl
Size
4 KB
Type
Python Wheel
Python
3
iurban_tenancy-0.1.1.tar.gz
Size
4 KB
Type
Source

iurban-tenancy

Shared multi-tenancy data layer for iUrban microapps (ADR-006). Stops every microapp from copying tenancy.py / reinventing RLS.

What it gives you

Use

from iurban_tenancy import Base, UuidPkMixin, TenantMixin, TimestampMixin, rls_ddl

class Incident(UuidPkMixin, TenantMixin, TimestampMixin, Base):
    __tablename__ = "incidents"
    # ... your columns

# migration: op.execute(rls_ddl("incidents"))
# app wiring (FastAPI + iurban-auth)
from fastapi import Depends, HTTPException
from iurban_auth import current_user
from iurban_tenancy.fastapi import make_tenant_session
from .db import async_session

def tenant_id(user = Depends(current_user)) -> str:
    if not user.tenant_id:
        raise HTTPException(403, "token carries no tenant_id")
    return user.tenant_id

tenant_session = make_tenant_session(async_session, tenant_id)

Rules (ADR-006)

App connects as a non-superuser role; apply_tenant runs inside a transaction (safe with PgBouncer transaction-pooling — a non-LOCAL SET would leak across tenants). Schema changes only via Alembic migrations.