state-hub/api/schemas/review_contract.py
tegwick 598f6418e7
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 25s
feat(review): add multi-owner contracts and receipts
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a023c0-a0a3-7c03-b395-5a0d2757214d
2026-08-22 20:57:51 +02:00

96 lines
2.6 KiB
Python

import uuid
from datetime import datetime
from typing import Any, Literal
from pydantic import BaseModel, ConfigDict, Field
class SourceRef(BaseModel):
repo: str = Field(min_length=1, max_length=100)
path: str = Field(min_length=1, max_length=1000)
revision: str = Field(pattern=r"^[0-9a-f]{40,64}$")
class ReviewContractProject(BaseModel):
contract: dict[str, Any]
source: SourceRef
decision_id: uuid.UUID | None = None
workplan_id: uuid.UUID | None = None
task_id: uuid.UUID | None = None
required_for_decision: bool = False
class ReviewContractRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
contract_key: str
schema_version: str
contract_digest: str
source_repo: str
source_path: str
source_revision: str
document: dict[str, Any]
active: bool
required_for_decision: bool
decision_id: uuid.UUID | None
workplan_id: uuid.UUID | None
task_id: uuid.UUID | None
projected_at: datetime
created_at: datetime
updated_at: datetime
class ReviewReceiptSubmit(BaseModel):
owner_id: str = Field(min_length=1, max_length=160)
actor: str = Field(min_length=2, max_length=160)
disposition: Literal["approve", "request_changes"]
contract_digest: str = Field(pattern=r"^[0-9a-f]{64}$")
artifact_hashes: dict[str, str] = Field(default_factory=dict)
assertion_ids: list[str] = Field(default_factory=list)
checks: list[dict[str, Any]] = Field(default_factory=list)
note: str | None = Field(default=None, max_length=2000)
source: SourceRef
class ReviewReceiptRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
contract_id: uuid.UUID
owner_id: str
actor: str
disposition: str
contract_digest: str
receipt_digest: str
artifact_hashes: dict[str, str]
assertion_ids: list[str]
checks: list[dict[str, Any]]
note: str | None
source_repo: str
source_path: str
source_revision: str
submitted_at: datetime
created_at: datetime
class OwnerReviewState(BaseModel):
owner_id: str
status: Literal["missing", "approved", "request_changes", "stale"]
receipt_id: uuid.UUID | None = None
receipt_digest: str | None = None
submitted_at: datetime | None = None
class GateReviewState(BaseModel):
gate_id: str
policy: Literal["all_required"]
owners: list[str]
satisfied: bool
class ReviewAggregateRead(BaseModel):
contract_key: str
contract_digest: str
satisfied: bool
authorizes_execution: Literal[False] = False
owners: list[OwnerReviewState]
gates: list[GateReviewState]