issue-core/issue_core/api/schemas.py
tegwick f88e9a28fe
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Build and Publish Container Image / build-and-push (push) Successful in 1m22s
feat: implement ISSUE-WP-0005 connector mapping and scope alignment
Add MappingService (work_record_uuid ↔ external id), project/map CLI with
outward push-status, optional TaskSpec work_record fields, boundary-sync
policy, and packaging/capability framing cleanup. Mark WP-0005 finished.
2026-07-22 00:25:06 +02:00

70 lines
2.1 KiB
Python

"""
Pydantic schemas for the issue-core REST API.
The TaskIngestionRequest schema matches activity-core's IssueSink TaskSpec
payload. See:
- SCOPE.md "TaskSpec payload" section
- activity-core docs/adr/adr-001-event-bridge-architecture.md
"""
from typing import List, Literal, Optional
from pydantic import BaseModel, ConfigDict, Field
SourceType = Literal["rule", "instruction"]
Priority = Literal["high", "medium", "low"]
BackendName = Literal["gitea", "sqlite", "github"]
class TaskIngestionRequest(BaseModel):
"""TaskSpec payload from activity-core's IssueSink (POST /issues/)."""
model_config = ConfigDict(extra="forbid")
title: str = Field(..., min_length=1, max_length=500)
description: str = ""
target_repo: str = Field(..., min_length=1)
priority: Priority = "medium"
labels: List[str] = Field(default_factory=list)
due_in_days: Optional[int] = Field(default=None, ge=0)
source_type: SourceType
source_id: str = Field(..., min_length=1)
triggering_event_id: str = Field(
...,
min_length=1,
description=(
"Activity event UUID, or a stable scheduler/source key when no "
"event row exists. Not a work-record UUID."
),
)
activity_definition_id: str = Field(..., min_length=1)
work_record_uuid: Optional[str] = Field(
default=None,
description=(
"Optional work-record UUIDv7. When set, ingestion upserts a "
"mapping row (work_record_uuid ↔ backend issue id)."
),
)
work_record_id: Optional[str] = Field(
default=None,
description="Optional canonical work-record id (human-facing).",
)
work_record_kind: Optional[str] = Field(
default=None,
description="Optional work-record kind (task, intake, …).",
)
class TaskIngestionResponse(BaseModel):
"""Response returned to the emitter after a successful ingestion."""
issue_id: str
issue_url: Optional[str] = None
backend: BackendName
class ErrorResponse(BaseModel):
"""Uniform error envelope."""
error: str
detail: Optional[str] = None