Why: - first runnable slice of ADR-0012's resource-lifetime rules and ADR-0015's package layout: app-lifetime clients built once in the lifespan, released via explicit dependencies. Changes: - Settings split into per-domain nested settings (postgres/minio/ingestion/qdrant/app/logging); FastAPI app wired with /healthz, /readyz and a /v1 router; Postgres/MinIO/Qdrant adapters and SQLAlchemy models for tenants, API keys, source files, ingestion jobs/events.
28 lines
1.2 KiB
Python
28 lines
1.2 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import CheckConstraint, DateTime, String, func
|
|
from sqlalchemy.dialects.postgresql import JSONB
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from src.infrastructure.postgres.models.base import Base
|
|
|
|
TENANT_STATUSES = ("active", "suspended", "deleted")
|
|
|
|
|
|
class Tenant(Base):
|
|
__tablename__ = "tenants"
|
|
__table_args__ = (CheckConstraint(f"status IN {TENANT_STATUSES}", name="ck_tenants_status"),)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(primary_key=True)
|
|
slug: Mapped[str] = mapped_column(String(80), unique=True, index=True)
|
|
name: Mapped[str] = mapped_column(String(200))
|
|
status: Mapped[str] = mapped_column(String(20), default="active", server_default="active")
|
|
settings: Mapped[dict[str, object]] = mapped_column(JSONB, default=dict, server_default="{}")
|
|
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
|
)
|
|
deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), default=None)
|