import uuid from datetime import datetime from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Text, func from sqlalchemy.orm import Mapped, mapped_column from .db import Base def uuid_str() -> str: return str(uuid.uuid4()) class Hub(Base): __tablename__ = "hubs" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=uuid_str) slug: Mapped[str] = mapped_column(String(120), unique=True, index=True) name: Mapped[str] = mapped_column(String(240)) domain: Mapped[str | None] = mapped_column(String(240)) hub_kind: Mapped[str | None] = mapped_column(String(80)) hub_family: Mapped[str | None] = mapped_column(String(80)) vsm_function: Mapped[str | None] = mapped_column(String(80)) vsm_system: Mapped[str | None] = mapped_column(String(80)) status: Mapped[str] = mapped_column(String(40), default="active") description: Mapped[str | None] = mapped_column(Text()) body_json: Mapped[str] = mapped_column(Text(), 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() ) class HubCapabilityManifest(Base): __tablename__ = "hub_capability_manifests" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=uuid_str) hub_id: Mapped[str | None] = mapped_column(String(36), ForeignKey("hubs.id"), index=True) hub_slug: Mapped[str | None] = mapped_column(String(120), index=True) manifest_version: Mapped[str] = mapped_column(String(40), default="0.1.0") status: Mapped[str] = mapped_column(String(40), default="draft") body_json: Mapped[str] = mapped_column(Text()) 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() ) class ApiConsumer(Base): __tablename__ = "api_consumers" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=uuid_str) slug: Mapped[str | None] = mapped_column(String(120), unique=True, index=True) name: Mapped[str] = mapped_column(String(240), index=True) description: Mapped[str | None] = mapped_column(Text()) hub_capability_manifest_id: Mapped[str | None] = mapped_column(String(36), index=True) rate_limit_per_minute: Mapped[int | None] = mapped_column(Integer()) quota_per_day: Mapped[int | None] = mapped_column(Integer()) key_prefix: Mapped[str | None] = mapped_column(String(32)) key_hash: Mapped[str | None] = mapped_column(String(255)) status: Mapped[str] = mapped_column(String(40), default="active") body_json: Mapped[str] = mapped_column(Text(), default="{}") created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) class ApiKey(Base): __tablename__ = "api_keys" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=uuid_str) api_consumer_id: Mapped[str] = mapped_column( String(36), ForeignKey("api_consumers.id"), index=True ) key_prefix: Mapped[str] = mapped_column(String(32), index=True) key_hash: Mapped[str] = mapped_column(String(255), unique=True) scopes: Mapped[str | None] = mapped_column(Text()) status: Mapped[str] = mapped_column(String(40), default="active") created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) class Widget(Base): __tablename__ = "widgets" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=uuid_str) hub_id: Mapped[str] = mapped_column(String(36), ForeignKey("hubs.id"), index=True) name: Mapped[str] = mapped_column(String(240)) widget_type: Mapped[str | None] = mapped_column(String(120), index=True) capability_ref: Mapped[str | None] = mapped_column(String(240), index=True) view_context: Mapped[str | None] = mapped_column(String(500)) policy_scope: Mapped[str | None] = mapped_column(String(120)) status: Mapped[str] = mapped_column(String(40), default="active") body_json: Mapped[str] = mapped_column(Text(), default="{}") created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) class InteractionEvent(Base): __tablename__ = "interaction_events" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=uuid_str) widget_id: Mapped[str] = mapped_column(String(36), ForeignKey("widgets.id"), index=True) event_type: Mapped[str] = mapped_column(String(160), index=True) view_context: Mapped[str | None] = mapped_column(String(500)) metadata_json: Mapped[str] = mapped_column(Text(), default="{}") body_json: Mapped[str] = mapped_column(Text(), default="{}") created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) class MigrationRun(Base): __tablename__ = "migration_runs" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=uuid_str) source: Mapped[str] = mapped_column(String(120), index=True) schema_version: Mapped[str] = mapped_column(String(80)) bundle_sha256: Mapped[str] = mapped_column(String(64), index=True) dry_run: Mapped[bool] = mapped_column(Boolean(), default=False) status: Mapped[str] = mapped_column(String(40), default="imported") counts_json: Mapped[str] = mapped_column(Text(), default="{}") diagnostics_json: Mapped[str] = mapped_column(Text(), default="{}") created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())