feat(capability-requests): add routing dispute & reroute workflow (CUST-WP-0027)

Adds a structured dispute mechanism when capability request routing is wrong:
- New `routing_disputed` status with four DB columns (dispute_reason, disputed_by,
  dispute_suggested_domain, disputed_at) via Alembic migration m0h1i2j3k4l5
- POST /capability-requests/{id}/dispute — any party can flag misrouting with a reason
  and optional suggested domain; notifies custodian + current fulfilling domain
- POST /capability-requests/{id}/reroute — custodian re-routes to correct domain via
  catalog_entry_id or direct slug; appends audit trail to routing_note; resets to requested
- Two new MCP tools: dispute_capability_routing and reroute_capability_request
- Dashboard: amber disputed-banner at top of Summary, routing_disputed Kanban column,
  dispute details (reason, suggested domain, raised-by) shown on disputed cards

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-21 23:58:52 +01:00
parent b6103d1f9f
commit b3a44fb4f3
6 changed files with 277 additions and 16 deletions

View File

@@ -62,6 +62,19 @@ class CapabilityRequestPatch(BaseModel):
fulfilling_workstream_id: uuid.UUID | None = None
class CapabilityRequestDispute(BaseModel):
reason: str
disputed_by: str
suggested_domain: str | None = None
class CapabilityRequestReroute(BaseModel):
note: str
rerouted_by: str
domain: str | None = None # slug — used if catalog_entry_id not given
catalog_entry_id: uuid.UUID | None = None # preferred: re-derives domain
class CapabilityRequestRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
@@ -81,6 +94,10 @@ class CapabilityRequestRead(BaseModel):
catalog_entry_id: uuid.UUID | None = None
resolution_note: str | None = None
routing_note: str | None = None
dispute_reason: str | None = None
disputed_by: str | None = None
dispute_suggested_domain: str | None = None
disputed_at: datetime | None = None
accepted_at: datetime | None = None
completed_at: datetime | None = None
created_at: datetime