Initial travel knowledge graph release
This commit is contained in:
208
app/contracts.py
Normal file
208
app/contracts.py
Normal file
@@ -0,0 +1,208 @@
|
||||
"""Pydantic request/response models."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class _Base(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
# ── Auth ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
class LoginRequest(BaseModel):
|
||||
username: str
|
||||
password: str
|
||||
|
||||
|
||||
class TokenResponse(BaseModel):
|
||||
access_token: str
|
||||
token_type: str = "bearer"
|
||||
|
||||
|
||||
# ── Source Profiles ──────────────────────────────────────────────────────────
|
||||
|
||||
class SourceProfileCreate(BaseModel):
|
||||
source_code: str
|
||||
source_name: str
|
||||
source_type: Literal["manual", "python_crawler", "api", "csv", "external_system"]
|
||||
description: str | None = None
|
||||
api_endpoint: str | None = None
|
||||
auth_method: str | None = None
|
||||
update_frequency: Literal["daily", "weekly", "monthly", "on_demand"] | None = None
|
||||
authority_level: int = Field(default=3, ge=1, le=5)
|
||||
enabled: bool = True
|
||||
metadata_jsonb: dict = Field(default_factory=dict)
|
||||
|
||||
|
||||
class SourceProfileUpdate(BaseModel):
|
||||
source_name: str | None = None
|
||||
description: str | None = None
|
||||
authority_level: int | None = Field(default=None, ge=1, le=5)
|
||||
enabled: bool | None = None
|
||||
update_frequency: str | None = None
|
||||
|
||||
|
||||
# ── Question Traces ──────────────────────────────────────────────────────────
|
||||
|
||||
class QuestionTraceCreate(BaseModel):
|
||||
question_text: str
|
||||
source: Literal["real", "simulated"] = "real"
|
||||
origin: str | None = None
|
||||
user_session: str | None = None
|
||||
asked_at: datetime | None = None
|
||||
|
||||
|
||||
class QuestionTraceBatch(BaseModel):
|
||||
questions: list[QuestionTraceCreate]
|
||||
|
||||
|
||||
class SimulationQuestion(BaseModel):
|
||||
question_text: str
|
||||
scenario_tags: list[str] = Field(default_factory=list)
|
||||
enabled: bool = True
|
||||
|
||||
|
||||
class SimulationQuestionUpdate(BaseModel):
|
||||
question_text: str | None = None
|
||||
scenario_tags: list[str] | None = None
|
||||
enabled: bool | None = None
|
||||
|
||||
|
||||
# ── Field Decisions ──────────────────────────────────────────────────────────
|
||||
|
||||
class FieldDecisionUpdate(BaseModel):
|
||||
field_decisions: dict[str, str]
|
||||
note: str | None = None
|
||||
|
||||
|
||||
# ── Acquisition Tasks ────────────────────────────────────────────────────────
|
||||
|
||||
class AcquisitionTaskCreate(BaseModel):
|
||||
title: str
|
||||
description: str | None = None
|
||||
scenario_tags: list[str] = Field(default_factory=list)
|
||||
target_entity_types: list[str] = Field(default_factory=list)
|
||||
target_fields: list[str] = Field(default_factory=list)
|
||||
suggested_collection_method: str | None = None
|
||||
priority: int = Field(default=3, ge=1, le=5)
|
||||
due_at: datetime | None = None
|
||||
|
||||
|
||||
class TaskFromGap(BaseModel):
|
||||
trace_id: int
|
||||
title: str | None = None
|
||||
priority: int = Field(default=3, ge=1, le=5)
|
||||
|
||||
|
||||
class TaskAssign(BaseModel):
|
||||
assignee: str
|
||||
|
||||
|
||||
class TaskComplete(BaseModel):
|
||||
result_summary: str | None = None
|
||||
|
||||
|
||||
# ── Inventory ────────────────────────────────────────────────────────────────
|
||||
|
||||
class IssueResolve(BaseModel):
|
||||
resolution_note: str | None = None
|
||||
|
||||
|
||||
# ── Vocabulary ───────────────────────────────────────────────────────────────
|
||||
|
||||
class VocabularyTermCreate(BaseModel):
|
||||
entity_type: str
|
||||
canonical_name: str
|
||||
aliases: list[str] = Field(default_factory=list)
|
||||
forbidden_aliases: list[str] = Field(default_factory=list)
|
||||
notes: str | None = None
|
||||
|
||||
|
||||
class VocabularyTermUpdate(BaseModel):
|
||||
canonical_name: str | None = None
|
||||
aliases: list[str] | None = None
|
||||
forbidden_aliases: list[str] | None = None
|
||||
notes: str | None = None
|
||||
|
||||
|
||||
# ── Conflicts ────────────────────────────────────────────────────────────────
|
||||
|
||||
class ConflictResolve(BaseModel):
|
||||
resolution: str
|
||||
chosen_value: Any | None = None
|
||||
note: str | None = None
|
||||
|
||||
|
||||
# ── Aligner ──────────────────────────────────────────────────────────────────
|
||||
|
||||
class AlignSuggestRequest(BaseModel):
|
||||
candidate_ids: list[int]
|
||||
|
||||
|
||||
class MergeEntities(BaseModel):
|
||||
note: str | None = None
|
||||
|
||||
|
||||
# ── Rollback ─────────────────────────────────────────────────────────────────
|
||||
|
||||
class RollbackRequest(BaseModel):
|
||||
reason: str | None = None
|
||||
|
||||
|
||||
# ── RBAC & Accounts (P1) ─────────────────────────────────────────────────────
|
||||
|
||||
class RoleCreate(BaseModel):
|
||||
role_key: str = Field(pattern=r"^[a-z][a-z0-9_]{1,30}$")
|
||||
label: str
|
||||
description: str | None = None
|
||||
sort_order: int | None = None
|
||||
|
||||
|
||||
class RoleUpdate(BaseModel):
|
||||
label: str | None = None
|
||||
description: str | None = None
|
||||
sort_order: int | None = None
|
||||
|
||||
|
||||
class CapabilityCreate(BaseModel):
|
||||
cap_key: str = Field(pattern=r"^[a-z][a-z0-9_]{1,40}$")
|
||||
label: str
|
||||
sort_order: int | None = None
|
||||
|
||||
|
||||
class RoleCapCell(BaseModel):
|
||||
role_key: str
|
||||
cap_key: str
|
||||
value: str
|
||||
|
||||
|
||||
class UserCreate(BaseModel):
|
||||
username: str = Field(min_length=3, max_length=120)
|
||||
password: str = Field(min_length=4, max_length=72)
|
||||
full_name: str | None = None
|
||||
phone: str | None = None
|
||||
status: str | None = None
|
||||
roles: list[str] = []
|
||||
|
||||
|
||||
class UserUpdate(BaseModel):
|
||||
full_name: str | None = None
|
||||
phone: str | None = None
|
||||
status: str | None = None
|
||||
password: str | None = Field(default=None, min_length=4, max_length=72)
|
||||
roles: list[str] | None = None
|
||||
|
||||
|
||||
class AreaUpdate(BaseModel):
|
||||
name: str | None = None
|
||||
note: str | None = None
|
||||
responsible_user_id: int | None = None
|
||||
|
||||
|
||||
class UserAreasSet(BaseModel):
|
||||
area_ids: list[str] = [] # existing area ids picked from the tree
|
||||
custom_areas: list[str] = [] # free-text area names typed by admin
|
||||
Reference in New Issue
Block a user