state-hub/api/models/managed_repo.py
tegwick 8988a093f2
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Multi-Context Image / build-and-push (push) Successful in 24s
feat: persist repository rename identity
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a049a4-ee9f-78e1-9d66-2cb0f9bea3e3
2026-08-28 22:08:21 +02:00

73 lines
3.3 KiB
Python

import uuid
from datetime import date, datetime
from sqlalchemy import Date, DateTime, ForeignKey, String, Text
from sqlalchemy.dialects.postgresql import ARRAY, JSONB, UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from api.models.base import Base, TimestampMixin, new_uuid
class ManagedRepo(Base, TimestampMixin):
__tablename__ = "managed_repos"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), primary_key=True, default=new_uuid
)
domain_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), ForeignKey("domains.id", ondelete="RESTRICT"), nullable=False, index=True
)
slug: Mapped[str] = mapped_column(String(100), unique=True, nullable=False, index=True)
name: Mapped[str] = mapped_column(String(200), nullable=False)
local_path: Mapped[str | None] = mapped_column(Text, nullable=True)
host_paths: Mapped[dict] = mapped_column(JSONB, nullable=False, default=dict, server_default="{}")
remote_url: Mapped[str | None] = mapped_column(Text, nullable=True)
description: Mapped[str | None] = mapped_column(Text, nullable=True)
status: Mapped[str] = mapped_column(String(20), nullable=False, default="active")
topic_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True), ForeignKey("topics.id", ondelete="SET NULL"), nullable=True
)
git_fingerprint: Mapped[str | None] = mapped_column(String(40), nullable=True, index=True)
sbom_source: Mapped[str | None] = mapped_column(Text, nullable=True)
last_sbom_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True
)
last_state_synced_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True
)
category: Mapped[str | None] = mapped_column(String(50), nullable=True)
secondary_domains: Mapped[list[str] | None] = mapped_column(ARRAY(Text), nullable=True)
capability_tags: Mapped[list[str] | None] = mapped_column(ARRAY(Text), nullable=True)
business_stake: Mapped[list[str] | None] = mapped_column(ARRAY(Text), nullable=True)
business_mechanics: Mapped[list[str] | None] = mapped_column(ARRAY(Text), nullable=True)
classified_at: Mapped[date | None] = mapped_column(Date, nullable=True)
classified_by: Mapped[str | None] = mapped_column(String(50), nullable=True)
standard_version: Mapped[str | None] = mapped_column(String(20), nullable=True)
domain: Mapped["Domain"] = relationship( # noqa: F821
"Domain", back_populates="repos", lazy="selectin"
)
goals: Mapped[list["RepoGoal"]] = relationship( # noqa: F821
"RepoGoal", back_populates="repo", lazy="selectin"
)
forge_identity: Mapped["RepositoryForgeIdentity | None"] = relationship( # noqa: F821
"RepositoryForgeIdentity",
back_populates="repo",
lazy="selectin",
uselist=False,
)
slug_records: Mapped[list["RepositorySlug"]] = relationship( # noqa: F821
"RepositorySlug", back_populates="repo", lazy="selectin"
)
rename_operations: Mapped[list["RepositoryRenameOperation"]] = relationship( # noqa: F821
"RepositoryRenameOperation", back_populates="repo", lazy="selectin"
)
@property
def domain_slug(self) -> str:
return self.domain.slug if self.domain is not None else ""