Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a049a4-ee9f-78e1-9d66-2cb0f9bea3e3
292 lines
11 KiB
Python
292 lines
11 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import (
|
|
BigInteger,
|
|
Boolean,
|
|
CheckConstraint,
|
|
DateTime,
|
|
ForeignKey,
|
|
ForeignKeyConstraint,
|
|
Index,
|
|
String,
|
|
Text,
|
|
UniqueConstraint,
|
|
text,
|
|
)
|
|
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from api.models.base import Base, TimestampMixin, new_uuid
|
|
|
|
|
|
FORGE_IDENTITY_STATES = ("unverified", "verified")
|
|
REPOSITORY_SLUG_KINDS = ("canonical", "alias")
|
|
REPOSITORY_RENAME_PHASES = (
|
|
"draft",
|
|
"preflighted",
|
|
"forge-renamed",
|
|
"statehub-rebound",
|
|
"source-synced",
|
|
"consumers-verified",
|
|
"completed",
|
|
"rollback-preflight",
|
|
"rolled-back",
|
|
)
|
|
TERMINAL_REPOSITORY_RENAME_PHASES = ("completed", "rolled-back")
|
|
|
|
|
|
class RepositoryForgeIdentity(Base, TimestampMixin):
|
|
"""One explicitly verified (or explicitly unverified) Forge identity per repo."""
|
|
|
|
__tablename__ = "repository_forge_identities"
|
|
__table_args__ = (
|
|
UniqueConstraint("repo_id", name="uq_repository_forge_identities_repo_id"),
|
|
UniqueConstraint(
|
|
"id",
|
|
"repo_id",
|
|
"verification_state",
|
|
name="uq_repository_forge_identity_verified_ref",
|
|
),
|
|
UniqueConstraint(
|
|
"provider",
|
|
"forge_instance",
|
|
"forge_owner",
|
|
"forge_repository_id",
|
|
name="uq_repository_forge_identity_tuple",
|
|
),
|
|
CheckConstraint(
|
|
"verification_state IN ('unverified', 'verified')",
|
|
name="ck_repository_forge_identity_state",
|
|
),
|
|
CheckConstraint(
|
|
"forge_repository_id IS NULL OR forge_repository_id > 0",
|
|
name="ck_repository_forge_id_positive",
|
|
),
|
|
CheckConstraint(
|
|
"verification_state != 'verified' OR "
|
|
"(provider IS NOT NULL AND forge_instance IS NOT NULL "
|
|
"AND forge_owner IS NOT NULL AND forge_repository_id IS NOT NULL "
|
|
"AND verified_at IS NOT NULL AND verified_by IS NOT NULL)",
|
|
name="ck_repository_forge_verified_complete",
|
|
),
|
|
CheckConstraint(
|
|
"verification_state = 'verified' OR "
|
|
"(verified_at IS NULL AND verified_by IS NULL)",
|
|
name="ck_repository_forge_unverified_has_no_attestation",
|
|
),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True), primary_key=True, default=new_uuid
|
|
)
|
|
repo_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("managed_repos.id", ondelete="RESTRICT"),
|
|
nullable=False,
|
|
)
|
|
provider: Mapped[str | None] = mapped_column(String(40), nullable=True)
|
|
forge_instance: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
forge_owner: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
forge_repository_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
|
|
verification_state: Mapped[str] = mapped_column(
|
|
String(20), nullable=False, default="unverified", server_default="unverified"
|
|
)
|
|
verified_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
verified_by: Mapped[str | None] = mapped_column(String(160), nullable=True)
|
|
verification_evidence: Mapped[dict] = mapped_column(
|
|
JSONB, nullable=False, default=dict, server_default="{}"
|
|
)
|
|
|
|
repo: Mapped["ManagedRepo"] = relationship( # noqa: F821
|
|
"ManagedRepo", back_populates="forge_identity", lazy="selectin"
|
|
)
|
|
rename_operations: Mapped[list["RepositoryRenameOperation"]] = relationship(
|
|
"RepositoryRenameOperation",
|
|
back_populates="forge_identity",
|
|
lazy="selectin",
|
|
viewonly=True,
|
|
)
|
|
|
|
|
|
class RepositoryRenameOperation(Base, TimestampMixin):
|
|
"""Append-preserving journal for one phased canonical-coordinate change."""
|
|
|
|
__tablename__ = "repository_rename_operations"
|
|
__table_args__ = (
|
|
CheckConstraint(
|
|
"phase IN ('draft', 'preflighted', 'forge-renamed', "
|
|
"'statehub-rebound', 'source-synced', 'consumers-verified', "
|
|
"'completed', 'rollback-preflight', 'rolled-back')",
|
|
name="ck_repository_rename_phase",
|
|
),
|
|
CheckConstraint(
|
|
"old_slug != new_slug", name="ck_repository_rename_distinct_slugs"
|
|
),
|
|
CheckConstraint(
|
|
"expected_forge_repository_id > 0",
|
|
name="ck_repository_rename_forge_id_positive",
|
|
),
|
|
CheckConstraint(
|
|
"forge_identity_state = 'verified'",
|
|
name="ck_repository_rename_verified_identity",
|
|
),
|
|
CheckConstraint(
|
|
"phase = 'draft' OR preflighted_at IS NOT NULL",
|
|
name="ck_repository_rename_preflight_timestamp",
|
|
),
|
|
CheckConstraint(
|
|
"phase != 'completed' OR completed_at IS NOT NULL",
|
|
name="ck_repository_rename_completed_timestamp",
|
|
),
|
|
CheckConstraint(
|
|
"phase != 'rolled-back' OR rolled_back_at IS NOT NULL",
|
|
name="ck_repository_rename_rollback_timestamp",
|
|
),
|
|
Index(
|
|
"uq_repository_rename_active_repo",
|
|
"repo_id",
|
|
unique=True,
|
|
postgresql_where=text("phase NOT IN ('completed', 'rolled-back')"),
|
|
),
|
|
Index(
|
|
"uq_repository_rename_active_new_slug",
|
|
"new_slug",
|
|
unique=True,
|
|
postgresql_where=text("phase NOT IN ('completed', 'rolled-back')"),
|
|
),
|
|
Index(
|
|
"ix_repository_rename_phase", "phase"
|
|
),
|
|
ForeignKeyConstraint(
|
|
["forge_identity_id", "repo_id", "forge_identity_state"],
|
|
[
|
|
"repository_forge_identities.id",
|
|
"repository_forge_identities.repo_id",
|
|
"repository_forge_identities.verification_state",
|
|
],
|
|
name="fk_repository_rename_verified_identity",
|
|
ondelete="RESTRICT",
|
|
),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True), primary_key=True, default=new_uuid
|
|
)
|
|
repo_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("managed_repos.id", ondelete="RESTRICT"),
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
forge_identity_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True), nullable=False
|
|
)
|
|
forge_identity_state: Mapped[str] = mapped_column(
|
|
String(20), nullable=False, default="verified", server_default="verified"
|
|
)
|
|
expected_provider: Mapped[str] = mapped_column(String(40), nullable=False)
|
|
expected_forge_instance: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
expected_forge_owner: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
expected_forge_repository_id: Mapped[int] = mapped_column(
|
|
BigInteger, nullable=False
|
|
)
|
|
expected_source_commit: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
expected_default_branch: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
old_slug: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
|
|
new_slug: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
|
|
old_coordinates: Mapped[dict] = mapped_column(JSONB, nullable=False)
|
|
new_coordinates: Mapped[dict] = mapped_column(JSONB, nullable=False)
|
|
phase: Mapped[str] = mapped_column(
|
|
String(32), nullable=False, default="draft", server_default="draft"
|
|
)
|
|
actor: Mapped[str] = mapped_column(String(160), nullable=False)
|
|
phase_changed_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), nullable=False
|
|
)
|
|
preflighted_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
preflight_expires_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
completed_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
rolled_back_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
evidence: Mapped[dict] = mapped_column(
|
|
JSONB, nullable=False, default=dict, server_default="{}"
|
|
)
|
|
error_code: Mapped[str | None] = mapped_column(String(80), nullable=True)
|
|
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
error_details: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
|
|
error_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
|
|
repo: Mapped["ManagedRepo"] = relationship( # noqa: F821
|
|
"ManagedRepo", back_populates="rename_operations", lazy="selectin"
|
|
)
|
|
forge_identity: Mapped[RepositoryForgeIdentity] = relationship(
|
|
"RepositoryForgeIdentity",
|
|
back_populates="rename_operations",
|
|
lazy="selectin",
|
|
viewonly=True,
|
|
)
|
|
slugs: Mapped[list["RepositorySlug"]] = relationship(
|
|
"RepositorySlug", back_populates="source_operation", lazy="selectin"
|
|
)
|
|
|
|
|
|
class RepositorySlug(Base, TimestampMixin):
|
|
"""Global uniqueness boundary for current and protected prior slugs."""
|
|
|
|
__tablename__ = "repository_slugs"
|
|
__table_args__ = (
|
|
UniqueConstraint("slug", name="uq_repository_slugs_slug"),
|
|
CheckConstraint(
|
|
"kind IN ('canonical', 'alias')", name="ck_repository_slug_kind"
|
|
),
|
|
CheckConstraint(
|
|
"kind != 'alias' OR protected",
|
|
name="ck_repository_slug_alias_protected",
|
|
),
|
|
Index(
|
|
"uq_repository_slugs_one_canonical",
|
|
"repo_id",
|
|
unique=True,
|
|
postgresql_where=text("kind = 'canonical'"),
|
|
),
|
|
Index("ix_repository_slugs_repo_kind", "repo_id", "kind"),
|
|
)
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True), primary_key=True, default=new_uuid
|
|
)
|
|
repo_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("managed_repos.id", ondelete="RESTRICT"),
|
|
nullable=False,
|
|
)
|
|
slug: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
kind: Mapped[str] = mapped_column(String(16), nullable=False)
|
|
protected: Mapped[bool] = mapped_column(
|
|
Boolean, nullable=False, default=True, server_default="true"
|
|
)
|
|
source_operation_id: Mapped[uuid.UUID | None] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("repository_rename_operations.id", ondelete="RESTRICT"),
|
|
nullable=True,
|
|
index=True,
|
|
)
|
|
|
|
repo: Mapped["ManagedRepo"] = relationship( # noqa: F821
|
|
"ManagedRepo", back_populates="slug_records", lazy="selectin"
|
|
)
|
|
source_operation: Mapped[RepositoryRenameOperation | None] = relationship(
|
|
"RepositoryRenameOperation", back_populates="slugs", lazy="selectin"
|
|
)
|