""" Developer Models — Webhook integrations, webhook delivery logs, and API call audit metrics. """ import uuid from datetime import datetime from typing import Optional from sqlalchemy import String, Boolean, Text, Integer, Index, ForeignKey from sqlalchemy.dialects.postgresql import UUID, JSONB from sqlalchemy.orm import Mapped, mapped_column from app.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin class WebhookEndpoint(UUIDPrimaryKeyMixin, TimestampMixin, Base): """Developer registered HTTP webhook listeners.""" __tablename__ = "webhook_endpoints" __table_args__ = ( Index("ix_webhook_endpoints_user_id", "user_id"), ) user_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, ) url: Mapped[str] = mapped_column(Text, nullable=False) secret_key: Mapped[str] = mapped_column(String(255), nullable=False) subscribed_events: Mapped[dict] = mapped_column(JSONB, default=list, nullable=False) # ['model.trained', 'dataset.uploaded'] is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) def __repr__(self) -> str: return f"" class WebhookDelivery(UUIDPrimaryKeyMixin, Base): """Webhook HTTP dispatch attempt log.""" __tablename__ = "webhook_deliveries" __table_args__ = ( Index("ix_webhook_deliveries_webhook_id", "webhook_id"), ) webhook_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("webhook_endpoints.id", ondelete="CASCADE"), nullable=False, ) event_type: Mapped[str] = mapped_column(String(100), nullable=False) payload_json: Mapped[dict] = mapped_column(JSONB, nullable=False) response_status_code: Mapped[Optional[int]] = mapped_column(Integer, nullable=True) response_body: Mapped[Optional[str]] = mapped_column(Text, nullable=True) duration_ms: Mapped[int] = mapped_column(Integer, default=0, nullable=False) is_success: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) delivered_at: Mapped[datetime] = mapped_column(server_default="now()", nullable=False) def __repr__(self) -> str: return f"" class APICallLog(UUIDPrimaryKeyMixin, Base): """API request metric and rate limit log.""" __tablename__ = "api_call_logs" __table_args__ = ( Index("ix_api_call_logs_user_id", "user_id"), Index("ix_api_call_logs_api_key_id", "api_key_id"), ) user_id: Mapped[Optional[uuid.UUID]] = mapped_column( UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=True, ) api_key_id: Mapped[Optional[uuid.UUID]] = mapped_column( UUID(as_uuid=True), ForeignKey("api_keys.id", ondelete="SET NULL"), nullable=True, ) endpoint: Mapped[str] = mapped_column(String(255), nullable=False) http_method: Mapped[str] = mapped_column(String(10), nullable=False) status_code: Mapped[int] = mapped_column(Integer, nullable=False) response_time_ms: Mapped[int] = mapped_column(Integer, nullable=False) ip_address: Mapped[Optional[str]] = mapped_column(String(45), nullable=True) created_at: Mapped[datetime] = mapped_column(server_default="now()", nullable=False) def __repr__(self) -> str: return f""