import uuid
from datetime import datetime

from sqlalchemy import (
    JSON,
    BigInteger,
    Boolean,
    CheckConstraint,
    DateTime,
    ForeignKey,
    ForeignKeyConstraint,
    Index,
    Integer,
    LargeBinary,
    String,
    Text,
    UniqueConstraint,
    Uuid,
    text,
)
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy.sql import func

JSONType = JSON().with_variant(JSONB, "postgresql")


class Base(DeclarativeBase):
    pass


class TimestampMixin:
    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 Workspace(Base, TimestampMixin):
    __tablename__ = "workspaces"
    __table_args__ = (CheckConstraint("audit_sequence >= 0", name="ck_workspace_audit_sequence"),)
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    name: Mapped[str] = mapped_column(String(160))
    timezone: Mapped[str] = mapped_column(String(80), default="UTC")
    audit_sequence: Mapped[int] = mapped_column(Integer, default=0)
    audit_head_hash: Mapped[bytes | None] = mapped_column(LargeBinary(32))


class User(Base, TimestampMixin):
    __tablename__ = "users"
    __table_args__ = (
        CheckConstraint("auth_version > 0", name="ck_user_auth_version"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    email: Mapped[str] = mapped_column(String(320), unique=True)
    password_hash: Mapped[str] = mapped_column(String(255))
    display_name: Mapped[str] = mapped_column(String(160))
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)
    auth_version: Mapped[int] = mapped_column(Integer, default=1)
    password_changed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    mfa_secret_ciphertext: Mapped[bytes | None] = mapped_column(LargeBinary)
    mfa_key_version: Mapped[int | None] = mapped_column(Integer)
    mfa_enabled_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    mfa_pending_ciphertext: Mapped[bytes | None] = mapped_column(LargeBinary)
    mfa_pending_key_version: Mapped[int | None] = mapped_column(Integer)
    mfa_pending_expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    mfa_last_used_step: Mapped[int | None] = mapped_column(BigInteger)


class InstallationState(Base):
    __tablename__ = "installation_state"
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    owner_setup_completed: Mapped[bool] = mapped_column(Boolean, default=False)
    completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))


class DeviceSession(Base):
    __tablename__ = "device_sessions"
    __table_args__ = (
        Index("ix_session_workspace_user", "workspace_id", "user_id"),
        ForeignKeyConstraint(
            ["workspace_id", "user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_session_membership_identity",
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    user_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    token_hash: Mapped[str] = mapped_column(String(64), unique=True)
    csrf_hash: Mapped[str] = mapped_column(String(64))
    device_name: Mapped[str | None] = mapped_column(String(160))
    user_agent: Mapped[str | None] = mapped_column(String(500))
    ip_hash: Mapped[str | None] = mapped_column(String(64))
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    last_seen_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
    idle_expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
    last_rotated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
    session_version: Mapped[int] = mapped_column(Integer, default=1)
    revoked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))


class LoginEvent(Base):
    __tablename__ = "login_events"
    __table_args__ = (Index("ix_login_workspace_created", "workspace_id", "created_at"),)
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID | None] = mapped_column(ForeignKey("workspaces.id"), index=True)
    user_id: Mapped[uuid.UUID | None] = mapped_column(ForeignKey("users.id"), index=True)
    email_hash: Mapped[str] = mapped_column(String(64))
    successful: Mapped[bool] = mapped_column(Boolean)
    reason: Mapped[str] = mapped_column(String(80))
    ip_hash: Mapped[str | None] = mapped_column(String(64))
    user_agent: Mapped[str | None] = mapped_column(String(500))
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())


class PasswordResetToken(Base):
    __tablename__ = "password_reset_tokens"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_reset_membership_identity",
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    user_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    token_hash: Mapped[str] = mapped_column(String(64), unique=True)
    expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
    used_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())


class MfaRecoveryCode(Base):
    __tablename__ = "mfa_recovery_codes"
    __table_args__ = (
        Index("ix_mfa_recovery_user_used", "user_id", "used_at"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    user_id: Mapped[uuid.UUID] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), index=True
    )
    code_hash: Mapped[str] = mapped_column(String(64), unique=True)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    used_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))


class WorkspaceMembership(Base, TimestampMixin):
    __tablename__ = "workspace_memberships"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_membership_workspace_id"),
        UniqueConstraint("workspace_id", "user_id", name="uq_membership_workspace_user"),
        CheckConstraint(
            "status IN ('invited','active','suspended','revoked')",
            name="ck_membership_status",
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    user_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("users.id"), index=True)
    status: Mapped[str] = mapped_column(String(32), default="active")


class Role(Base, TimestampMixin):
    __tablename__ = "roles"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_role_workspace_id"),
        UniqueConstraint("workspace_id", "name", name="uq_role_workspace_name"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    name: Mapped[str] = mapped_column(String(80))
    is_system: Mapped[bool] = mapped_column(Boolean, default=False)


class Permission(Base):
    __tablename__ = "permissions"
    key: Mapped[str] = mapped_column(String(120), primary_key=True)
    description: Mapped[str] = mapped_column(String(255))


class RolePermission(Base):
    __tablename__ = "role_permissions"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "role_id"],
            ["roles.workspace_id", "roles.id"],
            name="fk_role_permission_workspace_role",
        ),
    )
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
    role_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
    permission_key: Mapped[str] = mapped_column(ForeignKey("permissions.key"), primary_key=True)


class MembershipRole(Base):
    __tablename__ = "membership_roles"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "membership_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.id"],
            name="fk_membership_role_workspace_membership",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "role_id"],
            ["roles.workspace_id", "roles.id"],
            name="fk_membership_role_workspace_role",
        ),
    )
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
    membership_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
    role_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)


class ApprovalRequest(Base, TimestampMixin):
    __tablename__ = "approval_requests"
    __table_args__ = (
        Index("ix_approval_workspace_status", "workspace_id", "status"),
        Index("uq_approval_workspace_action", "workspace_id", "action_id", unique=True),
        ForeignKeyConstraint(
            ["workspace_id", "decided_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_approval_decider_membership",
        ),
        CheckConstraint("risk IN ('low','medium','high')", name="ck_approval_risk"),
        CheckConstraint(
            "status IN ('pending','approved','rejected','expired')",
            name="ck_approval_status",
        ),
        CheckConstraint(
            "(status = 'pending' AND decided_at IS NULL AND decided_by_user_id IS NULL) OR "
            "(status IN ('approved','rejected') AND decided_at IS NOT NULL AND "
            "decided_by_user_id IS NOT NULL) OR "
            "(status = 'expired' AND decided_at IS NOT NULL)",
            name="ck_approval_decision_state",
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    action_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    requested_by_type: Mapped[str] = mapped_column(String(32))
    requested_by_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    permission: Mapped[str] = mapped_column(ForeignKey("permissions.key"))
    risk: Mapped[str] = mapped_column(String(16))
    canonical_payload_hash: Mapped[str] = mapped_column(String(64))
    payload: Mapped[dict] = mapped_column(JSONType)
    status: Mapped[str] = mapped_column(String(24), default="pending")
    expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
    decided_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    decided_by_user_id: Mapped[uuid.UUID | None] = mapped_column(Uuid)


class IdempotencyRecord(Base):
    __tablename__ = "idempotency_records"
    __table_args__ = (
        Index("uq_idempotency_workspace_key", "workspace_id", "key", unique=True),
        CheckConstraint(
            "status IN ('in_progress','completed','failed','unknown')",
            name="ck_idempotency_status",
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    key: Mapped[str] = mapped_column(String(180))
    request_hash: Mapped[str] = mapped_column(String(64))
    status: Mapped[str] = mapped_column(String(24))
    response_status: Mapped[int | None] = mapped_column(Integer)
    response_body: Mapped[dict | None] = mapped_column(JSONType)
    expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))


class AuditEvent(Base):
    __tablename__ = "audit_events"
    __table_args__ = (
        Index("ix_audit_workspace_created", "workspace_id", "created_at"),
        UniqueConstraint("workspace_id", "sequence", name="uq_audit_workspace_sequence"),
        CheckConstraint("sequence > 0", name="ck_audit_sequence"),
        CheckConstraint(
            "(sequence = 1 AND previous_hash IS NULL) OR "
            "(sequence > 1 AND previous_hash IS NOT NULL)",
            name="ck_audit_predecessor",
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    sequence: Mapped[int] = mapped_column(Integer)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    event_type: Mapped[str] = mapped_column(String(120))
    actor_type: Mapped[str] = mapped_column(String(32))
    actor_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    request_id: Mapped[str | None] = mapped_column(String(80))
    execution_id: Mapped[uuid.UUID | None] = mapped_column(Uuid)
    data: Mapped[dict] = mapped_column(JSONType)
    previous_hash: Mapped[bytes | None] = mapped_column(LargeBinary(32))
    event_hash: Mapped[bytes] = mapped_column(LargeBinary(32), unique=True)


class AIModelProfile(Base, TimestampMixin):
    __tablename__ = "ai_model_profiles"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_model_profile_workspace_id"),
        UniqueConstraint(
            "workspace_id", "profile_key", name="uq_model_profile_workspace_key"
        ),
        ForeignKeyConstraint(
            ["workspace_id", "created_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_model_profile_creator",
        ),
        CheckConstraint("provider IN ('openai')", name="ck_model_profile_provider"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    created_by_user_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    profile_key: Mapped[str] = mapped_column(String(80))
    display_name: Mapped[str] = mapped_column(String(160))
    provider: Mapped[str] = mapped_column(String(40))
    model_id: Mapped[str] = mapped_column(String(160))
    enabled: Mapped[bool] = mapped_column(Boolean, default=True)
    capabilities: Mapped[list[str]] = mapped_column(JSONType, default=list)


class Agent(Base, TimestampMixin):
    __tablename__ = "agents"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_agent_workspace_id"),
        UniqueConstraint("workspace_id", "name", name="uq_agent_workspace_name"),
        ForeignKeyConstraint(
            ["workspace_id", "created_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_agent_creator_membership",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "manager_agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_agent_manager",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "escalation_agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_agent_escalation",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "computer_id"],
            ["computers.workspace_id", "computers.id"],
            name="fk_agent_computer",
        ),
        UniqueConstraint(
            "workspace_id", "computer_id", name="uq_agent_dedicated_computer"
        ),
        CheckConstraint(
            "status IN ('active','disabled','archived')", name="ck_agent_status"
        ),
        CheckConstraint("autonomy_level BETWEEN 0 AND 5", name="ck_agent_autonomy"),
        CheckConstraint(
            "computer_autonomy BETWEEN 0 AND 5", name="ck_agent_computer_autonomy"
        ),
        CheckConstraint(
            "system_privilege IN ('restricted','standard_user','administrator','full_system')",
            name="ck_agent_system_privilege",
        ),
        CheckConstraint(
            "computer_required = false OR computer_id IS NOT NULL",
            name="ck_agent_required_computer",
        ),
        CheckConstraint(
            "status != 'active' OR computer_id IS NOT NULL",
            name="ck_active_agent_has_computer",
        ),
        CheckConstraint(
            "budget_limit_minor IS NULL OR budget_limit_minor >= 0",
            name="ck_agent_budget_limit",
        ),
        CheckConstraint(
            "execution_limit IS NULL OR execution_limit > 0",
            name="ck_agent_execution_limit",
        ),
        CheckConstraint("version > 0", name="ck_agent_version"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    created_by_user_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    name: Mapped[str] = mapped_column(String(160))
    description: Mapped[str] = mapped_column(String(1000), default="")
    purpose: Mapped[str] = mapped_column(Text, default="")
    status: Mapped[str] = mapped_column(String(24), default="disabled")
    autonomy_level: Mapped[int] = mapped_column(Integer, default=1)
    computer_required: Mapped[bool] = mapped_column(Boolean, default=False)
    computer_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, index=True)
    system_privilege: Mapped[str] = mapped_column(String(24), default="standard_user")
    computer_autonomy: Mapped[int] = mapped_column(Integer, default=1)
    computer_network_policy: Mapped[dict] = mapped_column(JSONType, default=dict)
    computer_file_policy: Mapped[dict] = mapped_column(JSONType, default=dict)
    preferred_model: Mapped[str | None] = mapped_column(String(160))
    fallback_model: Mapped[str | None] = mapped_column(String(160))
    manager_agent_id: Mapped[uuid.UUID | None] = mapped_column(Uuid)
    escalation_agent_id: Mapped[uuid.UUID | None] = mapped_column(Uuid)
    budget_limit_minor: Mapped[int | None] = mapped_column(Integer)
    budget_currency: Mapped[str] = mapped_column(String(3), default="USD")
    execution_limit: Mapped[int | None] = mapped_column(Integer)
    version: Mapped[int] = mapped_column(Integer, default=1)


class ComputerTemplate(Base, TimestampMixin):
    __tablename__ = "computer_templates"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_computer_template_workspace_id"),
        UniqueConstraint(
            "workspace_id", "template_key", name="uq_computer_template_workspace_key"
        ),
        CheckConstraint("os_family IN ('linux','windows')", name="ck_template_os_family"),
        CheckConstraint(
            "status IN ('available','unconfigured','disabled')", name="ck_template_status"
        ),
        CheckConstraint("minimum_cpu >= 1", name="ck_template_minimum_cpu"),
        CheckConstraint("minimum_memory_mb >= 512", name="ck_template_minimum_memory"),
        CheckConstraint("minimum_disk_gb >= 10", name="ck_template_minimum_disk"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    template_key: Mapped[str] = mapped_column(String(80))
    name: Mapped[str] = mapped_column(String(160))
    os_family: Mapped[str] = mapped_column(String(16))
    os_distribution: Mapped[str] = mapped_column(String(80))
    os_version: Mapped[str] = mapped_column(String(80))
    browser: Mapped[str] = mapped_column(String(40), default="chromium")
    provider_template_ref: Mapped[str | None] = mapped_column(String(255))
    image_digest: Mapped[str | None] = mapped_column(String(160))
    minimum_cpu: Mapped[int] = mapped_column(Integer)
    minimum_memory_mb: Mapped[int] = mapped_column(Integer)
    minimum_disk_gb: Mapped[int] = mapped_column(Integer)
    windows_license_required: Mapped[bool] = mapped_column(Boolean, default=False)
    status: Mapped[str] = mapped_column(String(24), default="unconfigured")


class Computer(Base, TimestampMixin):
    __tablename__ = "computers"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_computer_workspace_id"),
        UniqueConstraint("workspace_id", "name", name="uq_computer_workspace_name"),
        UniqueConstraint(
            "workspace_id", "provider_resource_id", name="uq_computer_provider_resource"
        ),
        ForeignKeyConstraint(
            ["workspace_id", "template_id"],
            ["computer_templates.workspace_id", "computer_templates.id"],
            name="fk_computer_template",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "created_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_computer_creator",
        ),
        CheckConstraint("os_family IN ('linux','windows')", name="ck_computer_os_family"),
        CheckConstraint(
            "status IN ('unconfigured','pending','provisioning','starting','running','idle',"
            "'suspending','suspended','stopping','stopped','restarting','recovering','failed',"
            "'destroying','destroyed')",
            name="ck_computer_status",
        ),
        CheckConstraint(
            "desired_state IN ('running','suspended','stopped','destroyed')",
            name="ck_computer_desired_state",
        ),
        CheckConstraint(
            "system_privilege IN ('restricted','standard_user','administrator','full_system')",
            name="ck_computer_system_privilege",
        ),
        CheckConstraint(
            "start_policy IN ('always_running','start_when_needed','scheduled','manual')",
            name="ck_computer_start_policy",
        ),
        CheckConstraint("cpu_cores BETWEEN 1 AND 64", name="ck_computer_cpu"),
        CheckConstraint(
            "memory_mb BETWEEN 512 AND 524288", name="ck_computer_memory"
        ),
        CheckConstraint("disk_gb BETWEEN 10 AND 16384", name="ck_computer_disk"),
        CheckConstraint("version > 0", name="ck_computer_version"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    template_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    created_by_user_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    name: Mapped[str] = mapped_column(String(160))
    os_family: Mapped[str] = mapped_column(String(16))
    os_distribution: Mapped[str] = mapped_column(String(80))
    os_version: Mapped[str] = mapped_column(String(80))
    compute_provider: Mapped[str] = mapped_column(String(40), default="unconfigured")
    provider_resource_id: Mapped[str | None] = mapped_column(String(255))
    cpu_cores: Mapped[int] = mapped_column(Integer)
    memory_mb: Mapped[int] = mapped_column(Integer)
    disk_gb: Mapped[int] = mapped_column(Integer)
    gpu: Mapped[str | None] = mapped_column(String(120))
    browser: Mapped[str] = mapped_column(String(40), default="chromium")
    persistent_disk: Mapped[bool] = mapped_column(Boolean, default=True)
    system_privilege: Mapped[str] = mapped_column(String(24), default="standard_user")
    start_policy: Mapped[str] = mapped_column(String(24), default="start_when_needed")
    status: Mapped[str] = mapped_column(String(24), default="unconfigured")
    desired_state: Mapped[str] = mapped_column(String(16), default="stopped")
    ip_address: Mapped[str | None] = mapped_column(String(64))
    control_endpoint: Mapped[str | None] = mapped_column(String(255))
    browser_status: Mapped[str | None] = mapped_column(String(40))
    current_application: Mapped[str | None] = mapped_column(String(160))
    current_task: Mapped[str | None] = mapped_column(String(500))
    provider_error_code: Mapped[str | None] = mapped_column(String(80))
    provider_error_message: Mapped[str | None] = mapped_column(String(500))
    last_seen_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    stopped_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    version: Mapped[int] = mapped_column(Integer, default=1)


class ComputerNetworkPolicy(Base, TimestampMixin):
    __tablename__ = "computer_network_policies"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "computer_id"],
            ["computers.workspace_id", "computers.id"],
            name="fk_computer_network_policy_computer",
            ondelete="CASCADE",
        ),
        UniqueConstraint(
            "workspace_id", "computer_id", name="uq_computer_network_policy_computer"
        ),
        CheckConstraint(
            "host_management_access = false", name="ck_computer_network_no_host_management"
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    computer_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    internet_access: Mapped[bool] = mapped_column(Boolean, default=True)
    lan_access: Mapped[bool] = mapped_column(Boolean, default=False)
    platform_api_access: Mapped[bool] = mapped_column(Boolean, default=True)
    other_agent_networks: Mapped[bool] = mapped_column(Boolean, default=False)
    host_management_access: Mapped[bool] = mapped_column(Boolean, default=False)
    allowed_domains: Mapped[list] = mapped_column(JSONType, default=list)
    blocked_domains: Mapped[list] = mapped_column(JSONType, default=list)
    version: Mapped[int] = mapped_column(Integer, default=1)


class WorkspaceComputerLimit(Base, TimestampMixin):
    __tablename__ = "workspace_computer_limits"
    __table_args__ = (
        CheckConstraint("maximum_computers >= 1", name="ck_computer_limit_count"),
        CheckConstraint("maximum_running_computers >= 1", name="ck_computer_limit_running"),
        CheckConstraint("maximum_cpu_per_computer >= 1", name="ck_computer_limit_cpu"),
        CheckConstraint("maximum_memory_mb >= 512", name="ck_computer_limit_memory"),
        CheckConstraint("maximum_disk_gb >= 10", name="ck_computer_limit_disk"),
    )
    workspace_id: Mapped[uuid.UUID] = mapped_column(
        ForeignKey("workspaces.id"), primary_key=True
    )
    maximum_computers: Mapped[int] = mapped_column(Integer, default=10)
    maximum_running_computers: Mapped[int] = mapped_column(Integer, default=4)
    maximum_cpu_per_computer: Mapped[int] = mapped_column(Integer, default=8)
    maximum_memory_mb: Mapped[int] = mapped_column(Integer, default=16384)
    maximum_disk_gb: Mapped[int] = mapped_column(Integer, default=200)


class ComputerOperation(Base):
    __tablename__ = "computer_operations"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_computer_operation_workspace_id"),
        UniqueConstraint(
            "workspace_id", "idempotency_key", name="uq_computer_operation_idempotency"
        ),
        ForeignKeyConstraint(
            ["workspace_id", "computer_id"],
            ["computers.workspace_id", "computers.id"],
            name="fk_computer_operation_computer",
            ondelete="CASCADE",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "requested_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_computer_operation_requester",
        ),
        CheckConstraint(
            "operation IN ('create','start','stop','restart','pause','resume','destroy',"
            "'snapshot','restore','resize','refresh')",
            name="ck_computer_operation_name",
        ),
        CheckConstraint(
            "status IN ('pending','running','succeeded','failed','blocked','unknown')",
            name="ck_computer_operation_status",
        ),
        CheckConstraint("risk IN ('low','medium','high')", name="ck_computer_operation_risk"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    computer_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    requested_by_user_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    operation: Mapped[str] = mapped_column(String(24))
    risk: Mapped[str] = mapped_column(String(16))
    idempotency_key: Mapped[str] = mapped_column(String(180))
    request_hash: Mapped[str] = mapped_column(String(64))
    request_redacted: Mapped[dict] = mapped_column(JSONType, default=dict)
    status: Mapped[str] = mapped_column(String(24), default="pending")
    provider_request_id: Mapped[str | None] = mapped_column(String(160))
    verification: Mapped[dict | None] = mapped_column(JSONType)
    error_code: Mapped[str | None] = mapped_column(String(80))
    error_message: Mapped[str | None] = mapped_column(String(500))
    started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())


class ComputerSnapshot(Base):
    __tablename__ = "computer_snapshots"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_computer_snapshot_workspace_id"),
        UniqueConstraint(
            "workspace_id", "provider_snapshot_id", name="uq_computer_provider_snapshot"
        ),
        ForeignKeyConstraint(
            ["workspace_id", "computer_id"],
            ["computers.workspace_id", "computers.id"],
            name="fk_computer_snapshot_computer",
            ondelete="CASCADE",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "created_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_computer_snapshot_creator",
        ),
        CheckConstraint(
            "status IN ('creating','ready','restoring','failed','deleted')",
            name="ck_computer_snapshot_status",
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    computer_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    created_by_user_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    name: Mapped[str] = mapped_column(String(160))
    provider_snapshot_id: Mapped[str | None] = mapped_column(String(255))
    status: Mapped[str] = mapped_column(String(24), default="creating")
    includes_memory: Mapped[bool] = mapped_column(Boolean, default=False)
    automatic: Mapped[bool] = mapped_column(Boolean, default=False)
    metadata_redacted: Mapped[dict] = mapped_column(JSONType, default=dict)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())


class ComputerMetric(Base):
    __tablename__ = "computer_metrics"
    __table_args__ = (
        Index("ix_computer_metric_computer_recorded", "computer_id", "recorded_at"),
        ForeignKeyConstraint(
            ["workspace_id", "computer_id"],
            ["computers.workspace_id", "computers.id"],
            name="fk_computer_metric_computer",
            ondelete="CASCADE",
        ),
        CheckConstraint("cpu_percent BETWEEN 0 AND 100", name="ck_computer_metric_cpu"),
        CheckConstraint("memory_used_mb >= 0", name="ck_computer_metric_memory"),
        CheckConstraint("disk_used_gb >= 0", name="ck_computer_metric_disk"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    computer_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    cpu_percent: Mapped[int] = mapped_column(Integer)
    memory_used_mb: Mapped[int] = mapped_column(Integer)
    disk_used_gb: Mapped[int] = mapped_column(Integer)
    network_rx_bytes: Mapped[int] = mapped_column(BigInteger, default=0)
    network_tx_bytes: Mapped[int] = mapped_column(BigInteger, default=0)
    top_processes: Mapped[list] = mapped_column(JSONType, default=list)
    recorded_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())


class AgentVersion(Base):
    __tablename__ = "agent_versions"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_agent_version_agent",
            ondelete="CASCADE",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "created_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_agent_version_creator",
        ),
        UniqueConstraint(
            "workspace_id", "agent_id", "version_number", name="uq_agent_version_number"
        ),
        CheckConstraint("version_number > 0", name="ck_agent_version_number"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    agent_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    version_number: Mapped[int] = mapped_column(Integer)
    system_instructions: Mapped[str] = mapped_column(Text, default="")
    personality: Mapped[str] = mapped_column(Text, default="")
    config_snapshot: Mapped[dict] = mapped_column(JSONType)
    created_by_user_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())


class AgentPermission(Base):
    __tablename__ = "agent_permissions"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_agent_permission_agent",
            ondelete="CASCADE",
        ),
    )
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
    agent_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
    permission_key: Mapped[str] = mapped_column(
        ForeignKey("permissions.key"), primary_key=True
    )


class AgentTool(Base):
    __tablename__ = "agent_tools"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_agent_tool_agent",
            ondelete="CASCADE",
        ),
    )
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
    agent_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
    tool_name: Mapped[str] = mapped_column(String(120), primary_key=True)
    constraints: Mapped[dict] = mapped_column(JSONType, default=dict)


class AgentSchedule(Base):
    __tablename__ = "agent_schedules"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_agent_schedule_agent",
            ondelete="CASCADE",
        ),
        CheckConstraint("start_minute BETWEEN 0 AND 1439", name="ck_agent_schedule_start"),
        CheckConstraint("end_minute BETWEEN 1 AND 1440", name="ck_agent_schedule_end"),
        CheckConstraint("start_minute < end_minute", name="ck_agent_schedule_range"),
    )
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
    agent_id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True)
    timezone: Mapped[str] = mapped_column(String(80))
    working_days: Mapped[list] = mapped_column(JSONType)
    start_minute: Mapped[int] = mapped_column(Integer)
    end_minute: Mapped[int] = mapped_column(Integer)
    enabled: Mapped[bool] = mapped_column(Boolean, default=True)


class AgentDelegation(Base):
    __tablename__ = "agent_delegations"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "source_agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_delegation_source_agent",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "target_agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_delegation_target_agent",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "requested_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_delegation_requester",
        ),
        CheckConstraint(
            "status IN ('requested','accepted','running','succeeded','failed','cancelled')",
            name="ck_delegation_status",
        ),
        CheckConstraint(
            "source_agent_id <> target_agent_id", name="ck_delegation_distinct_agents"
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    source_agent_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    target_agent_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    requested_by_user_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    instruction: Mapped[str] = mapped_column(Text)
    instruction_hash: Mapped[str] = mapped_column(String(64))
    permission_scope: Mapped[list] = mapped_column(JSONType)
    status: Mapped[str] = mapped_column(String(24), default="requested")
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))


class Execution(Base):
    __tablename__ = "executions"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_execution_workspace_id"),
        Index("ix_execution_workspace_status_created", "workspace_id", "status", "created_at"),
        ForeignKeyConstraint(
            ["workspace_id", "requested_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_execution_requester_membership",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_execution_agent",
        ),
        CheckConstraint(
            "status IN ('planning','planned','awaiting_approval','running','succeeded',"
            "'failed','cancelled','blocked','unknown')",
            name="ck_execution_status",
        ),
        CheckConstraint("input_tokens >= 0", name="ck_execution_input_tokens"),
        CheckConstraint("output_tokens >= 0", name="ck_execution_output_tokens"),
        CheckConstraint("version > 0", name="ck_execution_version"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    requested_by_user_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    agent_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, index=True)
    instruction: Mapped[str] = mapped_column(Text)
    instruction_hash: Mapped[str] = mapped_column(String(64))
    status: Mapped[str] = mapped_column(String(32), default="planning")
    provider: Mapped[str | None] = mapped_column(String(40))
    model: Mapped[str | None] = mapped_column(String(160))
    provider_response_id: Mapped[str | None] = mapped_column(String(160))
    plan: Mapped[dict | None] = mapped_column(JSONType)
    output_summary: Mapped[str | None] = mapped_column(Text)
    error_code: Mapped[str | None] = mapped_column(String(80))
    input_tokens: Mapped[int] = mapped_column(Integer, default=0)
    output_tokens: Mapped[int] = mapped_column(Integer, default=0)
    stop_requested_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    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()
    )
    version: Mapped[int] = mapped_column(Integer, default=1)


class ExecutionStep(Base):
    __tablename__ = "execution_steps"
    __table_args__ = (
        UniqueConstraint(
            "workspace_id", "execution_id", "position",
            name="uq_execution_step_position",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "execution_id"],
            ["executions.workspace_id", "executions.id"],
            name="fk_execution_step_execution",
            ondelete="CASCADE",
        ),
        CheckConstraint("position >= 0", name="ck_execution_step_position"),
        CheckConstraint(
            "status IN ('pending','running','awaiting_approval','succeeded','failed',"
            "'cancelled','unknown')",
            name="ck_execution_step_status",
        ),
        CheckConstraint("risk IN ('low','medium','high')", name="ck_execution_step_risk"),
        CheckConstraint("access_type IN ('read','write')", name="ck_execution_step_access"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    execution_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    position: Mapped[int] = mapped_column(Integer)
    model_step_id: Mapped[str] = mapped_column(String(80))
    tool_name: Mapped[str] = mapped_column(String(120))
    permission: Mapped[str] = mapped_column(ForeignKey("permissions.key"))
    risk: Mapped[str] = mapped_column(String(16))
    access_type: Mapped[str] = mapped_column(String(16))
    arguments: Mapped[dict] = mapped_column(JSONType)
    concise_rationale: Mapped[str] = mapped_column(String(500))
    depends_on: Mapped[list] = mapped_column(JSONType)
    status: Mapped[str] = mapped_column(String(32), default="pending")
    checkpoint: Mapped[dict | None] = mapped_column(JSONType)
    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 ComputerProfile(Base, TimestampMixin):
    __tablename__ = "computer_profiles"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_computer_profile_workspace_id"),
        UniqueConstraint(
            "workspace_id", "profile_key", name="uq_computer_profile_workspace_key"
        ),
        UniqueConstraint(
            "workspace_id", "storage_key", name="uq_computer_profile_storage_key"
        ),
        UniqueConstraint(
            "workspace_id", "agent_id", name="uq_computer_profile_agent"
        ),
        ForeignKeyConstraint(
            ["workspace_id", "agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_computer_profile_agent",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "computer_id"],
            ["computers.workspace_id", "computers.id"],
            name="fk_computer_profile_computer",
        ),
        UniqueConstraint(
            "workspace_id", "computer_id", name="uq_computer_profile_computer"
        ),
        ForeignKeyConstraint(
            ["workspace_id", "created_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_computer_profile_creator",
        ),
        CheckConstraint(
            "status IN ('active','disabled','revoked')", name="ck_computer_profile_status"
        ),
        CheckConstraint(
            "retention_days BETWEEN 1 AND 3650", name="ck_computer_profile_retention"
        ),
        CheckConstraint("version > 0", name="ck_computer_profile_version"),
        CheckConstraint(
            "agent_id IS NOT NULL OR status = 'revoked'",
            name="ck_computer_profile_owner",
        ),
        CheckConstraint(
            "computer_id IS NOT NULL OR status = 'revoked'",
            name="ck_computer_profile_computer_owner",
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    agent_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, index=True)
    computer_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, index=True)
    created_by_user_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    profile_key: Mapped[str] = mapped_column(String(80))
    name: Mapped[str] = mapped_column(String(160))
    storage_key: Mapped[str] = mapped_column(String(64))
    status: Mapped[str] = mapped_column(String(24), default="active")
    retention_days: Mapped[int] = mapped_column(Integer, default=30)
    version: Mapped[int] = mapped_column(Integer, default=1)
    revoked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))


class WorkspaceControlState(Base):
    __tablename__ = "workspace_control_states"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "stopped_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_workspace_control_stopper",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "resumed_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_workspace_control_resumer",
        ),
        CheckConstraint("version > 0", name="ck_workspace_control_version"),
    )
    workspace_id: Mapped[uuid.UUID] = mapped_column(
        ForeignKey("workspaces.id"), primary_key=True
    )
    emergency_stopped: Mapped[bool] = mapped_column(Boolean, default=False)
    reason: Mapped[str | None] = mapped_column(String(500))
    stopped_by_user_id: Mapped[uuid.UUID | None] = mapped_column(Uuid)
    stopped_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    resumed_by_user_id: Mapped[uuid.UUID | None] = mapped_column(Uuid)
    resumed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    version: Mapped[int] = mapped_column(Integer, default=1)
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
    )


class ComputerSession(Base):
    __tablename__ = "computer_sessions"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_computer_session_workspace_id"),
        Index(
            "ix_computer_session_workspace_status_updated",
            "workspace_id", "status", "updated_at",
        ),
        Index(
            "uq_computer_active_session_profile",
            "workspace_id", "profile_id",
            unique=True,
            postgresql_where=text(
                "status IN ('starting','ready','ai_controlled','human_controlled',"
                "'awaiting_human','paused','recovering','stopping')"
            ),
            sqlite_where=text(
                "status IN ('starting','ready','ai_controlled','human_controlled',"
                "'awaiting_human','paused','recovering','stopping')"
            ),
        ),
        ForeignKeyConstraint(
            ["workspace_id", "requested_by_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_computer_session_requester",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "agent_id"],
            ["agents.workspace_id", "agents.id"],
            name="fk_computer_session_agent",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "execution_id"],
            ["executions.workspace_id", "executions.id"],
            name="fk_computer_session_execution",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "profile_id"],
            ["computer_profiles.workspace_id", "computer_profiles.id"],
            name="fk_computer_session_profile",
        ),
        CheckConstraint(
            "status IN ('starting','ready','ai_controlled','human_controlled',"
            "'awaiting_human','paused','recovering','stopping','stopped','failed')",
            name="ck_computer_session_status",
        ),
        CheckConstraint(
            "control_owner IN ('ai','human','system','none')",
            name="ck_computer_session_control_owner",
        ),
        CheckConstraint(
            "(status = 'human_controlled' AND control_owner = 'human') OR "
            "(status = 'ai_controlled' AND control_owner = 'ai') OR "
            "status NOT IN ('human_controlled','ai_controlled')",
            name="ck_computer_session_control_state",
        ),
        CheckConstraint("lease_version >= 0", name="ck_computer_session_lease_version"),
        CheckConstraint("version > 0", name="ck_computer_session_version"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    requested_by_user_id: Mapped[uuid.UUID] = mapped_column(Uuid)
    agent_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    execution_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, index=True)
    profile_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    task_summary: Mapped[str] = mapped_column(Text)
    status: Mapped[str] = mapped_column(String(32), default="starting")
    control_owner: Mapped[str] = mapped_column(String(16), default="system")
    worker_id: Mapped[str | None] = mapped_column(String(160))
    current_url: Mapped[str | None] = mapped_column(Text)
    active_tab_id: Mapped[str | None] = mapped_column(String(160))
    current_action_summary: Mapped[str | None] = mapped_column(String(500))
    upcoming_action_summary: Mapped[str | None] = mapped_column(String(500))
    failure_code: Mapped[str | None] = mapped_column(String(80))
    failure_message: Mapped[str | None] = mapped_column(String(500))
    lease_version: Mapped[int] = mapped_column(Integer, default=0)
    version: Mapped[int] = mapped_column(Integer, default=1)
    started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    last_active_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    paused_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    stopped_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    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 ComputerControlLease(Base):
    __tablename__ = "computer_control_leases"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "session_id"],
            ["computer_sessions.workspace_id", "computer_sessions.id"],
            name="fk_computer_lease_session",
            ondelete="CASCADE",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "actor_user_id"],
            ["workspace_memberships.workspace_id", "workspace_memberships.user_id"],
            name="fk_computer_lease_actor",
        ),
        UniqueConstraint(
            "workspace_id", "session_id", "fencing_token",
            name="uq_computer_lease_fencing_token",
        ),
        CheckConstraint("owner IN ('ai','human','system')", name="ck_computer_lease_owner"),
        CheckConstraint("fencing_token > 0", name="ck_computer_lease_fencing_token"),
        CheckConstraint(
            "released_at IS NULL OR released_at >= issued_at",
            name="ck_computer_lease_release_time",
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    session_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    owner: Mapped[str] = mapped_column(String(16))
    actor_user_id: Mapped[uuid.UUID | None] = mapped_column(Uuid)
    fencing_token: Mapped[int] = mapped_column(Integer)
    issued_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
    expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
    heartbeat_at: Mapped[datetime] = mapped_column(DateTime(timezone=True))
    released_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    release_reason: Mapped[str | None] = mapped_column(String(160))


class ComputerAction(Base):
    __tablename__ = "computer_actions"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_computer_action_workspace_id"),
        ForeignKeyConstraint(
            ["workspace_id", "session_id"],
            ["computer_sessions.workspace_id", "computer_sessions.id"],
            name="fk_computer_action_session",
            ondelete="CASCADE",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "execution_id"],
            ["executions.workspace_id", "executions.id"],
            name="fk_computer_action_execution",
        ),
        CheckConstraint(
            "actor_type IN ('user','agent','system')", name="ck_computer_action_actor_type"
        ),
        CheckConstraint(
            "risk IN ('low','medium','high')", name="ck_computer_action_risk"
        ),
        CheckConstraint(
            "access_type IN ('read','write','control')", name="ck_computer_action_access"
        ),
        CheckConstraint(
            "status IN ('pending','running','awaiting_approval','blocked','succeeded',"
            "'failed','cancelled','unknown')",
            name="ck_computer_action_status",
        ),
        CheckConstraint(
            "duration_ms IS NULL OR duration_ms >= 0", name="ck_computer_action_duration"
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    session_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    execution_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, index=True)
    actor_type: Mapped[str] = mapped_column(String(16))
    actor_id: Mapped[uuid.UUID | None] = mapped_column(Uuid)
    tool_name: Mapped[str] = mapped_column(String(160))
    parameters_redacted: Mapped[dict] = mapped_column(JSONType, default=dict)
    risk: Mapped[str] = mapped_column(String(16))
    access_type: Mapped[str] = mapped_column(String(16))
    action_intent_hash: Mapped[str | None] = mapped_column(String(64))
    status: Mapped[str] = mapped_column(String(32), default="pending")
    result_redacted: Mapped[dict | None] = mapped_column(JSONType)
    verification: Mapped[dict | None] = mapped_column(JSONType)
    error_code: Mapped[str | None] = mapped_column(String(80))
    duration_ms: Mapped[int | None] = mapped_column(Integer)
    started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())


class ComputerArtifact(Base):
    __tablename__ = "computer_artifacts"
    __table_args__ = (
        UniqueConstraint("workspace_id", "id", name="uq_computer_artifact_workspace_id"),
        UniqueConstraint(
            "workspace_id", "storage_key", name="uq_computer_artifact_storage_key"
        ),
        ForeignKeyConstraint(
            ["workspace_id", "session_id"],
            ["computer_sessions.workspace_id", "computer_sessions.id"],
            name="fk_computer_artifact_session",
            ondelete="CASCADE",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "action_id"],
            ["computer_actions.workspace_id", "computer_actions.id"],
            name="fk_computer_artifact_action",
        ),
        CheckConstraint(
            "kind IN ('screenshot','download','upload','log')", name="ck_computer_artifact_kind"
        ),
        CheckConstraint(
            "status IN ('quarantined','available','rejected','deleted','expired')",
            name="ck_computer_artifact_status",
        ),
        CheckConstraint("size_bytes >= 0", name="ck_computer_artifact_size"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    session_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    action_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, index=True)
    kind: Mapped[str] = mapped_column(String(24))
    status: Mapped[str] = mapped_column(String(24), default="quarantined")
    storage_key: Mapped[str] = mapped_column(String(255))
    sha256: Mapped[str] = mapped_column(String(64))
    mime_type: Mapped[str] = mapped_column(String(160))
    size_bytes: Mapped[int] = mapped_column(Integer)
    metadata_redacted: Mapped[dict] = mapped_column(JSONType, default=dict)
    expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())


class ComputerCheckpoint(Base):
    __tablename__ = "computer_checkpoints"
    __table_args__ = (
        ForeignKeyConstraint(
            ["workspace_id", "session_id"],
            ["computer_sessions.workspace_id", "computer_sessions.id"],
            name="fk_computer_checkpoint_session",
            ondelete="CASCADE",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "action_id"],
            ["computer_actions.workspace_id", "computer_actions.id"],
            name="fk_computer_checkpoint_action",
        ),
        ForeignKeyConstraint(
            ["workspace_id", "screenshot_artifact_id"],
            ["computer_artifacts.workspace_id", "computer_artifacts.id"],
            name="fk_computer_checkpoint_screenshot",
        ),
        CheckConstraint(
            "checkpoint_type IN ('session_started','before_action','after_action','takeover',"
            "'return_control','pause','recovery','failure','completion')",
            name="ck_computer_checkpoint_type",
        ),
        CheckConstraint("sequence > 0", name="ck_computer_checkpoint_sequence"),
        UniqueConstraint(
            "workspace_id", "session_id", "sequence",
            name="uq_computer_checkpoint_sequence",
        ),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    session_id: Mapped[uuid.UUID] = mapped_column(Uuid, index=True)
    action_id: Mapped[uuid.UUID | None] = mapped_column(Uuid)
    sequence: Mapped[int] = mapped_column(Integer)
    checkpoint_type: Mapped[str] = mapped_column(String(32))
    current_url: Mapped[str | None] = mapped_column(Text)
    active_tab_id: Mapped[str | None] = mapped_column(String(160))
    tabs: Mapped[list] = mapped_column(JSONType, default=list)
    state_redacted: Mapped[dict] = mapped_column(JSONType, default=dict)
    screenshot_artifact_id: Mapped[uuid.UUID | None] = mapped_column(Uuid)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())


class OutboxEvent(Base):
    __tablename__ = "outbox_events"
    __table_args__ = (
        Index("ix_outbox_unpublished", "published_at", "created_at"),
        CheckConstraint("schema_version > 0", name="ck_outbox_schema_version"),
        CheckConstraint("attempts >= 0", name="ck_outbox_attempts"),
    )
    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    workspace_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("workspaces.id"), index=True)
    topic: Mapped[str] = mapped_column(String(160))
    schema_version: Mapped[int] = mapped_column(Integer, default=1)
    payload: Mapped[dict] = mapped_column(JSONType)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    published_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    attempts: Mapped[int] = mapped_column(Integer, default=0)
    last_error: Mapped[str | None] = mapped_column(Text)
