generated from coulomb/repo-seed
feat: rename to issue-core and add task ingestion endpoint
Renames the package, distribution, CLI alias, Makefile targets, and working directory from issue-facade to issue-core, signalling its role as the authoritative task lifecycle manager for the Coulomb org (peer to activity-core, rules-core, project-core). Adds POST /issues/ ingestion endpoint for activity-core's IssueSink, under a new optional [api] extra. The endpoint is served by `issue serve`, authenticates via the ISSUE_CORE_API_KEY env var (Bearer or X-API-Key header), and routes the TaskSpec payload to the configured default backend with full traceability metadata embedded in sync_metadata. - T01: Python package issue_tracker -> issue_core, dir rename - T02: registered in state hub under custodian domain - T03: INTENT.md (what it is, what it isn't, how it fits) - T04: SCOPE.md (in/out-of-scope, integration boundaries) - T05: POST /issues/ via FastAPI + Uvicorn, 9 unit tests - T06: docs/nats-task-ingestion.md design stub Closes ISSC-WP-0001. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
50
issue_core/api/schemas.py
Normal file
50
issue_core/api/schemas.py
Normal file
@@ -0,0 +1,50 @@
|
||||
"""
|
||||
Pydantic schemas for the issue-core REST API.
|
||||
|
||||
The TaskIngestionRequest schema matches activity-core's IssueSink TaskSpec
|
||||
payload exactly. See:
|
||||
- SCOPE.md "TaskSpec payload" section
|
||||
- activity-core docs/adr/adr-001-event-bridge-architecture.md
|
||||
"""
|
||||
|
||||
from typing import List, Literal, Optional
|
||||
from uuid import UUID
|
||||
|
||||
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: UUID
|
||||
activity_definition_id: str = Field(..., min_length=1)
|
||||
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user