feat(B2): add tenant model + migrations 035/036 + RLS policies

Migration 035: tenants table with 'Schaeffler' default seed.
Migration 036: tenant_id FK on all tables, RLS policies, backfill.
New domains/tenants/ with CRUD router (admin only).
All domain models extended with tenant_id FK.
core/database.py: get_db_for_tenant with RLS context setter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 16:30:41 +01:00
parent b87df4a3e5
commit 251dd703ed
19 changed files with 537 additions and 7 deletions
+9 -1
View File
@@ -1,8 +1,13 @@
import uuid
from datetime import datetime
from decimal import Decimal
from sqlalchemy import String, Boolean, DateTime, Text, Numeric, Integer, UniqueConstraint, Index
from sqlalchemy import String, Boolean, DateTime, Text, Numeric, Integer, UniqueConstraint, Index, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.dialects.postgresql import UUID
from app.database import Base
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from app.domains.tenants.models import Tenant
class PricingTier(Base):
@@ -14,6 +19,9 @@ class PricingTier(Base):
price_per_item: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
description: Mapped[str | None] = mapped_column(Text, nullable=True)
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
tenant_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True), ForeignKey("tenants.id"), nullable=True, index=True
)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)