From 6d65d50ec121238e025e9b8ffd15e2e1cb87a67a Mon Sep 17 00:00:00 2001 From: Hare Date: Wed, 23 Sep 2026 05:42:50 +0900 Subject: [PATCH] feat: migrate ticket and objective domains to ServerApi --- Cargo.lock | 4 + crates/client/src/backend_workspace.rs | 6 +- crates/client/src/workspace_product.rs | 498 +- crates/merge-request/Cargo.toml | 1 + crates/merge-request/src/lib.rs | 38 +- crates/server-api/Cargo.toml | 2 + crates/server-api/src/lib.rs | 1651 ++- crates/ticket/src/lib.rs | 128 +- crates/workspace-server/src/server.rs | 1464 ++- openapi/server-api.json | 10460 +++++++++++++++- .../src/lib/generated/repository-api.ts | 2 +- 11 files changed, 13759 insertions(+), 495 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31f95a8c1..3ad43461a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2579,6 +2579,7 @@ version = "0.1.0" dependencies = [ "chrono", "rusqlite", + "schemars", "serde", "serde_json", "tempfile", @@ -3910,6 +3911,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ + "chrono", "dyn-clone", "ref-cast", "schemars_derive", @@ -4150,12 +4152,14 @@ version = "0.1.0" dependencies = [ "api-macros", "memory", + "merge-request", "protocol", "runtime-api", "schemars", "serde", "serde_json", "sha2 0.11.0", + "ticket", "tokio", "ts-rs", "webauthn-rs-proto", diff --git a/crates/client/src/backend_workspace.rs b/crates/client/src/backend_workspace.rs index d7564e81f..35536fa23 100644 --- a/crates/client/src/backend_workspace.rs +++ b/crates/client/src/backend_workspace.rs @@ -68,7 +68,7 @@ impl From, ) -> BackendWorkspaceClientError { @@ -92,7 +92,7 @@ fn server_client_error( } #[derive(Clone, Debug)] -struct ServerBearerAuthorizer { +pub(crate) struct ServerBearerAuthorizer { authorization: String, } @@ -114,7 +114,7 @@ impl server_api::client_support::RequestAuthorizer for ServerBearerAuthorizer { const SERVER_RESPONSE_LIMIT: usize = 16 * 1024 * 1024; -fn server_api_client( +pub(crate) fn server_api_client( backend: &BackendApiClient, ) -> Result, BackendWorkspaceClientError> { server_api::ServerApiClient::builder(backend.origin().as_str()) diff --git a/crates/client/src/workspace_product.rs b/crates/client/src/workspace_product.rs index 5d42a8e22..e561b9a44 100644 --- a/crates/client/src/workspace_product.rs +++ b/crates/client/src/workspace_product.rs @@ -1,13 +1,12 @@ use reqwest::Method; +use serde::Serialize; use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; use server_api::{ BrowserCreateWorkerResponse, BrowserWorkspaceOrchestratorResponse, CreateWorkspaceWorkerRequest, ListResponse, MemoryDocumentResponse, MemoryStagingListResponse, ObjectiveCreateRequest, ObjectiveDetail, ObjectiveEditRequest, ObjectiveLinkTicketRequest, ObjectiveStateRequest, ObjectiveSummary, RevokeRuntimeTrustKeyRequest, - RuntimeTrustKeyRevealResponse, TICKET_ORCHESTRATION_PLANS_QUERY_PATH, - TICKET_RELATIONS_QUERY_PATH, WorkerLaunchOptionsResponse, WorkspaceRuntimeDetail, + RuntimeTrustKeyRevealResponse, WorkerLaunchOptionsResponse, WorkspaceRuntimeDetail, WorkspaceRuntimeResource, }; use ticket::{ @@ -22,21 +21,6 @@ use crate::{BackendApiClient, BackendWorkspaceClientError}; const DEFAULT_PRODUCT_LIST_LIMIT: usize = 1_000; -#[derive(Debug, Deserialize)] -struct BackendObjectiveListResponse { - workspace_id: String, - limit: usize, - items: Vec, - invalid_records: Vec, - record_authority: String, -} - -#[derive(Debug, Deserialize)] -struct BackendInvalidProjectRecord { - label: String, - reason: String, -} - /// Workspace-scoped Backend client for Ticket and Objective product state. /// /// Construction requires both the selected Backend URL and Workspace identity. @@ -85,26 +69,71 @@ impl BackendWorkspaceProductClient { &self.workspace_id } + fn generated(&self, operation: F) -> Result + where + F: FnOnce( + server_api::ServerApiClient, + ) -> Fut, + Fut: std::future::Future< + Output = Result< + T, + server_api::client_support::ClientError, + >, + >, + { + let client = crate::backend_workspace::server_api_client(&self.api)?; + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .map_err(|error| BackendWorkspaceClientError::InvalidTarget(error.to_string()))?; + runtime + .block_on(operation(client)) + .map_err(|error| crate::backend_workspace::server_client_error(&self.api, error)) + } + pub fn list_tickets( &self, query: &TicketListQuery, ) -> Result, BackendWorkspaceClientError> { + let workspace_id = self.workspace_id.clone(); let state = ticket_list_state_query(query); - self.get_json(&format!("/tickets/search?state={state}")) + self.generated(move |client| async move { + client + .ticket_summary_search( + workspace_id, + server_api::TicketSummarySearchQuery { + state: Some(state), + limit: None, + }, + ) + .await + .map(|response| response.0) + }) } pub fn show_ticket(&self, id: &TicketIdOrSlug) -> Result { - self.get_json(&format!( - "/tickets/{}/record", - encode_path_segment(&ticket_reference(id)) - )) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(id); + self.generated(move |client| async move { + client + .ticket_record_get(workspace_id, id) + .await + .map(|response| response.0) + }) } pub fn create_ticket( &self, input: &NewTicket, ) -> Result { - self.send_json(Method::POST, "/tickets", Some(input)) + let workspace_id = self.workspace_id.clone(); + let input = input.clone(); + self.generated(move |client| async move { + client + .ticket_create_record(workspace_id, server_api::CreateTicketRecordRequest(input)) + .await + .map(|response| response.0) + }) } pub fn add_ticket_event( @@ -112,14 +141,18 @@ impl BackendWorkspaceProductClient { id: &TicketIdOrSlug, event: &NewTicketEvent, ) -> Result<(), BackendWorkspaceClientError> { - self.send_unit( - Method::POST, - &format!( - "/tickets/{}/thread-events", - encode_path_segment(&ticket_reference(id)) - ), - Some(event), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(id); + let event = event.clone(); + self.generated(move |client| async move { + client + .ticket_thread_event_add( + workspace_id, + id, + server_api::TicketThreadEventRequest(event), + ) + .await + }) } pub fn set_ticket_workflow_state( @@ -127,14 +160,18 @@ impl BackendWorkspaceProductClient { id: &TicketIdOrSlug, change: &TicketStateChange, ) -> Result<(), BackendWorkspaceClientError> { - self.send_unit( - Method::POST, - &format!( - "/tickets/{}/workflow-state", - encode_path_segment(&ticket_reference(id)) - ), - Some(change), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(id); + let change = change.clone(); + self.generated(move |client| async move { + client + .ticket_workflow_state_set( + workspace_id, + id, + server_api::TicketStateChangeRequest(change), + ) + .await + }) } pub fn close_ticket( @@ -142,14 +179,18 @@ impl BackendWorkspaceProductClient { id: &TicketIdOrSlug, resolution: &MarkdownText, ) -> Result<(), BackendWorkspaceClientError> { - self.send_unit( - Method::POST, - &format!( - "/tickets/{}/workflow/close", - encode_path_segment(&ticket_reference(id)) - ), - Some(resolution), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(id); + let resolution = resolution.clone(); + self.generated(move |client| async move { + client + .ticket_close_record( + workspace_id, + id, + server_api::TicketCloseRecordRequest(resolution), + ) + .await + }) } pub fn add_ticket_relation( @@ -157,14 +198,19 @@ impl BackendWorkspaceProductClient { id: &TicketIdOrSlug, relation: &NewTicketRelation, ) -> Result { - self.send_json( - Method::POST, - &format!( - "/tickets/{}/relations", - encode_path_segment(&ticket_reference(id)) - ), - Some(relation), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(id); + let relation = relation.clone(); + self.generated(move |client| async move { + client + .ticket_relation_record( + workspace_id, + id, + server_api::CreateTicketRelationRequest(relation), + ) + .await + .map(|response| response.0) + }) } pub fn query_ticket_relations( @@ -172,28 +218,42 @@ impl BackendWorkspaceProductClient { ticket: Option<&TicketIdOrSlug>, kind: Option, ) -> Result, BackendWorkspaceClientError> { - #[derive(Serialize)] - struct Query<'a> { - ticket: Option<&'a TicketIdOrSlug>, - kind: Option, - } - self.send_json( - Method::POST, - TICKET_RELATIONS_QUERY_PATH, - Some(&Query { ticket, kind }), - ) + let workspace_id = self.workspace_id.clone(); + let ticket = ticket.cloned(); + self.generated(move |client| async move { + client + .ticket_relation_query( + workspace_id, + server_api::TicketRelationSearchRequest { ticket, kind }, + ) + .await + .map(|response| response.0) + }) } pub fn ticket_doctor(&self) -> Result { - self.get_json("/tickets/doctor") + let workspace_id = self.workspace_id.clone(); + self.generated(move |client| async move { + client + .ticket_doctor(workspace_id) + .await + .map(|response| response.0) + }) } pub fn list_objectives( &self, limit: usize, ) -> Result, BackendWorkspaceClientError> { - let response: BackendObjectiveListResponse = - self.get_json(&format!("/objectives?limit={limit}"))?; + let workspace_id = self.workspace_id.clone(); + let response = self.generated(move |client| async move { + client + .objective_list( + workspace_id, + server_api::ObjectiveListQuery { limit: Some(limit) }, + ) + .await + })?; Ok(ListResponse { workspace_id: response.workspace_id, limit: response.limit, @@ -212,14 +272,20 @@ impl BackendWorkspaceProductClient { } pub fn show_objective(&self, id: &str) -> Result { - self.get_json(&format!("/objectives/{}", encode_path_segment(id))) + let workspace_id = self.workspace_id.clone(); + let id = id.to_string(); + self.generated(move |client| async move { client.objective_get(workspace_id, id).await }) } pub fn create_objective( &self, input: &ObjectiveCreateRequest, ) -> Result { - self.send_json(Method::POST, "/objectives", Some(input)) + let workspace_id = self.workspace_id.clone(); + let input = input.clone(); + self.generated( + move |client| async move { client.objective_create(workspace_id, input).await }, + ) } pub fn edit_objective( @@ -227,10 +293,11 @@ impl BackendWorkspaceProductClient { id: &str, input: &ObjectiveEditRequest, ) -> Result { - self.send_json( - Method::PATCH, - &format!("/objectives/{}", encode_path_segment(id)), - Some(input), + let workspace_id = self.workspace_id.clone(); + let id = id.to_string(); + let input = input.clone(); + self.generated( + move |client| async move { client.objective_edit(workspace_id, id, input).await }, ) } @@ -239,11 +306,12 @@ impl BackendWorkspaceProductClient { id: &str, input: &ObjectiveStateRequest, ) -> Result { - self.send_json( - Method::POST, - &format!("/objectives/{}/state", encode_path_segment(id)), - Some(input), - ) + let workspace_id = self.workspace_id.clone(); + let id = id.to_string(); + let input = input.clone(); + self.generated(move |client| async move { + client.objective_state_set(workspace_id, id, input).await + }) } pub fn link_objective_ticket( @@ -251,11 +319,12 @@ impl BackendWorkspaceProductClient { id: &str, input: &ObjectiveLinkTicketRequest, ) -> Result { - self.send_json( - Method::POST, - &format!("/objectives/{}/ticket-links", encode_path_segment(id)), - Some(input), - ) + let workspace_id = self.workspace_id.clone(); + let id = id.to_string(); + let input = input.clone(); + self.generated(move |client| async move { + client.objective_ticket_link(workspace_id, id, input).await + }) } pub fn unlink_objective_ticket( @@ -263,15 +332,14 @@ impl BackendWorkspaceProductClient { id: &str, ticket_id: &str, ) -> Result { - self.send_json::<(), _>( - Method::DELETE, - &format!( - "/objectives/{}/ticket-links/{}", - encode_path_segment(id), - encode_path_segment(ticket_id) - ), - None, - ) + let workspace_id = self.workspace_id.clone(); + let id = id.to_string(); + let ticket_id = ticket_id.to_string(); + self.generated(move |client| async move { + client + .objective_ticket_unlink(workspace_id, id, ticket_id) + .await + }) } pub fn list_runtimes( @@ -387,17 +455,6 @@ impl BackendWorkspaceProductClient { response.json().map_err(BackendWorkspaceClientError::Http) } - fn send_unit( - &self, - method: Method, - path: &str, - body: Option<&B>, - ) -> Result<(), BackendWorkspaceClientError> { - let response = self.request(method, path, body)?.send()?; - self.api.check_status(response.status())?; - Ok(()) - } - fn request( &self, method: Method, @@ -419,15 +476,17 @@ impl BackendWorkspaceProductClient { impl TicketBackend for BackendWorkspaceProductClient { fn default_intake_ready_state_change_body(&self, from: &str) -> String { - #[derive(Serialize)] - struct Request<'a> { - from: &'a str, - } - self.send_json( - Method::POST, - "/tickets/default-intake-ready-body", - Some(&Request { from }), - ) + let workspace_id = self.workspace_id.clone(); + let from = from.to_string(); + self.generated(move |client| async move { + client + .ticket_default_intake_ready_body( + workspace_id, + server_api::DefaultIntakeReadyBodyRequest { from }, + ) + .await + .map(|response| response.0) + }) .unwrap_or_else(|error| error.to_string()) } @@ -444,22 +503,30 @@ impl TicketBackend for BackendWorkspaceProductClient { } fn edit_item(&self, id: TicketIdOrSlug, edit: TicketItemEdit) -> ticket::Result { - self.send_json( - Method::PATCH, - &format!( - "/tickets/{}/item", - encode_path_segment(&ticket_reference(&id)) - ), - Some(&edit), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(&id); + self.generated(move |client| async move { + client + .ticket_record_item_edit( + workspace_id, + id, + server_api::EditTicketRecordItemRequest(edit), + ) + .await + .map(|response| response.0) + }) .map_err(ticket_client_error) } fn dependency_check(&self, id: TicketIdOrSlug) -> ticket::Result { - self.get_json(&format!( - "/tickets/{}/dependency-check", - encode_path_segment(&ticket_reference(&id)) - )) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(&id); + self.generated(move |client| async move { + client + .ticket_dependency_check(workspace_id, id) + .await + .map(|response| response.0) + }) .map_err(ticket_client_error) } @@ -473,14 +540,17 @@ impl TicketBackend for BackendWorkspaceProductClient { id: TicketIdOrSlug, change: TicketStateChange, ) -> ticket::Result<()> { - self.send_unit( - Method::POST, - &format!( - "/tickets/{}/state-changes", - encode_path_segment(&ticket_reference(&id)) - ), - Some(&change), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(&id); + self.generated(move |client| async move { + client + .ticket_state_change_add( + workspace_id, + id, + server_api::TicketStateChangeRequest(change), + ) + .await + }) .map_err(ticket_client_error) } @@ -489,14 +559,17 @@ impl TicketBackend for BackendWorkspaceProductClient { id: TicketIdOrSlug, summary: TicketIntakeSummary, ) -> ticket::Result<()> { - self.send_unit( - Method::POST, - &format!( - "/tickets/{}/intake-summaries", - encode_path_segment(&ticket_reference(&id)) - ), - Some(&summary), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(&id); + self.generated(move |client| async move { + client + .ticket_intake_summary_add( + workspace_id, + id, + server_api::TicketIntakeSummaryRequest(summary), + ) + .await + }) .map_err(ticket_client_error) } @@ -506,15 +579,19 @@ impl TicketBackend for BackendWorkspaceProductClient { field: &str, change: TicketStateChange, ) -> ticket::Result<()> { - self.send_unit( - Method::POST, - &format!( - "/tickets/{}/state-fields/{}", - encode_path_segment(&ticket_reference(&id)), - encode_path_segment(field) - ), - Some(&change), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(&id); + let field = field.to_string(); + self.generated(move |client| async move { + client + .ticket_state_field_set( + workspace_id, + id, + field, + server_api::TicketStateChangeRequest(change), + ) + .await + }) .map_err(ticket_client_error) } @@ -528,14 +605,19 @@ impl TicketBackend for BackendWorkspaceProductClient { } fn mark_ready(&self, id: TicketIdOrSlug, request: TicketMarkReady) -> ticket::Result { - self.send_json( - Method::POST, - &format!( - "/tickets/{}/workflow/mark-ready", - encode_path_segment(&ticket_reference(&id)) - ), - Some(&request), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(&id); + let request = server_api::TicketMarkReadyRequest { + operation_key: request.operation_key, + reason: request.reason, + intake_summary: request.intake_summary, + }; + self.generated(move |client| async move { + client + .ticket_mark_ready_record(workspace_id, id, request) + .await + .map(|response| response.0) + }) .map_err(ticket_client_error) } @@ -544,14 +626,14 @@ impl TicketBackend for BackendWorkspaceProductClient { id: TicketIdOrSlug, _queued_by: &str, ) -> ticket::Result { - self.send_json::<(), _>( - Method::POST, - &format!( - "/tickets/{}/workflow/queue", - encode_path_segment(&ticket_reference(&id)) - ), - None, - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(&id); + self.generated(move |client| async move { + client + .ticket_queue_record(workspace_id, id) + .await + .map(|response| response.0) + }) .map_err(ticket_client_error) } @@ -575,22 +657,19 @@ impl TicketBackend for BackendWorkspaceProductClient { kind: TicketRelationKind, target: TicketIdOrSlug, ) -> ticket::Result { - #[derive(Serialize)] - struct Request { - kind: TicketRelationKind, - target: String, - } - self.send_json( - Method::DELETE, - &format!( - "/tickets/{}/relations", - encode_path_segment(&ticket_reference(&id)) - ), - Some(&Request { - kind, - target: ticket_reference(&target), - }), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(&id); + let target = ticket_reference(&target); + self.generated(move |client| async move { + client + .ticket_relation_remove( + workspace_id, + id, + server_api::TicketRelationRemoveRequest { kind, target }, + ) + .await + .map(|response| response.0) + }) .map_err(ticket_client_error) } @@ -604,10 +683,14 @@ impl TicketBackend for BackendWorkspaceProductClient { } fn relation_view(&self, id: TicketIdOrSlug) -> ticket::Result { - self.get_json(&format!( - "/tickets/{}/relation-view", - encode_path_segment(&ticket_reference(&id)) - )) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(&id); + self.generated(move |client| async move { + client + .ticket_relation_view(workspace_id, id) + .await + .map(|response| response.0) + }) .map_err(ticket_client_error) } @@ -616,14 +699,18 @@ impl TicketBackend for BackendWorkspaceProductClient { id: TicketIdOrSlug, record: NewOrchestrationPlanRecord, ) -> ticket::Result { - self.send_json( - Method::POST, - &format!( - "/tickets/{}/orchestration-plans", - encode_path_segment(&ticket_reference(&id)) - ), - Some(&record), - ) + let workspace_id = self.workspace_id.clone(); + let id = ticket_reference(&id); + self.generated(move |client| async move { + client + .ticket_orchestration_plan_record( + workspace_id, + id, + server_api::CreateTicketOrchestrationPlanRequest(record), + ) + .await + .map(|response| response.0) + }) .map_err(ticket_client_error) } @@ -632,16 +719,16 @@ impl TicketBackend for BackendWorkspaceProductClient { ticket: Option, kind: Option, ) -> ticket::Result> { - #[derive(Serialize)] - struct Query { - ticket: Option, - kind: Option, - } - self.send_json( - Method::POST, - TICKET_ORCHESTRATION_PLANS_QUERY_PATH, - Some(&Query { ticket, kind }), - ) + let workspace_id = self.workspace_id.clone(); + self.generated(move |client| async move { + client + .ticket_orchestration_plan_query( + workspace_id, + server_api::TicketOrchestrationPlanSearchRequest { ticket, kind }, + ) + .await + .map(|response| response.0) + }) .map_err(ticket_client_error) } @@ -649,7 +736,6 @@ impl TicketBackend for BackendWorkspaceProductClient { self.ticket_doctor().map_err(ticket_client_error) } } - fn ticket_client_error(error: BackendWorkspaceClientError) -> TicketError { TicketError::Sqlite(format!("Backend request failed: {error}")) } diff --git a/crates/merge-request/Cargo.toml b/crates/merge-request/Cargo.toml index 7c0b5664e..61fa80fe0 100644 --- a/crates/merge-request/Cargo.toml +++ b/crates/merge-request/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true [dependencies] chrono = { version = "0.4", default-features = false, features = ["clock", "serde"] } rusqlite.workspace = true +schemars = { workspace = true, features = ["chrono04"] } serde = { workspace = true, features = ["derive"] } serde_json.workspace = true thiserror.workspace = true diff --git a/crates/merge-request/src/lib.rs b/crates/merge-request/src/lib.rs index c2777e4a2..154f3a773 100644 --- a/crates/merge-request/src/lib.rs +++ b/crates/merge-request/src/lib.rs @@ -18,7 +18,7 @@ const DOMAIN_TABLES: [&str; 5] = [ "merge_request_reviewer_child_sessions", ]; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(rename_all = "snake_case")] pub enum MergeRequestState { Open, @@ -43,13 +43,13 @@ impl MergeRequestState { } } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(rename_all = "snake_case")] pub enum ReviewDecision { Approve, RequestChanges, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(rename_all = "snake_case")] pub enum FindingSeverity { Blocker, @@ -57,7 +57,7 @@ pub enum FindingSeverity { Minor, Note, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct ReviewFinding { pub severity: FindingSeverity, #[serde(default, skip_serializing_if = "Option::is_none")] @@ -68,7 +68,7 @@ pub struct ReviewFinding { pub line: Option, pub body: String, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct WorkerIdentity { pub runtime_id: String, pub worker_id: String, @@ -91,18 +91,20 @@ impl MergeRequestAuth { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct ReviewRequestedEvent { pub event_id: String, + #[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))] pub sequence: u64, pub subject_ref: String, pub requested_by: WorkerIdentity, pub reviewer: WorkerIdentity, pub created_at: DateTime, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct ReviewEvent { pub event_id: String, + #[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))] pub sequence: u64, pub request_event_id: String, pub subject_ref: String, @@ -112,9 +114,10 @@ pub struct ReviewEvent { pub reviewer: WorkerIdentity, pub created_at: DateTime, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct ReviewRevokedEvent { pub event_id: String, + #[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))] pub sequence: u64, pub review_event_id: String, pub subject_ref: String, @@ -122,39 +125,42 @@ pub struct ReviewRevokedEvent { pub revoked_by: WorkerIdentity, pub created_at: DateTime, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct ReviewCancelledEvent { pub event_id: String, + #[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))] pub sequence: u64, pub request_event_id: String, pub subject_ref: String, pub reason: String, pub created_at: DateTime, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct CommentEvent { pub event_id: String, + #[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))] pub sequence: u64, pub body: String, pub author: WorkerIdentity, pub created_at: DateTime, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(rename_all = "snake_case")] pub enum MergeStrategy { FastForward, Merge, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(rename_all = "snake_case")] pub enum ConflictResolution { None, Clean, ConflictsResolved, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct MergeEvent { pub event_id: String, + #[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))] pub sequence: u64, pub operation_id: String, pub approval_event_id: String, @@ -166,7 +172,7 @@ pub struct MergeEvent { pub merged_by: WorkerIdentity, pub created_at: DateTime, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum MergeRequestThreadEvent { ReviewRequested(ReviewRequestedEvent), @@ -203,7 +209,7 @@ impl MergeRequestThreadEvent { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct MergeRequest { pub workspace_id: String, pub merge_request_id: String, @@ -313,7 +319,7 @@ pub struct ReadinessCheck { pub current_subject_ref: Option, pub auth: MergeRequestAuth, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct ReadinessReport { pub ready: bool, pub blockers: Vec, diff --git a/crates/server-api/Cargo.toml b/crates/server-api/Cargo.toml index d3b9def43..a74b4c020 100644 --- a/crates/server-api/Cargo.toml +++ b/crates/server-api/Cargo.toml @@ -12,12 +12,14 @@ typescript = ["dep:ts-rs", "protocol/typescript"] [dependencies] api-macros = { workspace = true, features = ["reqwest", "axum", "openapi"] } memory.workspace = true +merge-request.workspace = true protocol.workspace = true runtime-api.workspace = true schemars.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true sha2.workspace = true +ticket.workspace = true ts-rs = { version = "12.0.1", optional = true } webauthn-rs-proto = "0.5.5" workdir.workspace = true diff --git a/crates/server-api/src/lib.rs b/crates/server-api/src/lib.rs index 568bab327..ba6632d7d 100644 --- a/crates/server-api/src/lib.rs +++ b/crates/server-api/src/lib.rs @@ -152,6 +152,75 @@ impl_openapi_schema!( SkillCatalogResponse, SkillDetailResponse, SkillActivationResponse, + BrowserAppendTicketEventRequest, + BrowserCloseTicketRequest, + BrowserEditTicketRequest, + BrowserQueueTicketRequest, + BrowserTransitionTicketStateRequest, + CancelTicketImplementationRequest, + ClearTicketRoleAssignmentQuery, + CompleteMergeRequestRequest, + CreateTicketOrchestrationPlanRequest, + CreateTicketRecordRequest, + CreateTicketRelationRequest, + DefaultIntakeReadyBodyRequest, + EditTicketRecordItemRequest, + MergeEvent, + MergeRequestDetailResponse, + MergeRequestListQuery, + MergeRequestListResponse, + MergeRequestReadinessResponse, + MergeRequestThreadQuery, + MergeRequestThreadResponse, + ObjectiveCreateRequest, + ObjectiveDetail, + ObjectiveEditRequest, + ObjectiveLinkTicketRequest, + ObjectiveListQuery, + ObjectiveListResponse, + ObjectiveQueryRequest, + ObjectiveQueryResponse, + ObjectiveShowRequest, + ObjectiveStateRequest, + OpenMergeRequestRequest, + PublicMergeRequest, + RegisterMergeRequestReviewCapabilityRequest, + RegisterReviewerChildSessionRequest, + RepairMergeRequestSelectorRequest, + ReviewEvent, + ReviewRevokedEvent, + RevokeMergeRequestReviewRequest, + SetTicketRoleAssignmentRequest, + SubmitMergeRequestReviewRequest, + TextResponse, + TicketCloseRecordRequest, + TicketDependencyCheckResponse, + TicketDetail, + TicketDoctorResponse, + TicketIntakeSummaryRequest, + TicketListHttpQuery, + TicketListResponse, + TicketMarkReadyRequest, + TicketOrchestrationPlanRecord, + TicketOrchestrationPlanRecordList, + TicketOrchestrationPlanSearchRequest, + TicketQueryRequest, + TicketQueryResponse, + TicketQueueResponse, + TicketRecord, + TicketRecordRef, + TicketRecordSummaryList, + TicketRelationRecord, + TicketRelationRecordList, + TicketRelationRecordView, + TicketRelationRemoveRequest, + TicketRelationSearchRequest, + TicketRoleAssignmentMutationResponse, + TicketRoleAssignmentsResponse, + TicketShowRequest, + TicketStateChangeRequest, + TicketSummarySearchQuery, + TicketThreadEventRequest, ); #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -910,6 +979,478 @@ pub trait ServerApi { #[path] workspace_id: String, #[body] request: CreateWorkspaceRepositoryRequest, ) -> Result; + + #[get("/api/tickets", status = 200, error_status = 400, additional_error_statuses = [500])] + async fn ticket_list_alias( + &self, + #[query] query: TicketListHttpQuery, + ) -> Result; + + #[get("/api/w/{workspace_id}/tickets", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_list( + &self, + #[path] workspace_id: String, + #[query] query: TicketListHttpQuery, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_create_record( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[body] request: CreateTicketRecordRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/query", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_query( + &self, + #[path] workspace_id: String, + #[body] request: TicketQueryRequest, + ) -> Result; + + #[get("/api/tickets/{id}", status = 200, error_status = 404, additional_error_statuses = [400, 500])] + async fn ticket_get_alias( + &self, + #[path] id: String, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/default-intake-ready-body", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn ticket_default_intake_ready_body( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[body] request: DefaultIntakeReadyBodyRequest, + ) -> Result; + + #[get("/api/w/{workspace_id}/tickets/search", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn ticket_summary_search( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[query] query: TicketSummarySearchQuery, + ) -> Result; + + #[get("/api/w/{workspace_id}/tickets/doctor", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn ticket_doctor( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/relations/search", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn ticket_relation_query( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[body] request: TicketRelationSearchRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/orchestration-plans/search", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn ticket_orchestration_plan_query( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[body] request: TicketOrchestrationPlanSearchRequest, + ) -> Result; + + #[get("/api/w/{workspace_id}/tickets/{id}/record", status = 200, error_status = 404, additional_error_statuses = [400, 401, 403, 500])] + async fn ticket_record_get( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + ) -> Result; + + #[patch("/api/w/{workspace_id}/tickets/{id}/item", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_record_item_edit( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: EditTicketRecordItemRequest, + ) -> Result; + + #[get("/api/w/{workspace_id}/tickets/{id}/dependency-check", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn ticket_dependency_check( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/thread-events", status = 204, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_thread_event_add( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: TicketThreadEventRequest, + ) -> Result<(), RepositoryApiError>; + + #[post("/api/w/{workspace_id}/tickets/{id}/state-changes", status = 204, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_state_change_add( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: TicketStateChangeRequest, + ) -> Result<(), RepositoryApiError>; + + #[post("/api/w/{workspace_id}/tickets/{id}/intake-summaries", status = 204, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_intake_summary_add( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: TicketIntakeSummaryRequest, + ) -> Result<(), RepositoryApiError>; + + #[post("/api/w/{workspace_id}/tickets/{id}/state-fields/{field}", status = 204, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_state_field_set( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[path] field: String, + #[body] request: TicketStateChangeRequest, + ) -> Result<(), RepositoryApiError>; + + #[post("/api/w/{workspace_id}/tickets/{id}/workflow-state", status = 204, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_workflow_state_set( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: TicketStateChangeRequest, + ) -> Result<(), RepositoryApiError>; + + #[post("/api/w/{workspace_id}/tickets/{id}/workflow/mark-ready", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_mark_ready_record( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: TicketMarkReadyRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/workflow/queue", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_queue_record( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + ) -> Result; + + #[get("/api/w/{workspace_id}/merge-requests", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500], bearer_auth = true, browser_auth = true)] + async fn merge_request_list( + &self, + #[path] workspace_id: String, + #[query] query: MergeRequestListQuery, + ) -> Result; + + #[get("/api/w/{workspace_id}/merge-requests/{merge_request_id}", status = 200, error_status = 404, additional_error_statuses = [400, 401, 403, 500], bearer_auth = true, browser_auth = true)] + async fn merge_request_show( + &self, + #[path] workspace_id: String, + #[path] merge_request_id: String, + #[query] query: MergeRequestThreadQuery, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/merge-request", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn merge_request_open( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: OpenMergeRequestRequest, + ) -> Result; + + #[get("/api/w/{workspace_id}/tickets/{id}/merge-request/readiness", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn merge_request_readiness( + &self, + #[path] workspace_id: String, + #[path] id: String, + ) -> Result; + + #[get("/api/w/{workspace_id}/tickets/{id}/merge-request/thread", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn merge_request_thread( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[query] query: MergeRequestThreadQuery, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/merge-request/repair-source", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn merge_request_selector_repair( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: RepairMergeRequestSelectorRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/internal/reviewer-child-sessions", status = 204, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn merge_request_reviewer_child_register( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[body] request: RegisterReviewerChildSessionRequest, + ) -> Result<(), RepositoryApiError>; + + #[post("/api/w/{workspace_id}/tickets/{id}/merge-request/review-capabilities", status = 204, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn merge_request_review_capability_register( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: RegisterMergeRequestReviewCapabilityRequest, + ) -> Result<(), RepositoryApiError>; + + #[post("/api/w/{workspace_id}/tickets/{id}/merge-request/reviews", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn merge_request_review_submit( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: SubmitMergeRequestReviewRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/merge-request/reviews/revoke", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn merge_request_review_revoke( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: RevokeMergeRequestReviewRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/merge-request/complete", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn merge_request_complete( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: CompleteMergeRequestRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/workflow/close", status = 204, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_close_record( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: TicketCloseRecordRequest, + ) -> Result<(), RepositoryApiError>; + + #[get("/api/w/{workspace_id}/tickets/{id}/relation-view", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn ticket_relation_view( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/relations", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_relation_record( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: CreateTicketRelationRequest, + ) -> Result; + + #[delete("/api/w/{workspace_id}/tickets/{id}/relations", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_relation_remove( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: TicketRelationRemoveRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/orchestration-plans", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500])] + async fn ticket_orchestration_plan_record( + &self, + #[extension] context: ServerRequestContext, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: CreateTicketOrchestrationPlanRequest, + ) -> Result; + + #[get("/api/w/{workspace_id}/tickets/{id}", status = 200, error_status = 404, additional_error_statuses = [400, 401, 403, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_get( + &self, + #[path] workspace_id: String, + #[path] id: String, + ) -> Result; + + #[patch("/api/w/{workspace_id}/tickets/{id}", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_edit( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: BrowserEditTicketRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/show", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn ticket_show( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: TicketShowRequest, + ) -> Result; + + #[get("/api/w/{workspace_id}/tickets/{id}/assignments", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_assignment_list( + &self, + #[path] workspace_id: String, + #[path] id: String, + ) -> Result; + + #[put("/api/w/{workspace_id}/tickets/{id}/assignments/{role}", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_assignment_set( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[path] role: String, + #[body] request: SetTicketRoleAssignmentRequest, + ) -> Result; + + #[delete("/api/w/{workspace_id}/tickets/{id}/assignments/{role}", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_assignment_clear( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[path] role: String, + #[query] query: ClearTicketRoleAssignmentQuery, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/implementation-cancellations", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_implementation_cancel( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: CancelTicketImplementationRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/state", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_state_transition( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: BrowserTransitionTicketStateRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/ready", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_ready( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: TicketMarkReadyRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/events", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_event_append( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: BrowserAppendTicketEventRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/queue", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_queue( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: BrowserQueueTicketRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/tickets/{id}/close", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn ticket_close( + &self, + #[path] workspace_id: String, + #[path] id: String, + #[body] request: BrowserCloseTicketRequest, + ) -> Result; + + #[get("/api/objectives", status = 200, error_status = 400, additional_error_statuses = [500])] + async fn objective_list_alias( + &self, + #[query] query: ObjectiveListQuery, + ) -> Result; + + #[get("/api/w/{workspace_id}/objectives", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500], bearer_auth = true, browser_auth = true)] + async fn objective_list( + &self, + #[path] workspace_id: String, + #[query] query: ObjectiveListQuery, + ) -> Result; + + #[post("/api/w/{workspace_id}/objectives", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn objective_create( + &self, + #[path] workspace_id: String, + #[body] request: ObjectiveCreateRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/objectives/query", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn objective_query( + &self, + #[path] workspace_id: String, + #[body] request: ObjectiveQueryRequest, + ) -> Result; + + #[get("/api/objectives/{id}", status = 200, error_status = 404, additional_error_statuses = [400, 500])] + async fn objective_get_alias( + &self, + #[path] id: String, + ) -> Result; + + #[get("/api/w/{workspace_id}/objectives/{objective_id}", status = 200, error_status = 404, additional_error_statuses = [400, 401, 403, 500], bearer_auth = true, browser_auth = true)] + async fn objective_get( + &self, + #[path] workspace_id: String, + #[path] objective_id: String, + ) -> Result; + + #[patch("/api/w/{workspace_id}/objectives/{objective_id}", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn objective_edit( + &self, + #[path] workspace_id: String, + #[path] objective_id: String, + #[body] request: ObjectiveEditRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/objectives/{objective_id}/show", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500])] + async fn objective_show( + &self, + #[path] workspace_id: String, + #[path] objective_id: String, + #[body] request: ObjectiveShowRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/objectives/{objective_id}/state", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn objective_state_set( + &self, + #[path] workspace_id: String, + #[path] objective_id: String, + #[body] request: ObjectiveStateRequest, + ) -> Result; + + #[post("/api/w/{workspace_id}/objectives/{objective_id}/ticket-links", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn objective_ticket_link( + &self, + #[path] workspace_id: String, + #[path] objective_id: String, + #[body] request: ObjectiveLinkTicketRequest, + ) -> Result; + + #[delete("/api/w/{workspace_id}/objectives/{objective_id}/ticket-links/{ticket_id}", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 409, 500], bearer_auth = true, browser_auth = true)] + async fn objective_ticket_unlink( + &self, + #[path] workspace_id: String, + #[path] objective_id: String, + #[path] ticket_id: String, + ) -> Result; } /// Digest of the fully rendered canonical contract with its digest slot normalized. @@ -947,10 +1488,27 @@ pub fn canonical_openapi_document() /// /// Generated clients and OpenAPI omit extension parameters; operation implementations use this /// value instead of re-parsing transport headers inside domain handlers. -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct ServerRequestContext { pub actor: Option, pub origin: Option, + /// Transport headers retained for Server-side authentication adapters. + /// + /// Generated clients and OpenAPI do not expose this extension. Values stay byte-exact so the + /// Workspace Server can reuse the existing Runtime source-proof and browser-session authority + /// while generated Axum routes replace only the handwritten route registration. + pub transport_headers: Vec<(String, Vec)>, +} + +impl std::fmt::Debug for ServerRequestContext { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter + .debug_struct("ServerRequestContext") + .field("actor", &self.actor) + .field("origin", &self.origin) + .field("transport_header_count", &self.transport_headers.len()) + .finish() + } } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] @@ -2933,9 +3491,10 @@ pub struct WorkingDirectoryCreateResponse { pub diagnostics: Vec, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] pub struct ListResponse { pub workspace_id: String, + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] pub limit: usize, pub items: Vec, pub source: String, @@ -2943,19 +3502,28 @@ pub struct ListResponse { pub diagnostics: Vec, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, JsonSchema)] #[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] pub struct QueryPage { + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] pub limit: usize, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] pub returned: usize, pub has_more: bool, pub next_cursor: Option, pub sort: String, + #[cfg_attr(feature = "typescript", ts(type = "number | null"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] pub source_limit: Option, pub source_truncated: bool, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] pub struct ObjectiveEventDetail { pub event_ref: String, pub kind: String, @@ -2963,7 +3531,9 @@ pub struct ObjectiveEventDetail { pub created_at: String, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] pub struct ObjectiveLinkedTicketSummary { pub id: String, pub resource_key: String, @@ -2971,15 +3541,21 @@ pub struct ObjectiveLinkedTicketSummary { pub state: String, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] pub struct ObjectiveResourceSummary { pub path: String, pub media_type: Option, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] pub bytes: usize, pub updated_at: String, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] pub struct ObjectiveSummary { pub id: String, pub resource_key: String, @@ -2992,7 +3568,9 @@ pub struct ObjectiveSummary { pub record_source: String, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] pub struct ObjectiveDetail { pub id: String, pub resource_key: String, @@ -3011,7 +3589,9 @@ pub struct ObjectiveDetail { pub record_source: String, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] pub struct ObjectiveCreateRequest { pub title: String, #[serde(default)] @@ -3026,7 +3606,9 @@ fn default_objective_state() -> String { "active".to_string() } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] pub struct ObjectiveEditRequest { pub title: Option, pub old_string: Option, @@ -3035,17 +3617,1005 @@ pub struct ObjectiveEditRequest { pub replace_all: bool, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] pub struct ObjectiveStateRequest { pub state: String, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] pub struct ObjectiveLinkTicketRequest { pub ticket_id: String, } -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +/// One malformed project record reported by a bounded list projection. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct InvalidProjectRecord { + pub label: String, + pub reason: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketListItemSummary { + pub id: String, + pub resource_key: String, + pub title: String, + pub state: String, + pub priority: String, + pub updated_at: Option, + pub queued_by: Option, + pub queued_at: Option, + pub workspace_action_priority: String, + pub record_source: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct TicketListHttpQuery { + pub states: Option, + #[schemars(range(min = 0, max = 1000))] + pub limit: Option, + pub cursor: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketListResponse { + pub workspace_id: String, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 1000))] + pub limit: usize, + pub items: Vec, + pub page: QueryPage, + pub invalid_records: Vec, + pub record_authority: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketEventDetail { + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] + pub sequence: usize, + pub event_ref: String, + pub kind: String, + pub author: Option, + pub at: Option, + pub status: Option, + pub from: Option, + pub to: Option, + pub reason: Option, + pub state_field: Option, + pub heading: Option, + pub body: Option, + pub attributes: BTreeMap, + pub references: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketDetailRelation { + pub ticket_id: String, + pub kind: String, + pub target: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "typescript", ts(optional = nullable))] + pub target_resource_key: Option, + pub note: Option, + pub author: String, + pub at: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketDetailDerivedRelation { + pub source_ticket: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "typescript", ts(optional = nullable))] + pub source_resource_key: Option, + pub inverse_kind: String, + pub forward_kind: String, + pub note: Option, + pub author: String, + pub at: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketDetailRelationBlocker { + pub blocking_ticket: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "typescript", ts(optional = nullable))] + pub blocking_resource_key: Option, + pub reason_kind: String, + pub relation_kind: String, + pub note: Option, + pub blocking_state: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketDetailRelationNotice { + pub related_ticket: String, + pub kind: String, + pub message: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketDetailRelationView { + pub outgoing: Vec, + pub incoming: Vec, + pub blockers: Vec, + pub notices: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct ObjectiveLinkSummary { + pub id: String, + pub resource_key: String, + pub title: String, + pub state: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketEvidenceEvent { + pub event_ref: String, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] + pub sequence: usize, + pub kind: String, + pub at: Option, + pub author: Option, + pub excerpt: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketAssignmentSummary { + pub assignment_id: String, + pub runtime_id: String, + pub worker_id: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "typescript", ts(optional = nullable))] + pub worker_resource_key: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)] +#[cfg_attr(feature = "typescript", ts(tag = "kind", rename_all = "snake_case"))] +pub enum TicketAssignmentPrincipal { + User { + account_id: String, + }, + Worker { + runtime_id: String, + worker_id: String, + }, + WorkspaceAgent { + agent_key: String, + }, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(rename_all = "snake_case")] +pub enum TicketAssignmentRole { + Orchestrator, + Coder, + Owner, + Contributor, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketRoleAssignmentRecord { + pub workspace_id: String, + pub ticket_id: String, + pub assignment_id: String, + pub role: TicketAssignmentRole, + pub principal: TicketAssignmentPrincipal, + pub assigned_by: String, + pub assigned_at: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketRoleAssignmentSummary { + pub assignment_id: String, + pub role: String, + pub principal: TicketAssignmentPrincipal, + pub assigned_by: String, + pub assigned_at: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketActionEligibility { + pub can_assign_orchestrator: bool, + pub can_unassign_orchestrator: bool, + pub can_queue: bool, + pub can_start_manual_coder: bool, + pub queue_tickets: Vec, + pub blockers: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketMergeRequestSummary { + pub merge_request_id: String, + pub repository_key: String, + pub state: String, + pub review_status: String, + pub selector_from: Option, + pub selector_to: String, + pub updated_at: String, + pub current_subject_ref: Option, + pub review_subject_ref: Option, + pub review_requested_at: Option, + pub review_submitted_at: Option, + pub review_excerpt: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct MergeRequestRefDiagnostic { + pub code: String, + pub message: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct MergeRequestListItem { + pub summary: TicketMergeRequestSummary, + pub ticket_ids: Vec, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] + pub thread_event_count: usize, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub ref_diagnostics: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct MergeRequestListResponse { + pub items: Vec, + pub next_cursor: Option, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketEvidenceSummary { + pub has_merge_request: bool, + pub has_current_subject_ref: bool, + pub has_review_request: bool, + pub has_commit: bool, + pub review_status: Option, + pub approved_current_subject: bool, + pub review_after_rescope: bool, + pub unresolved_request_changes: bool, + pub complete_for_integration: bool, + pub missing: Vec, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketQueryRequest { + pub query: Option, + #[serde(default)] + pub states: Vec, + #[serde(default)] + pub event_kinds: Vec, + #[serde(default)] + pub evidence: Vec, + pub review_status: Option, + #[serde(default)] + pub attention: Vec, + pub related_ticket_id: Option, + pub relation_kind: Option, + pub linked_objective_id: Option, + pub updated_after: Option, + pub updated_before: Option, + pub sort: Option, + #[schemars(range(min = 0, max = 1000))] + pub limit: Option, + pub cursor: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketQueryItem { + pub id: String, + pub resource_key: String, + pub title: String, + pub state: String, + pub readiness: Option, + pub priority: String, + pub created_at: Option, + pub updated_at: Option, + pub item_revision: String, + pub workspace_action_priority: String, + pub matched_fields: Vec, + pub snippet: Option, + pub matching_event: Option, + pub linked_objective_ids: Vec, + pub linked_objective_keys: Vec, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] + pub relation_count: usize, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] + pub blocker_count: usize, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] + pub unresolved_blocker_count: usize, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] + pub unresolved_review_count: usize, + pub evidence: TicketEvidenceSummary, + pub merge_request: Option, + pub current_coder: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketQueryResponse { + pub items: Vec, + pub page: QueryPage, + pub record_authority: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketShowRequest { + #[schemars(range(min = 0, max = 1000))] + pub event_limit: Option, + pub event_cursor: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketDetail { + pub id: String, + pub resource_key: String, + pub title: String, + pub state: String, + pub readiness: Option, + pub priority: String, + pub created_at: Option, + pub updated_at: Option, + pub item_revision: String, + pub queued_by: Option, + pub queued_at: Option, + pub repository_key: Option, + pub ref_selector: Option, + pub risk_flags: Vec, + pub body: String, + pub body_truncated: bool, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] + pub event_count: usize, + pub events: Vec, + pub event_page: QueryPage, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] + pub artifact_count: usize, + pub artifacts: Vec, + pub relations: TicketDetailRelationView, + pub linked_objectives: Vec, + pub implementation_reports: Vec, + pub assignments: Vec, + pub current_coder: Option, + pub assignment_diagnostics: Vec, + pub action_eligibility: TicketActionEligibility, + pub merge_request: Option, + pub evidence: TicketEvidenceSummary, + pub resolution: Option, + pub record_source: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct DefaultIntakeReadyBodyRequest { + pub from: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(transparent)] +pub struct TextResponse(pub String); + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct TicketSummarySearchQuery { + pub state: Option, + #[schemars(range(min = 0, max = 1000))] + pub limit: Option, +} + +macro_rules! transparent_ticket_dto { + ($name:ident, $inner:ty) => { + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] + #[serde(transparent)] + pub struct $name(pub $inner); + }; +} + +transparent_ticket_dto!(TicketRecord, ticket::Ticket); +transparent_ticket_dto!(TicketRecordRef, ticket::TicketRef); +transparent_ticket_dto!(TicketRecordSummaryList, Vec); +transparent_ticket_dto!(TicketDependencyCheckResponse, ticket::TicketDependencyCheck); +transparent_ticket_dto!(TicketQueueResponse, ticket::TicketQueueOutcome); +transparent_ticket_dto!(TicketDoctorResponse, ticket::TicketDoctorReport); +transparent_ticket_dto!(TicketRelationRecord, ticket::TicketRelation); +transparent_ticket_dto!(TicketRelationRecordList, Vec); +transparent_ticket_dto!(TicketRelationRecordView, ticket::TicketRelationView); +transparent_ticket_dto!( + TicketOrchestrationPlanRecord, + ticket::OrchestrationPlanRecord +); +transparent_ticket_dto!( + TicketOrchestrationPlanRecordList, + Vec +); +transparent_ticket_dto!(CreateTicketRecordRequest, ticket::NewTicket); +transparent_ticket_dto!(EditTicketRecordItemRequest, ticket::TicketItemEdit); +transparent_ticket_dto!(TicketThreadEventRequest, ticket::NewTicketEvent); +transparent_ticket_dto!(TicketStateChangeRequest, ticket::TicketStateChange); +transparent_ticket_dto!(TicketIntakeSummaryRequest, ticket::TicketIntakeSummary); +transparent_ticket_dto!(TicketCloseRecordRequest, ticket::MarkdownText); +transparent_ticket_dto!(CreateTicketRelationRequest, ticket::NewTicketRelation); +transparent_ticket_dto!( + CreateTicketOrchestrationPlanRequest, + ticket::NewOrchestrationPlanRecord +); + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct TicketMarkReadyRequest { + pub operation_key: String, + #[serde(default)] + pub reason: Option, + #[serde(default)] + pub intake_summary: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct TicketRelationRemoveRequest { + pub kind: ticket::TicketRelationKind, + pub target: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct TicketRelationSearchRequest { + pub ticket: Option, + pub kind: Option, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct TicketOrchestrationPlanSearchRequest { + pub ticket: Option, + pub kind: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct SetTicketRoleAssignmentRequest { + pub operation_id: String, + pub principal: TicketAssignmentPrincipal, + pub expected_assignment_id: Option, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct ClearTicketRoleAssignmentQuery { + pub operation_id: Option, + pub assignment_id: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct CancelTicketImplementationRequest { + pub operation_id: String, + pub assignment_id: String, + pub reason: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketRoleAssignmentsResponse { + pub workspace_id: String, + pub ticket_id: String, + pub assignments: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct TicketRoleAssignmentMutationResponse { + pub workspace_id: String, + pub ticket_id: String, + pub assignment: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(tag = "action", rename_all = "snake_case", deny_unknown_fields)] +#[cfg_attr(feature = "typescript", ts(tag = "action", rename_all = "snake_case"))] +pub enum BrowserTicketTargetEdit { + Set { + repository_key: String, + ref_selector: Option, + }, + Clear, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(rename_all = "snake_case")] +pub enum BrowserTicketWorkflowState { + Planning, + Ready, + Queued, + Inprogress, + Done, + Closed, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct BrowserEditTicketRequest { + pub title: Option, + pub body: Option, + pub old_string: Option, + pub new_string: Option, + #[serde(default)] + pub replace_all: bool, + pub target: Option, + pub author: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct BrowserTransitionTicketStateRequest { + pub state: BrowserTicketWorkflowState, + pub reason: Option, + pub body: Option, + pub author: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(rename_all = "snake_case")] +pub enum BrowserTicketThreadRole { + Comment, + Plan, + Decision, + ImplementationReport, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct BrowserAppendTicketEventRequest { + pub role: BrowserTicketThreadRole, + pub body: String, + pub author: Option, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct BrowserQueueTicketRequest {} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct BrowserCloseTicketRequest { + pub resolution: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct ObjectiveListQuery { + #[schemars(range(min = 0, max = 1000))] + pub limit: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct ObjectiveListResponse { + pub workspace_id: String, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 1000))] + pub limit: usize, + pub items: Vec, + pub invalid_records: Vec, + pub record_authority: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct ObjectiveQueryRequest { + pub query: Option, + #[serde(default)] + pub states: Vec, + pub linked_ticket_id: Option, + pub updated_after: Option, + pub updated_before: Option, + pub sort: Option, + #[schemars(range(min = 0, max = 1000))] + pub limit: Option, + pub cursor: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct ObjectiveQueryItem { + pub id: String, + pub resource_key: String, + pub title: String, + pub state: String, + pub created_at: Option, + pub updated_at: Option, + pub matched_fields: Vec, + pub snippet: Option, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_usize))] + pub linked_ticket_count: usize, + pub linked_tickets: Vec, + pub linked_ticket_keys: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct ObjectiveQueryResponse { + pub items: Vec, + pub page: QueryPage, + pub record_authority: String, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct ObjectiveShowRequest { + #[schemars(range(min = 0, max = 1000))] + pub event_limit: Option, + pub event_cursor: Option, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(rename_all = "snake_case")] +pub enum MergeRequestState { + Open, + Merged, + Closed, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(rename_all = "snake_case")] +pub enum ReviewDecision { + Approve, + RequestChanges, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(rename_all = "snake_case")] +pub enum FindingSeverity { + Blocker, + Major, + Minor, + Note, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct ReviewFinding { + pub severity: FindingSeverity, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "typescript", ts(optional = nullable))] + pub code: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "typescript", ts(optional = nullable))] + pub path: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "typescript", ts(optional = nullable))] + pub line: Option, + pub body: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct MergeRequestWorkerIdentity { + pub runtime_id: String, + pub worker_id: String, +} + +macro_rules! merge_request_event { + ($name:ident { $($field:ident : $ty:ty),* $(,)? }) => { + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] + #[cfg_attr(feature = "typescript", derive(ts_rs::TS))] + #[serde(deny_unknown_fields)] + pub struct $name { + pub event_id: String, + #[cfg_attr(feature = "typescript", ts(type = "number"))] + #[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))] + pub sequence: u64, + $(pub $field: $ty,)* + pub created_at: String, + } + }; +} + +merge_request_event!(ReviewRequestedEvent { + subject_ref: String, + requested_by: MergeRequestWorkerIdentity, + reviewer: MergeRequestWorkerIdentity, +}); +merge_request_event!(ReviewEvent { + request_event_id: String, + subject_ref: String, + decision: ReviewDecision, + body: String, + findings: Vec, + reviewer: MergeRequestWorkerIdentity, +}); +merge_request_event!(ReviewRevokedEvent { + review_event_id: String, + subject_ref: String, + reason: String, + revoked_by: MergeRequestWorkerIdentity, +}); +merge_request_event!(ReviewCancelledEvent { + request_event_id: String, + subject_ref: String, + reason: String, +}); +merge_request_event!(MergeRequestCommentEvent { + body: String, + author: MergeRequestWorkerIdentity, +}); + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(rename_all = "snake_case")] +pub enum MergeStrategy { + FastForward, + Merge, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(rename_all = "snake_case")] +pub enum ConflictResolution { + None, + Clean, + ConflictsResolved, +} + +merge_request_event!(MergeEvent { + operation_id: String, + approval_event_id: String, + approved_source_ref: String, + target_ref_before: String, + target_ref_after: String, + strategy: MergeStrategy, + resolution: ConflictResolution, + merged_by: MergeRequestWorkerIdentity, +}); + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(tag = "kind", rename_all = "snake_case")] +pub enum MergeRequestThreadEvent { + ReviewRequested(ReviewRequestedEvent), + Review(ReviewEvent), + ReviewRevoked(ReviewRevokedEvent), + ReviewCancelled(ReviewCancelledEvent), + Comment(MergeRequestCommentEvent), + Merge(MergeEvent), +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct PublicMergeRequest { + pub workspace_id: String, + pub merge_request_id: String, + pub repository_key: String, + pub state: MergeRequestState, + pub selector_from: Option, + pub selector_to: String, + pub ticket_ids: Vec, + pub created_at: String, + pub updated_at: String, + pub thread: Vec, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct MergeRequestListQuery { + pub state: Option, + pub repository_key: Option, + pub ticket_ref: Option, + pub selector_from: Option, + pub selector_to: Option, + pub cursor: Option, + #[schemars(range(min = 0, max = 1000))] + pub limit: Option, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct MergeRequestThreadQuery { + #[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))] + pub after: Option, + #[schemars(range(min = 0, max = 1000))] + pub limit: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct MergeRequestRefResponse { + pub status: String, + #[serde(rename = "ref")] + pub revision_ref: Option, + pub observed_at: String, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "typescript", ts(optional = nullable))] + pub diagnostic: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct MergeRequestLinkedTicketResponse { + pub ticket_id: String, + pub key: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct MergeRequestDetailResponse { + #[serde(flatten)] + pub merge_request: PublicMergeRequest, + pub source: MergeRequestRefResponse, + pub target: MergeRequestRefResponse, + pub linked_tickets: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[cfg_attr(feature = "typescript", derive(ts_rs::TS))] +#[serde(deny_unknown_fields)] +pub struct MergeRequestReadinessResponse { + pub ready: bool, + pub blockers: Vec, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "typescript", ts(optional = nullable))] + pub subject_ref: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "typescript", ts(optional = nullable))] + pub review: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(transparent)] +pub struct MergeRequestThreadResponse(pub Vec); + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct OpenMergeRequestRequest { + pub repository_key: String, + pub selector_from: String, + pub selector_to: String, + #[serde(default)] + pub summary: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct RepairMergeRequestSelectorRequest { + pub selector_from: String, + pub reason: String, + pub explicit_confirmation: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct RevokeMergeRequestReviewRequest { + pub review_event_id: String, + pub reason: String, + pub explicit_confirmation: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct RegisterReviewerChildSessionRequest { + pub child_session_id: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct RegisterMergeRequestReviewCapabilityRequest { + pub child_session_id: String, + pub capability_token: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct SubmitMergeRequestReviewRequest { + pub capability_token: String, + pub decision: ReviewDecision, + #[serde(default)] + pub body: String, + #[serde(default)] + pub findings: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] +#[serde(deny_unknown_fields)] +pub struct CompleteMergeRequestRequest { + pub operation_id: String, + pub approval_event_id: String, + pub target_ref_before: String, + pub target_ref_after: String, + pub strategy: MergeStrategy, + pub resolution: ConflictResolution, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] #[cfg_attr(feature = "typescript", derive(ts_rs::TS))] #[serde(rename_all = "snake_case")] pub enum RuntimeSourceKind { @@ -5123,6 +6693,61 @@ mod tests { } } + #[test] + fn ticket_objective_and_merge_request_operations_are_in_server_api_metadata() { + let operations = ServerApiMetadata::OPERATIONS; + assert_eq!( + operations + .iter() + .filter(|operation| operation.operation_id.starts_with("ticket_")) + .count(), + 37 + ); + assert_eq!( + operations + .iter() + .filter(|operation| operation.operation_id.starts_with("objective_")) + .count(), + 11 + ); + assert_eq!( + operations + .iter() + .filter(|operation| operation.operation_id.starts_with("merge_request_")) + .count(), + 11 + ); + for (operation_id, method, path) in [ + ( + "ticket_relation_query", + HttpMethod::Post, + "/api/w/{workspace_id}/tickets/relations/search", + ), + ( + "ticket_orchestration_plan_query", + HttpMethod::Post, + "/api/w/{workspace_id}/tickets/orchestration-plans/search", + ), + ( + "merge_request_complete", + HttpMethod::Post, + "/api/w/{workspace_id}/tickets/{id}/merge-request/complete", + ), + ( + "objective_ticket_unlink", + HttpMethod::Delete, + "/api/w/{workspace_id}/objectives/{objective_id}/ticket-links/{ticket_id}", + ), + ] { + let operation = operations + .iter() + .find(|operation| operation.operation_id == operation_id) + .unwrap_or_else(|| panic!("missing ServerApi operation {operation_id}")); + assert_eq!(operation.method, method, "{operation_id}"); + assert_eq!(operation.path, path, "{operation_id}"); + } + } + #[test] fn workspace_configuration_domain_operations_are_in_server_api_metadata() { let operations = ServerApiMetadata::OPERATIONS; diff --git a/crates/ticket/src/lib.rs b/crates/ticket/src/lib.rs index 56531a027..3dba32a05 100644 --- a/crates/ticket/src/lib.rs +++ b/crates/ticket/src/lib.rs @@ -133,7 +133,19 @@ fn sqlite_err(error: impl std::fmt::Display) -> TicketError { TicketError::Sqlite(error.to_string()) } -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Serialize, + Deserialize, + schemars::JsonSchema, +)] pub enum TicketStatus { Open, Closed, @@ -162,7 +174,9 @@ impl fmt::Display for TicketStatus { } } -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[derive( + Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, schemars::JsonSchema, +)] pub enum ExtensibleTicketStatus { Open, Closed, @@ -206,7 +220,19 @@ impl From for ExtensibleTicketStatus { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Serialize, + Deserialize, + schemars::JsonSchema, +)] #[serde(rename_all = "snake_case")] pub enum TicketWorkflowState { Planning, @@ -273,7 +299,7 @@ impl fmt::Display for TicketWorkflowState { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct MarkdownText(pub String); impl MarkdownText { @@ -298,7 +324,7 @@ impl From for MarkdownText { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub enum TicketIdOrSlug { Id(String), Slug(String), @@ -325,7 +351,7 @@ impl From for TicketIdOrSlug { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(rename_all = "snake_case")] pub enum TicketEventKind { Create, @@ -390,13 +416,13 @@ impl From<&str> for TicketEventKind { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketReference { pub kind: String, pub target: String, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct NewTicketEvent { pub kind: TicketEventKind, pub author: Option, @@ -415,7 +441,7 @@ impl NewTicketEvent { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketStateChange { pub from: String, pub to: String, @@ -443,7 +469,7 @@ impl TicketStateChange { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketIntakeSummary { pub author: Option, pub body: MarkdownText, @@ -460,7 +486,7 @@ impl TicketIntakeSummary { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct NewTicket { pub title: String, pub slug: Option, @@ -533,7 +559,7 @@ pub trait TicketTargetAuthority: Send + Sync { ) -> Result; } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketMarkReady { pub operation_key: String, #[serde(default, skip_serializing_if = "Option::is_none")] @@ -685,7 +711,7 @@ fn validate_generic_state_change( Ok(()) } -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketItemEdit { pub title: Option, /// Whole-body replacement for legacy authoring surfaces. Prefer `body_replacement` @@ -697,7 +723,7 @@ pub struct TicketItemEdit { pub author: Option, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketBodyReplacement { pub old_string: String, pub new_string: String, @@ -787,7 +813,7 @@ impl TicketBodyReplacement { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketDependencyCheck { pub ticket: TicketSummary, pub blockers: Vec, @@ -796,7 +822,7 @@ pub struct TicketDependencyCheck { pub recommended_action: TicketWorkspaceNextAction, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketQueueOutcome { pub requested_ticket: String, pub queued_tickets: Vec, @@ -923,7 +949,7 @@ impl TicketListQuery { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketRef { pub id: String, #[serde(default, skip_serializing_if = "Option::is_none")] @@ -932,7 +958,19 @@ pub struct TicketRef { pub status: TicketStatus, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Serialize, + Deserialize, + schemars::JsonSchema, +)] #[serde(rename_all = "snake_case")] pub enum TicketRelationKind { DependsOn, @@ -971,7 +1009,7 @@ impl fmt::Display for TicketRelationKind { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct NewTicketRelation { pub kind: TicketRelationKind, pub target: String, @@ -979,7 +1017,7 @@ pub struct NewTicketRelation { pub author: Option, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(deny_unknown_fields)] pub struct TicketRelation { pub ticket_id: String, @@ -991,7 +1029,7 @@ pub struct TicketRelation { pub at: String, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct DerivedTicketRelation { pub source_ticket: String, pub inverse_kind: String, @@ -1001,7 +1039,7 @@ pub struct DerivedTicketRelation { pub at: String, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketRelationBlocker { pub blocking_ticket: String, pub reason_kind: String, @@ -1010,14 +1048,14 @@ pub struct TicketRelationBlocker { pub blocking_state: TicketWorkflowState, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketRelationNotice { pub related_ticket: String, pub kind: TicketRelationKind, pub message: String, } -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketRelationView { pub outgoing: Vec, pub incoming: Vec, @@ -1033,7 +1071,7 @@ pub enum TicketWorkspaceActionPriority { Background, } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(rename_all = "snake_case")] pub enum TicketWorkspaceNextAction { Clarify, @@ -1057,7 +1095,7 @@ pub struct TicketWorkspaceStateOverlay { pub workflow_state: TicketWorkflowState, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketQueueGuard { pub can_queue_for_orchestrator: bool, pub reason: Option, @@ -1473,7 +1511,19 @@ fn format_workspace_relation_blockers(blockers: &[&TicketRelationBlocker]) -> St formatted } -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] +#[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Serialize, + Deserialize, + schemars::JsonSchema, +)] #[serde(rename_all = "snake_case")] pub enum OrchestrationPlanKind { Before, @@ -1533,7 +1583,7 @@ impl fmt::Display for OrchestrationPlanKind { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(deny_unknown_fields)] pub struct AcceptedOrchestrationPlan { pub summary: String, @@ -1545,7 +1595,7 @@ pub struct AcceptedOrchestrationPlan { pub role_plan: Option, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct NewOrchestrationPlanRecord { pub kind: OrchestrationPlanKind, pub related_ticket: Option, @@ -1554,7 +1604,7 @@ pub struct NewOrchestrationPlanRecord { pub author: Option, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(deny_unknown_fields)] pub struct OrchestrationPlanRecord { pub id: String, @@ -1570,7 +1620,7 @@ pub struct OrchestrationPlanRecord { pub at: String, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketMeta { pub id: String, #[serde(default, skip_serializing_if = "Option::is_none")] @@ -1596,7 +1646,7 @@ pub struct TicketMeta { pub raw: BTreeMap, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketSummary { pub id: String, #[serde(default, skip_serializing_if = "Option::is_none")] @@ -1651,13 +1701,13 @@ pub struct SqliteTicketListPage { pub next: Option, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketDocument { pub body: MarkdownText, pub raw_frontmatter: BTreeMap, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketEvent { pub kind: TicketEventKind, pub author: Option, @@ -1673,13 +1723,13 @@ pub struct TicketEvent { pub attributes: BTreeMap, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketArtifactRef { /// Path relative to the ticket's `artifacts/` directory. pub relative_path: PathBuf, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct Ticket { pub meta: TicketMeta, pub document: TicketDocument, @@ -1689,20 +1739,20 @@ pub struct Ticket { pub resolution: Option, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub enum TicketDoctorSeverity { Error, Warning, } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketDoctorDiagnostic { pub severity: TicketDoctorSeverity, pub message: String, pub path: Option, } -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TicketDoctorReport { pub diagnostics: Vec, } diff --git a/crates/workspace-server/src/server.rs b/crates/workspace-server/src/server.rs index dbcf5f3c3..4d5bb7ee4 100644 --- a/crates/workspace-server/src/server.rs +++ b/crates/workspace-server/src/server.rs @@ -11,10 +11,10 @@ use axum::extract::{DefaultBodyLimit, Extension, Path as AxumPath, Query, Reques use axum::http::header::{ CACHE_CONTROL, CONTENT_TYPE, ETAG, IF_NONE_MATCH, LOCATION, ORIGIN, SET_COOKIE, }; -use axum::http::{HeaderMap, Method, StatusCode, Uri}; +use axum::http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, Uri}; use axum::middleware::{self, Next}; use axum::response::{IntoResponse, Response}; -use axum::routing::{delete, get, patch, post, put}; +use axum::routing::{delete, get, post, put}; use axum::{Json, Router}; use chrono::{Duration, SecondsFormat, Utc}; use config_source::ConfigTreeSnapshot; @@ -55,9 +55,9 @@ use server_api::{ RuntimeRemovalOperationState as ApiRuntimeRemovalOperationState, RuntimeTrustAuditAction, RuntimeTrustAuditEntry, RuntimeTrustConflictKind, RuntimeTrustConflictResponse, RuntimeTrustKeyRevealResponse, RuntimeTrustKeyState, RuntimeTrustKeyStatus, - TICKET_ORCHESTRATION_PLANS_QUERY_PATH, TICKET_RELATIONS_QUERY_PATH, UpdateRemoteRuntimeRequest, - UpdateWorkspaceMetadataRequest, WhoamiResponse, WorkerLaunchOptionsResponse, - WorkerLaunchProfileCandidate, WorkerLaunchRuntimeOption, WorkerLaunchWorkerSummary, + UpdateRemoteRuntimeRequest, UpdateWorkspaceMetadataRequest, WhoamiResponse, + WorkerLaunchOptionsResponse, WorkerLaunchProfileCandidate, WorkerLaunchRuntimeOption, + WorkerLaunchWorkerSummary, WorkingDirectoryCreateRequest as BrowserWorkingDirectoryCreateRequest, WorkingDirectoryCreateResponse as BrowserWorkingDirectoryCreateResponse, WorkingDirectoryDetailResponse as BrowserWorkingDirectoryDetailResponse, @@ -75,6 +75,8 @@ use server_api::{ WorkspaceSigningIdentityState, WorkspaceSummary, WorkspaceWorkerDiscoveryItem, WorkspaceWorkerDiscoveryPage, WorkspaceWorkerSubject, }; +#[cfg(test)] +use server_api::{TICKET_ORCHESTRATION_PLANS_QUERY_PATH, TICKET_RELATIONS_QUERY_PATH}; use sha2::{Digest, Sha256}; use ticket::{ MarkdownText, NewTicketEvent, TicketBackend, TicketBodyReplacement, TicketEventKind, @@ -3637,12 +3639,52 @@ fn build_server_auth_router(api: ServerAuthApi) -> Router { .with_state(api) } +fn server_request_context( + actor: Option, + origin: Option, + headers: &HeaderMap, +) -> server_api::ServerRequestContext { + server_api::ServerRequestContext { + actor, + origin, + transport_headers: headers + .iter() + .map(|(name, value)| (name.as_str().to_string(), value.as_bytes().to_vec())) + .collect(), + } +} + +fn contract_request_headers( + context: &server_api::ServerRequestContext, +) -> std::result::Result { + let mut headers = HeaderMap::new(); + for (name, value) in &context.transport_headers { + let name = HeaderName::from_bytes(name.as_bytes()).map_err(|error| { + server_api::RepositoryApiError::new( + StatusCode::INTERNAL_SERVER_ERROR.as_u16(), + "Internal Server Error", + format!("generated route retained an invalid request header name: {error}"), + Vec::new(), + ) + })?; + let value = HeaderValue::from_bytes(value).map_err(|error| { + server_api::RepositoryApiError::new( + StatusCode::INTERNAL_SERVER_ERROR.as_u16(), + "Internal Server Error", + format!("generated route retained an invalid request header value: {error}"), + Vec::new(), + ) + })?; + headers.append(name, value); + } + Ok(headers) +} + async fn attach_server_origin_context(mut request: Request, next: Next) -> Response { let actor = request.extensions().get::().cloned(); let origin = request_origin(request.headers()); - request - .extensions_mut() - .insert(server_api::ServerRequestContext { actor, origin }); + let context = server_request_context(actor, origin, request.headers()); + request.extensions_mut().insert(context); next.run(request).await } @@ -3667,9 +3709,8 @@ async fn attach_server_request_context( } }; let origin = request_origin(request.headers()); - request - .extensions_mut() - .insert(server_api::ServerRequestContext { actor, origin }); + let context = server_request_context(actor, origin, request.headers()); + request.extensions_mut().insert(context); next.run(request).await } @@ -3824,6 +3865,149 @@ fn generated_workspace_contract_router(service: ServerApiContractService) -> Rou .merge(server_api::server_api_axum::repository_create( service.clone(), )) + .merge(server_api::server_api_axum::ticket_list_alias( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_list(service.clone())) + .merge(server_api::server_api_axum::ticket_create_record( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_query(service.clone())) + .merge(server_api::server_api_axum::ticket_get_alias( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_default_intake_ready_body(service.clone())) + .merge(server_api::server_api_axum::ticket_summary_search( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_doctor(service.clone())) + .merge(server_api::server_api_axum::ticket_relation_query( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_orchestration_plan_query(service.clone())) + .merge(server_api::server_api_axum::ticket_record_get( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_record_item_edit( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_dependency_check( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_thread_event_add( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_state_change_add( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_intake_summary_add( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_state_field_set( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_workflow_state_set( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_mark_ready_record( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_queue_record( + service.clone(), + )) + .merge(server_api::server_api_axum::merge_request_list( + service.clone(), + )) + .merge(server_api::server_api_axum::merge_request_show( + service.clone(), + )) + .merge(server_api::server_api_axum::merge_request_open( + service.clone(), + )) + .merge(server_api::server_api_axum::merge_request_readiness( + service.clone(), + )) + .merge(server_api::server_api_axum::merge_request_thread( + service.clone(), + )) + .merge(server_api::server_api_axum::merge_request_selector_repair( + service.clone(), + )) + .merge(server_api::server_api_axum::merge_request_reviewer_child_register(service.clone())) + .merge( + server_api::server_api_axum::merge_request_review_capability_register(service.clone()), + ) + .merge(server_api::server_api_axum::merge_request_review_submit( + service.clone(), + )) + .merge(server_api::server_api_axum::merge_request_review_revoke( + service.clone(), + )) + .merge(server_api::server_api_axum::merge_request_complete( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_close_record( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_relation_view( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_relation_record( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_relation_remove( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_orchestration_plan_record(service.clone())) + .merge(server_api::server_api_axum::ticket_get(service.clone())) + .merge(server_api::server_api_axum::ticket_edit(service.clone())) + .merge(server_api::server_api_axum::ticket_show(service.clone())) + .merge(server_api::server_api_axum::ticket_assignment_list( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_assignment_set( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_assignment_clear( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_implementation_cancel( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_state_transition( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_ready(service.clone())) + .merge(server_api::server_api_axum::ticket_event_append( + service.clone(), + )) + .merge(server_api::server_api_axum::ticket_queue(service.clone())) + .merge(server_api::server_api_axum::ticket_close(service.clone())) + .merge(server_api::server_api_axum::objective_list_alias( + service.clone(), + )) + .merge(server_api::server_api_axum::objective_list(service.clone())) + .merge(server_api::server_api_axum::objective_create( + service.clone(), + )) + .merge(server_api::server_api_axum::objective_query( + service.clone(), + )) + .merge(server_api::server_api_axum::objective_get_alias( + service.clone(), + )) + .merge(server_api::server_api_axum::objective_get(service.clone())) + .merge(server_api::server_api_axum::objective_edit(service.clone())) + .merge(server_api::server_api_axum::objective_show(service.clone())) + .merge(server_api::server_api_axum::objective_state_set( + service.clone(), + )) + .merge(server_api::server_api_axum::objective_ticket_link( + service.clone(), + )) + .merge(server_api::server_api_axum::objective_ticket_unlink( + service.clone(), + )) .layer(middleware::from_fn_with_state( service.as_ref().clone(), attach_server_request_context, @@ -3836,6 +4020,12 @@ fn project_server_dto(value: &T) -> Result serde_json::from_value(value).map_err(|error| Error::RegistryInconsistency(error.to_string())) } +fn project_contract_dto( + value: &T, +) -> std::result::Result { + project_server_dto(value).map_err(|error| ApiError::from(error).into_repository_api_error()) +} + impl server_api::ServerApi for ServerApiContractService { async fn health( &self, @@ -4866,218 +5056,1060 @@ impl server_api::ServerApi for ServerApiContractService { .map(|(_status, Json(response))| response) .map_err(ApiError::into_repository_api_error) } + + async fn ticket_list_alias( + &self, + query: server_api::TicketListHttpQuery, + ) -> std::result::Result { + let query = TicketListQuery { + states: query.states, + limit: query.limit, + cursor: query.cursor, + }; + let Json(response) = list_tickets(State(self.workspace_api()?.clone()), Query(query)) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_list( + &self, + workspace_id: String, + query: server_api::TicketListHttpQuery, + ) -> std::result::Result { + let query = TicketListQuery { + states: query.states, + limit: query.limit, + cursor: query.cursor, + }; + let Json(response) = scoped_list_tickets( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + Query(query), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_create_record( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + request: server_api::CreateTicketRecordRequest, + ) -> std::result::Result { + let Json(response) = scoped_create_ticket_record( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + contract_request_headers(&context)?, + Json(request.0), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketRecordRef(response)) + } + + async fn ticket_query( + &self, + workspace_id: String, + request: server_api::TicketQueryRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_query_tickets( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_get_alias( + &self, + id: String, + ) -> std::result::Result { + let Json(response) = get_ticket(State(self.workspace_api()?.clone()), AxumPath(id)) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_default_intake_ready_body( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + request: server_api::DefaultIntakeReadyBodyRequest, + ) -> std::result::Result { + let Json(response) = scoped_default_intake_ready_body( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + contract_request_headers(&context)?, + Json(DefaultIntakeReadyBodyRequest { from: request.from }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TextResponse(response)) + } + + async fn ticket_summary_search( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + query: server_api::TicketSummarySearchQuery, + ) -> std::result::Result + { + let Json(response) = scoped_list_ticket_summaries( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + contract_request_headers(&context)?, + Query(TicketSummarySearchQuery { state: query.state }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketRecordSummaryList(response)) + } + + async fn ticket_doctor( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + ) -> std::result::Result { + let Json(response) = scoped_ticket_doctor( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + contract_request_headers(&context)?, + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketDoctorResponse(response)) + } + + async fn ticket_relation_query( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + request: server_api::TicketRelationSearchRequest, + ) -> std::result::Result + { + let Json(response) = scoped_query_ticket_relations( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + contract_request_headers(&context)?, + Json(TicketRelationSearchRequest { + ticket: request.ticket, + kind: request.kind, + }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketRelationRecordList(response)) + } + + async fn ticket_orchestration_plan_query( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + request: server_api::TicketOrchestrationPlanSearchRequest, + ) -> std::result::Result< + server_api::TicketOrchestrationPlanRecordList, + server_api::RepositoryApiError, + > { + let Json(response) = scoped_query_ticket_orchestration_plans( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + contract_request_headers(&context)?, + Json(TicketOrchestrationPlanSearchRequest { + ticket: request.ticket, + kind: request.kind, + }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketOrchestrationPlanRecordList(response)) + } + + async fn ticket_record_get( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + ) -> std::result::Result { + let Json(response) = scoped_get_ticket_record( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketRecord(response)) + } + + async fn ticket_record_item_edit( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::EditTicketRecordItemRequest, + ) -> std::result::Result { + let Json(response) = scoped_edit_ticket_record_item( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + Json(request.0), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketRecord(response)) + } + + async fn ticket_dependency_check( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + ) -> std::result::Result< + server_api::TicketDependencyCheckResponse, + server_api::RepositoryApiError, + > { + let Json(response) = scoped_ticket_dependency_check( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketDependencyCheckResponse(response)) + } + + async fn ticket_thread_event_add( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::TicketThreadEventRequest, + ) -> std::result::Result<(), server_api::RepositoryApiError> { + scoped_add_ticket_thread_event( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + Json(request.0), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(()) + } + + async fn ticket_state_change_add( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::TicketStateChangeRequest, + ) -> std::result::Result<(), server_api::RepositoryApiError> { + scoped_add_ticket_state_change( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + Json(request.0), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(()) + } + + async fn ticket_intake_summary_add( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::TicketIntakeSummaryRequest, + ) -> std::result::Result<(), server_api::RepositoryApiError> { + scoped_add_ticket_intake_summary( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + Json(request.0), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(()) + } + + async fn ticket_state_field_set( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + field: String, + request: server_api::TicketStateChangeRequest, + ) -> std::result::Result<(), server_api::RepositoryApiError> { + scoped_set_ticket_state_field( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id, field)), + contract_request_headers(&context)?, + Json(request.0), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(()) + } + + async fn ticket_workflow_state_set( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::TicketStateChangeRequest, + ) -> std::result::Result<(), server_api::RepositoryApiError> { + scoped_set_ticket_workflow_state( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + Json(request.0), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(()) + } + + async fn ticket_mark_ready_record( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::TicketMarkReadyRequest, + ) -> std::result::Result { + let Json(response) = scoped_mark_ticket_ready( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + Json(TicketMarkReadyRequest { + operation_key: request.operation_key, + reason: request.reason, + intake_summary: request.intake_summary, + }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketRecord(response)) + } + + async fn ticket_queue_record( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + ) -> std::result::Result { + let Json(response) = scoped_queue_ticket_record( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketQueueResponse(response)) + } + + async fn merge_request_list( + &self, + workspace_id: String, + query: server_api::MergeRequestListQuery, + ) -> std::result::Result + { + let query = project_contract_dto(&query)?; + let Json(response) = scoped_list_merge_requests( + State(self.workspace_api()?.clone()), + AxumPath(workspace_id), + Query(query), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn merge_request_show( + &self, + workspace_id: String, + merge_request_id: String, + query: server_api::MergeRequestThreadQuery, + ) -> std::result::Result + { + let query = project_contract_dto(&query)?; + let Json(response) = scoped_show_merge_request( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, merge_request_id)), + Query(query), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn merge_request_open( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::OpenMergeRequestRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_open_merge_request( + State(self.workspace_api()?.clone()), + contract_request_headers(&context)?, + AxumPath((workspace_id, id)), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn merge_request_readiness( + &self, + workspace_id: String, + id: String, + ) -> std::result::Result< + server_api::MergeRequestReadinessResponse, + server_api::RepositoryApiError, + > { + let Json(response) = scoped_merge_request_readiness( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn merge_request_thread( + &self, + workspace_id: String, + id: String, + query: server_api::MergeRequestThreadQuery, + ) -> std::result::Result + { + let query = project_contract_dto(&query)?; + let Json(response) = scoped_merge_request_thread( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + Query(query), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response).map(server_api::MergeRequestThreadResponse) + } + + async fn merge_request_selector_repair( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::RepairMergeRequestSelectorRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_repair_merge_request_selector( + State(self.workspace_api()?.clone()), + contract_request_headers(&context)?, + AxumPath((workspace_id, id)), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn merge_request_reviewer_child_register( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + request: server_api::RegisterReviewerChildSessionRequest, + ) -> std::result::Result<(), server_api::RepositoryApiError> { + let request = project_contract_dto(&request)?; + scoped_register_reviewer_child_session( + State(self.workspace_api()?.clone()), + contract_request_headers(&context)?, + AxumPath(workspace_id), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(()) + } + + async fn merge_request_review_capability_register( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::RegisterMergeRequestReviewCapabilityRequest, + ) -> std::result::Result<(), server_api::RepositoryApiError> { + let request = project_contract_dto(&request)?; + scoped_register_merge_request_review_capability( + State(self.workspace_api()?.clone()), + contract_request_headers(&context)?, + AxumPath((workspace_id, id)), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(()) + } + + async fn merge_request_review_submit( + &self, + workspace_id: String, + id: String, + request: server_api::SubmitMergeRequestReviewRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_submit_merge_request_review( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn merge_request_review_revoke( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::RevokeMergeRequestReviewRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_revoke_merge_request_review( + State(self.workspace_api()?.clone()), + contract_request_headers(&context)?, + AxumPath((workspace_id, id)), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn merge_request_complete( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::CompleteMergeRequestRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_complete_merge_request( + State(self.workspace_api()?.clone()), + contract_request_headers(&context)?, + AxumPath((workspace_id, id)), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_close_record( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::TicketCloseRecordRequest, + ) -> std::result::Result<(), server_api::RepositoryApiError> { + scoped_close_ticket_record( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + Json(request.0), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(()) + } + + async fn ticket_relation_view( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + ) -> std::result::Result + { + let Json(response) = scoped_ticket_relation_view( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketRelationRecordView(response)) + } + + async fn ticket_relation_record( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::CreateTicketRelationRequest, + ) -> std::result::Result { + let Json(response) = scoped_record_ticket_relation( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + Json(request.0), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketRelationRecord(response)) + } + + async fn ticket_relation_remove( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::TicketRelationRemoveRequest, + ) -> std::result::Result { + let Json(response) = scoped_remove_ticket_relation( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + Json(TicketRelationRemoveRequest { + kind: request.kind, + target: request.target, + }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketRelationRecord(response)) + } + + async fn ticket_orchestration_plan_record( + &self, + context: server_api::ServerRequestContext, + workspace_id: String, + id: String, + request: server_api::CreateTicketOrchestrationPlanRequest, + ) -> std::result::Result< + server_api::TicketOrchestrationPlanRecord, + server_api::RepositoryApiError, + > { + let Json(response) = scoped_record_ticket_orchestration_plan( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id)), + contract_request_headers(&context)?, + Json(request.0), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketOrchestrationPlanRecord(response)) + } + + async fn ticket_get( + &self, + workspace_id: String, + id: String, + ) -> std::result::Result { + let Json(response) = scoped_get_ticket( + State(self.workspace_api()?.clone()), + AxumPath(ScopedRecordPath { workspace_id, id }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_edit( + &self, + workspace_id: String, + id: String, + request: server_api::BrowserEditTicketRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_edit_ticket_item( + State(self.workspace_api()?.clone()), + AxumPath(ScopedRecordPath { workspace_id, id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_show( + &self, + workspace_id: String, + id: String, + request: server_api::TicketShowRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_show_ticket( + State(self.workspace_api()?.clone()), + AxumPath(ScopedRecordPath { workspace_id, id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_assignment_list( + &self, + workspace_id: String, + id: String, + ) -> std::result::Result< + server_api::TicketRoleAssignmentsResponse, + server_api::RepositoryApiError, + > { + let Json(response) = scoped_list_ticket_assignments( + State(self.workspace_api()?.clone()), + AxumPath(ScopedRecordPath { workspace_id, id }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_assignment_set( + &self, + workspace_id: String, + id: String, + role: String, + request: server_api::SetTicketRoleAssignmentRequest, + ) -> std::result::Result< + server_api::TicketRoleAssignmentMutationResponse, + server_api::RepositoryApiError, + > { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_set_ticket_assignment( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id, role)), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_assignment_clear( + &self, + workspace_id: String, + id: String, + role: String, + query: server_api::ClearTicketRoleAssignmentQuery, + ) -> std::result::Result< + server_api::TicketRoleAssignmentMutationResponse, + server_api::RepositoryApiError, + > { + let query = project_contract_dto(&query)?; + let Json(response) = scoped_clear_ticket_assignment( + State(self.workspace_api()?.clone()), + AxumPath((workspace_id, id, role)), + Query(query), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_implementation_cancel( + &self, + workspace_id: String, + id: String, + request: server_api::CancelTicketImplementationRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_cancel_ticket_implementation( + State(self.workspace_api()?.clone()), + AxumPath(ScopedRecordPath { workspace_id, id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_state_transition( + &self, + workspace_id: String, + id: String, + request: server_api::BrowserTransitionTicketStateRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_transition_ticket_state( + State(self.workspace_api()?.clone()), + AxumPath(ScopedRecordPath { workspace_id, id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_ready( + &self, + workspace_id: String, + id: String, + request: server_api::TicketMarkReadyRequest, + ) -> std::result::Result { + let request = TicketMarkReadyRequest { + operation_key: request.operation_key, + reason: request.reason, + intake_summary: request.intake_summary, + }; + let Json(response) = scoped_mark_ticket_ready_from_browser( + State(self.workspace_api()?.clone()), + AxumPath(ScopedRecordPath { workspace_id, id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_event_append( + &self, + workspace_id: String, + id: String, + request: server_api::BrowserAppendTicketEventRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_append_ticket_event( + State(self.workspace_api()?.clone()), + AxumPath(ScopedRecordPath { workspace_id, id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn ticket_queue( + &self, + workspace_id: String, + id: String, + request: server_api::BrowserQueueTicketRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_queue_ticket( + State(self.workspace_api()?.clone()), + AxumPath(ScopedRecordPath { workspace_id, id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + Ok(server_api::TicketQueueResponse(response)) + } + + async fn ticket_close( + &self, + workspace_id: String, + id: String, + request: server_api::BrowserCloseTicketRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_close_ticket( + State(self.workspace_api()?.clone()), + AxumPath(ScopedRecordPath { workspace_id, id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_list_alias( + &self, + query: server_api::ObjectiveListQuery, + ) -> std::result::Result + { + let Json(response) = list_objectives( + State(self.workspace_api()?.clone()), + Query(ObjectiveListQuery { limit: query.limit }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_list( + &self, + workspace_id: String, + query: server_api::ObjectiveListQuery, + ) -> std::result::Result + { + let Json(response) = scoped_list_objectives( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + Query(ObjectiveListQuery { limit: query.limit }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_create( + &self, + workspace_id: String, + request: server_api::ObjectiveCreateRequest, + ) -> std::result::Result { + let Json(response) = scoped_create_objective( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_query( + &self, + workspace_id: String, + request: server_api::ObjectiveQueryRequest, + ) -> std::result::Result + { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_query_objectives( + State(self.workspace_api()?.clone()), + AxumPath(ScopedWorkspacePath { workspace_id }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_get_alias( + &self, + id: String, + ) -> std::result::Result { + let Json(response) = get_objective(State(self.workspace_api()?.clone()), AxumPath(id)) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_get( + &self, + workspace_id: String, + objective_id: String, + ) -> std::result::Result { + let Json(response) = scoped_get_objective( + State(self.workspace_api()?.clone()), + AxumPath(ScopedObjectivePath { + workspace_id, + objective_id, + }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_edit( + &self, + workspace_id: String, + objective_id: String, + request: server_api::ObjectiveEditRequest, + ) -> std::result::Result { + let Json(response) = scoped_edit_objective( + State(self.workspace_api()?.clone()), + AxumPath(ScopedObjectivePath { + workspace_id, + objective_id, + }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_show( + &self, + workspace_id: String, + objective_id: String, + request: server_api::ObjectiveShowRequest, + ) -> std::result::Result { + let request = project_contract_dto(&request)?; + let Json(response) = scoped_show_objective( + State(self.workspace_api()?.clone()), + AxumPath(ScopedObjectivePath { + workspace_id, + objective_id, + }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_state_set( + &self, + workspace_id: String, + objective_id: String, + request: server_api::ObjectiveStateRequest, + ) -> std::result::Result { + let Json(response) = scoped_set_objective_state( + State(self.workspace_api()?.clone()), + AxumPath(ScopedObjectivePath { + workspace_id, + objective_id, + }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_ticket_link( + &self, + workspace_id: String, + objective_id: String, + request: server_api::ObjectiveLinkTicketRequest, + ) -> std::result::Result { + let Json(response) = scoped_link_objective_ticket( + State(self.workspace_api()?.clone()), + AxumPath(ScopedObjectivePath { + workspace_id, + objective_id, + }), + Json(request), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } + + async fn objective_ticket_unlink( + &self, + workspace_id: String, + objective_id: String, + ticket_id: String, + ) -> std::result::Result { + let Json(response) = scoped_unlink_objective_ticket( + State(self.workspace_api()?.clone()), + AxumPath(ScopedObjectiveTicketPath { + workspace_id, + objective_id, + ticket_id, + }), + ) + .await + .map_err(ApiError::into_repository_api_error)?; + project_contract_dto(&response) + } } fn build_inner_router(api: WorkspaceApi) -> Router { let contract_service = ServerApiContractService::Workspace(api.clone()); let auth = build_server_auth_router(ServerAuthApi::from(&api)) .merge(generated_auth_contract_router(contract_service.clone())); - let scoped_ticket_relations_query_path = - format!("/api/w/{{workspace_id}}{TICKET_RELATIONS_QUERY_PATH}"); - let scoped_ticket_orchestration_plans_query_path = - format!("/api/w/{{workspace_id}}{TICKET_ORCHESTRATION_PLANS_QUERY_PATH}"); let workspace = Router::new() - .route("/api/tickets", get(list_tickets)) - .route( - "/api/w/{workspace_id}/tickets", - get(scoped_list_tickets).post(scoped_create_ticket_record), - ) - .route( - "/api/w/{workspace_id}/tickets/query", - post(scoped_query_tickets), - ) - .route("/api/tickets/{id}", get(get_ticket)) - .route( - "/api/w/{workspace_id}/tickets/default-intake-ready-body", - post(scoped_default_intake_ready_body), - ) - .route( - "/api/w/{workspace_id}/tickets/search", - get(scoped_list_ticket_summaries), - ) - .route( - "/api/w/{workspace_id}/tickets/doctor", - get(scoped_ticket_doctor), - ) - .route( - scoped_ticket_relations_query_path.as_str(), - post(scoped_query_ticket_relations), - ) - .route( - scoped_ticket_orchestration_plans_query_path.as_str(), - post(scoped_query_ticket_orchestration_plans), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/record", - get(scoped_get_ticket_record), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/item", - patch(scoped_edit_ticket_record_item), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/dependency-check", - get(scoped_ticket_dependency_check), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/thread-events", - post(scoped_add_ticket_thread_event), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/state-changes", - post(scoped_add_ticket_state_change), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/intake-summaries", - post(scoped_add_ticket_intake_summary), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/state-fields/{field}", - post(scoped_set_ticket_state_field), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/workflow-state", - post(scoped_set_ticket_workflow_state), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/workflow/mark-ready", - post(scoped_mark_ticket_ready), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/workflow/queue", - post(scoped_queue_ticket_record), - ) - .route( - "/api/w/{workspace_id}/merge-requests", - get(scoped_list_merge_requests), - ) - .route( - "/api/w/{workspace_id}/merge-requests/{merge_request_id}", - get(scoped_show_merge_request), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/merge-request", - post(scoped_open_merge_request), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/merge-request/readiness", - get(scoped_merge_request_readiness), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/merge-request/thread", - get(scoped_merge_request_thread), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/merge-request/repair-source", - post(scoped_repair_merge_request_selector), - ) - .route( - "/api/w/{workspace_id}/internal/reviewer-child-sessions", - post(scoped_register_reviewer_child_session), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/merge-request/review-capabilities", - post(scoped_register_merge_request_review_capability), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/merge-request/reviews", - post(scoped_submit_merge_request_review), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/merge-request/reviews/revoke", - post(scoped_revoke_merge_request_review), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/merge-request/complete", - post(scoped_complete_merge_request), - ) - - .route( - "/api/w/{workspace_id}/tickets/{id}/workflow/close", - post(scoped_close_ticket_record), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/relation-view", - get(scoped_ticket_relation_view), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/relations", - post(scoped_record_ticket_relation).delete(scoped_remove_ticket_relation), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/orchestration-plans", - post(scoped_record_ticket_orchestration_plan), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}", - get(scoped_get_ticket).patch(scoped_edit_ticket_item), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/show", - post(scoped_show_ticket), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/assignments", - get(scoped_list_ticket_assignments), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/assignments/{role}", - put(scoped_set_ticket_assignment).delete(scoped_clear_ticket_assignment), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/implementation-cancellations", - post(scoped_cancel_ticket_implementation), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/state", - post(scoped_transition_ticket_state), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/ready", - post(scoped_mark_ticket_ready_from_browser), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/events", - post(scoped_append_ticket_event), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/queue", - post(scoped_queue_ticket), - ) - .route( - "/api/w/{workspace_id}/tickets/{id}/close", - post(scoped_close_ticket), - ) - .route("/api/objectives", get(list_objectives)) - .route( - "/api/w/{workspace_id}/objectives", - get(scoped_list_objectives).post(scoped_create_objective), - ) - .route( - "/api/w/{workspace_id}/objectives/query", - post(scoped_query_objectives), - ) - .route("/api/objectives/{id}", get(get_objective)) - .route( - "/api/w/{workspace_id}/objectives/{objective_id}", - get(scoped_get_objective).patch(scoped_edit_objective), - ) - .route( - "/api/w/{workspace_id}/objectives/{objective_id}/show", - post(scoped_show_objective), - ) - .route( - "/api/w/{workspace_id}/objectives/{objective_id}/state", - post(scoped_set_objective_state), - ) - .route( - "/api/w/{workspace_id}/objectives/{objective_id}/ticket-links", - post(scoped_link_objective_ticket), - ) - .route( - "/api/w/{workspace_id}/objectives/{objective_id}/ticket-links/{ticket_id}", - delete(scoped_unlink_objective_ticket), - ) .route( "/api/w/{workspace_id}/repositories/{repository_key}/ssh-connection-test", post(scoped_probe_repository_ssh_connection) diff --git a/openapi/server-api.json b/openapi/server-api.json index 8b60d309c..b2eaccb9b 100644 --- a/openapi/server-api.json +++ b/openapi/server-api.json @@ -1,6 +1,36 @@ { "components": { "schemas": { + "AcceptedOrchestrationPlan": { + "additionalProperties": false, + "properties": { + "branch": { + "type": [ + "string", + "null" + ] + }, + "role_plan": { + "type": [ + "string", + "null" + ] + }, + "summary": { + "type": "string" + }, + "worktree": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "summary" + ], + "type": "object" + }, "ActorAuthMethod": { "description": "Authentication method that established the current request actor.", "enum": [ @@ -15,6 +45,18 @@ }, "type": "array" }, + "Array_of_MergeRequestThreadEvent": { + "items": { + "$ref": "#/components/schemas/MergeRequestThreadEvent" + }, + "type": "array" + }, + "Array_of_OrchestrationPlanRecord": { + "items": { + "$ref": "#/components/schemas/OrchestrationPlanRecord" + }, + "type": "array" + }, "Array_of_RepositorySshCredential": { "items": { "$ref": "#/components/schemas/RepositorySshCredential" @@ -27,6 +69,18 @@ }, "type": "array" }, + "Array_of_TicketRelation": { + "items": { + "$ref": "#/components/schemas/TicketRelation" + }, + "type": "array" + }, + "Array_of_TicketSummary": { + "items": { + "$ref": "#/components/schemas/TicketSummary" + }, + "type": "array" + }, "AuditEvent": { "oneOf": [ { @@ -191,6 +245,204 @@ ], "type": "object" }, + "BrowserAppendTicketEventRequest": { + "additionalProperties": false, + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "body": { + "type": "string" + }, + "role": { + "$ref": "#/components/schemas/BrowserTicketThreadRole" + } + }, + "required": [ + "role", + "body" + ], + "type": "object" + }, + "BrowserCloseTicketRequest": { + "additionalProperties": false, + "properties": { + "resolution": { + "type": "string" + } + }, + "required": [ + "resolution" + ], + "type": "object" + }, + "BrowserEditTicketRequest": { + "additionalProperties": false, + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "body": { + "type": [ + "string", + "null" + ] + }, + "new_string": { + "type": [ + "string", + "null" + ] + }, + "old_string": { + "type": [ + "string", + "null" + ] + }, + "replace_all": { + "default": false, + "type": "boolean" + }, + "target": { + "anyOf": [ + { + "$ref": "#/components/schemas/BrowserTicketTargetEdit" + }, + { + "type": "null" + } + ] + }, + "title": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "BrowserQueueTicketRequest": { + "additionalProperties": false, + "type": "object" + }, + "BrowserTicketTargetEdit": { + "oneOf": [ + { + "additionalProperties": false, + "properties": { + "action": { + "const": "set", + "type": "string" + }, + "ref_selector": { + "type": [ + "string", + "null" + ] + }, + "repository_key": { + "type": "string" + } + }, + "required": [ + "action", + "repository_key" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "action": { + "const": "clear", + "type": "string" + } + }, + "required": [ + "action" + ], + "type": "object" + } + ] + }, + "BrowserTicketThreadRole": { + "enum": [ + "comment", + "plan", + "decision", + "implementation_report" + ], + "type": "string" + }, + "BrowserTicketWorkflowState": { + "enum": [ + "planning", + "ready", + "queued", + "inprogress", + "done", + "closed" + ], + "type": "string" + }, + "BrowserTransitionTicketStateRequest": { + "additionalProperties": false, + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "body": { + "type": [ + "string", + "null" + ] + }, + "reason": { + "type": [ + "string", + "null" + ] + }, + "state": { + "$ref": "#/components/schemas/BrowserTicketWorkflowState" + } + }, + "required": [ + "state" + ], + "type": "object" + }, + "CancelTicketImplementationRequest": { + "additionalProperties": false, + "properties": { + "assignment_id": { + "type": "string" + }, + "operation_id": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "required": [ + "operation_id", + "assignment_id", + "reason" + ], + "type": "object" + }, "CandidateKind": { "description": "Candidate kinds that extract is allowed to stage.", "enum": [ @@ -203,6 +455,24 @@ ], "type": "string" }, + "ClearTicketRoleAssignmentQuery": { + "additionalProperties": false, + "properties": { + "assignment_id": { + "type": [ + "string", + "null" + ] + }, + "operation_id": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, "CompiledFlowDefinition": { "additionalProperties": false, "properties": { @@ -287,6 +557,38 @@ ], "type": "object" }, + "CompleteMergeRequestRequest": { + "additionalProperties": false, + "properties": { + "approval_event_id": { + "type": "string" + }, + "operation_id": { + "type": "string" + }, + "resolution": { + "$ref": "#/components/schemas/ConflictResolution" + }, + "strategy": { + "$ref": "#/components/schemas/MergeStrategy" + }, + "target_ref_after": { + "type": "string" + }, + "target_ref_before": { + "type": "string" + } + }, + "required": [ + "operation_id", + "approval_event_id", + "target_ref_before", + "target_ref_after", + "strategy", + "resolution" + ], + "type": "object" + }, "ConfigCommitRequest": { "additionalProperties": false, "description": "Compare-and-swap request for applying a complete set of source-tree changes.", @@ -542,6 +844,14 @@ ], "type": "object" }, + "ConflictResolution": { + "enum": [ + "none", + "clean", + "conflicts_resolved" + ], + "type": "string" + }, "ConsolidationAudit": { "properties": { "consumed_staging_ids": { @@ -658,6 +968,18 @@ ], "type": "object" }, + "DefaultIntakeReadyBodyRequest": { + "additionalProperties": false, + "properties": { + "from": { + "type": "string" + } + }, + "required": [ + "from" + ], + "type": "object" + }, "DeleteRepositorySshCredentialRequest": { "additionalProperties": false, "properties": { @@ -696,6 +1018,39 @@ ], "type": "object" }, + "DerivedTicketRelation": { + "properties": { + "at": { + "type": "string" + }, + "author": { + "type": "string" + }, + "forward_kind": { + "$ref": "#/components/schemas/TicketRelationKind" + }, + "inverse_kind": { + "type": "string" + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "source_ticket": { + "type": "string" + } + }, + "required": [ + "source_ticket", + "inverse_kind", + "forward_kind", + "author", + "at" + ], + "type": "object" + }, "DeviceAccessTokenType": { "enum": [ "Bearer" @@ -976,6 +1331,29 @@ ], "type": "string" }, + "ExtensibleTicketStatus": { + "oneOf": [ + { + "enum": [ + "Open", + "Closed" + ], + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "Other": { + "type": "string" + } + }, + "required": [ + "Other" + ], + "type": "object" + } + ] + }, "ExtractAudit": { "properties": { "entry_range": { @@ -1084,6 +1462,15 @@ }, "type": "object" }, + "FindingSeverity": { + "enum": [ + "blocker", + "major", + "minor", + "note" + ], + "type": "string" + }, "FlowSourceKind": { "enum": [ "builtin", @@ -1262,6 +1649,26 @@ ], "type": "object" }, + "InvalidProjectRecord": { + "additionalProperties": false, + "description": "One malformed project record reported by a bounded list projection.", + "properties": { + "label": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "required": [ + "label", + "reason" + ], + "type": "object" + }, + "MarkdownText": { + "type": "string" + }, "MemoryAppendAuditOperation": { "properties": { "event": { @@ -2205,6 +2612,671 @@ ], "type": "object" }, + "MergeEvent": { + "additionalProperties": false, + "properties": { + "approval_event_id": { + "type": "string" + }, + "approved_source_ref": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "event_id": { + "type": "string" + }, + "merged_by": { + "$ref": "#/components/schemas/MergeRequestWorkerIdentity" + }, + "operation_id": { + "type": "string" + }, + "resolution": { + "$ref": "#/components/schemas/ConflictResolution" + }, + "sequence": { + "format": "uint64", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "strategy": { + "$ref": "#/components/schemas/MergeStrategy" + }, + "target_ref_after": { + "type": "string" + }, + "target_ref_before": { + "type": "string" + } + }, + "required": [ + "event_id", + "sequence", + "operation_id", + "approval_event_id", + "approved_source_ref", + "target_ref_before", + "target_ref_after", + "strategy", + "resolution", + "merged_by", + "created_at" + ], + "type": "object" + }, + "MergeRequestDetailResponse": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "linked_tickets": { + "items": { + "$ref": "#/components/schemas/MergeRequestLinkedTicketResponse" + }, + "type": "array" + }, + "merge_request_id": { + "type": "string" + }, + "repository_key": { + "type": "string" + }, + "selector_from": { + "type": [ + "string", + "null" + ] + }, + "selector_to": { + "type": "string" + }, + "source": { + "$ref": "#/components/schemas/MergeRequestRefResponse" + }, + "state": { + "$ref": "#/components/schemas/MergeRequestState" + }, + "target": { + "$ref": "#/components/schemas/MergeRequestRefResponse" + }, + "thread": { + "items": { + "$ref": "#/components/schemas/MergeRequestThreadEvent" + }, + "type": "array" + }, + "ticket_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "updated_at": { + "type": "string" + }, + "workspace_id": { + "type": "string" + } + }, + "required": [ + "workspace_id", + "merge_request_id", + "repository_key", + "state", + "selector_to", + "ticket_ids", + "created_at", + "updated_at", + "thread", + "source", + "target", + "linked_tickets" + ], + "type": "object" + }, + "MergeRequestLinkedTicketResponse": { + "additionalProperties": false, + "properties": { + "key": { + "type": [ + "string", + "null" + ] + }, + "ticket_id": { + "type": "string" + } + }, + "required": [ + "ticket_id" + ], + "type": "object" + }, + "MergeRequestListItem": { + "additionalProperties": false, + "properties": { + "ref_diagnostics": { + "items": { + "$ref": "#/components/schemas/MergeRequestRefDiagnostic" + }, + "type": "array" + }, + "summary": { + "$ref": "#/components/schemas/TicketMergeRequestSummary" + }, + "thread_event_count": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "ticket_ids": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "summary", + "ticket_ids", + "thread_event_count" + ], + "type": "object" + }, + "MergeRequestListQuery": { + "additionalProperties": false, + "properties": { + "cursor": { + "type": [ + "string", + "null" + ] + }, + "limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "repository_key": { + "type": [ + "string", + "null" + ] + }, + "selector_from": { + "type": [ + "string", + "null" + ] + }, + "selector_to": { + "type": [ + "string", + "null" + ] + }, + "state": { + "type": [ + "string", + "null" + ] + }, + "ticket_ref": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "MergeRequestListResponse": { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/MergeRequestListItem" + }, + "type": "array" + }, + "next_cursor": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "items" + ], + "type": "object" + }, + "MergeRequestReadinessResponse": { + "additionalProperties": false, + "properties": { + "blockers": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ready": { + "type": "boolean" + }, + "review": { + "anyOf": [ + { + "$ref": "#/components/schemas/ReviewEvent" + }, + { + "type": "null" + } + ] + }, + "subject_ref": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "ready", + "blockers" + ], + "type": "object" + }, + "MergeRequestRefDiagnostic": { + "additionalProperties": false, + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" + }, + "MergeRequestRefResponse": { + "additionalProperties": false, + "properties": { + "diagnostic": { + "anyOf": [ + { + "$ref": "#/components/schemas/MergeRequestRefDiagnostic" + }, + { + "type": "null" + } + ] + }, + "observed_at": { + "type": "string" + }, + "ref": { + "type": [ + "string", + "null" + ] + }, + "status": { + "type": "string" + } + }, + "required": [ + "status", + "observed_at" + ], + "type": "object" + }, + "MergeRequestState": { + "enum": [ + "open", + "merged", + "closed" + ], + "type": "string" + }, + "MergeRequestThreadEvent": { + "oneOf": [ + { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "event_id": { + "type": "string" + }, + "kind": { + "const": "review_requested", + "type": "string" + }, + "requested_by": { + "$ref": "#/components/schemas/MergeRequestWorkerIdentity" + }, + "reviewer": { + "$ref": "#/components/schemas/MergeRequestWorkerIdentity" + }, + "sequence": { + "format": "uint64", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "subject_ref": { + "type": "string" + } + }, + "required": [ + "kind", + "event_id", + "sequence", + "subject_ref", + "requested_by", + "reviewer", + "created_at" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "body": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "decision": { + "$ref": "#/components/schemas/ReviewDecision" + }, + "event_id": { + "type": "string" + }, + "findings": { + "items": { + "$ref": "#/components/schemas/ReviewFinding" + }, + "type": "array" + }, + "kind": { + "const": "review", + "type": "string" + }, + "request_event_id": { + "type": "string" + }, + "reviewer": { + "$ref": "#/components/schemas/MergeRequestWorkerIdentity" + }, + "sequence": { + "format": "uint64", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "subject_ref": { + "type": "string" + } + }, + "required": [ + "kind", + "event_id", + "sequence", + "request_event_id", + "subject_ref", + "decision", + "body", + "findings", + "reviewer", + "created_at" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "event_id": { + "type": "string" + }, + "kind": { + "const": "review_revoked", + "type": "string" + }, + "reason": { + "type": "string" + }, + "review_event_id": { + "type": "string" + }, + "revoked_by": { + "$ref": "#/components/schemas/MergeRequestWorkerIdentity" + }, + "sequence": { + "format": "uint64", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "subject_ref": { + "type": "string" + } + }, + "required": [ + "kind", + "event_id", + "sequence", + "review_event_id", + "subject_ref", + "reason", + "revoked_by", + "created_at" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "event_id": { + "type": "string" + }, + "kind": { + "const": "review_cancelled", + "type": "string" + }, + "reason": { + "type": "string" + }, + "request_event_id": { + "type": "string" + }, + "sequence": { + "format": "uint64", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "subject_ref": { + "type": "string" + } + }, + "required": [ + "kind", + "event_id", + "sequence", + "request_event_id", + "subject_ref", + "reason", + "created_at" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "author": { + "$ref": "#/components/schemas/MergeRequestWorkerIdentity" + }, + "body": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "event_id": { + "type": "string" + }, + "kind": { + "const": "comment", + "type": "string" + }, + "sequence": { + "format": "uint64", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "kind", + "event_id", + "sequence", + "body", + "author", + "created_at" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "approval_event_id": { + "type": "string" + }, + "approved_source_ref": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "event_id": { + "type": "string" + }, + "kind": { + "const": "merge", + "type": "string" + }, + "merged_by": { + "$ref": "#/components/schemas/MergeRequestWorkerIdentity" + }, + "operation_id": { + "type": "string" + }, + "resolution": { + "$ref": "#/components/schemas/ConflictResolution" + }, + "sequence": { + "format": "uint64", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "strategy": { + "$ref": "#/components/schemas/MergeStrategy" + }, + "target_ref_after": { + "type": "string" + }, + "target_ref_before": { + "type": "string" + } + }, + "required": [ + "kind", + "event_id", + "sequence", + "operation_id", + "approval_event_id", + "approved_source_ref", + "target_ref_before", + "target_ref_after", + "strategy", + "resolution", + "merged_by", + "created_at" + ], + "type": "object" + } + ] + }, + "MergeRequestThreadQuery": { + "additionalProperties": false, + "properties": { + "after": { + "format": "uint64", + "maximum": 9007199254740991, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "MergeRequestWorkerIdentity": { + "additionalProperties": false, + "properties": { + "runtime_id": { + "type": "string" + }, + "worker_id": { + "type": "string" + } + }, + "required": [ + "runtime_id", + "worker_id" + ], + "type": "object" + }, + "MergeStrategy": { + "enum": [ + "fast_forward", + "merge" + ], + "type": "string" + }, "ModelAudit": { "properties": { "model_id": { @@ -2228,6 +3300,760 @@ }, "type": "object" }, + "NewOrchestrationPlanRecord": { + "properties": { + "accepted_plan": { + "anyOf": [ + { + "$ref": "#/components/schemas/AcceptedOrchestrationPlan" + }, + { + "type": "null" + } + ] + }, + "author": { + "type": [ + "string", + "null" + ] + }, + "kind": { + "$ref": "#/components/schemas/OrchestrationPlanKind" + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "related_ticket": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "NewTicket": { + "properties": { + "assignee": { + "type": [ + "string", + "null" + ] + }, + "author": { + "type": [ + "string", + "null" + ] + }, + "body": { + "$ref": "#/components/schemas/MarkdownText" + }, + "kind": { + "type": "string" + }, + "labels": { + "items": { + "type": "string" + }, + "type": "array" + }, + "priority": { + "type": "string" + }, + "queued_at": { + "type": [ + "string", + "null" + ] + }, + "queued_by": { + "type": [ + "string", + "null" + ] + }, + "readiness": { + "type": [ + "string", + "null" + ] + }, + "ref_selector": { + "type": [ + "string", + "null" + ] + }, + "repository_key": { + "type": [ + "string", + "null" + ] + }, + "risk_flags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "slug": { + "type": [ + "string", + "null" + ] + }, + "title": { + "type": "string" + }, + "workflow_state": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketWorkflowState" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "title", + "kind", + "priority", + "labels", + "body", + "risk_flags" + ], + "type": "object" + }, + "NewTicketEvent": { + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "body": { + "$ref": "#/components/schemas/MarkdownText" + }, + "kind": { + "$ref": "#/components/schemas/TicketEventKind" + }, + "references": { + "items": { + "$ref": "#/components/schemas/TicketReference" + }, + "type": "array" + } + }, + "required": [ + "kind", + "body", + "references" + ], + "type": "object" + }, + "NewTicketRelation": { + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "kind": { + "$ref": "#/components/schemas/TicketRelationKind" + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "target": { + "type": "string" + } + }, + "required": [ + "kind", + "target" + ], + "type": "object" + }, + "ObjectiveCreateRequest": { + "additionalProperties": false, + "properties": { + "body_md": { + "default": "", + "type": "string" + }, + "linked_tickets": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "default": "active", + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": [ + "title" + ], + "type": "object" + }, + "ObjectiveDetail": { + "additionalProperties": false, + "properties": { + "body": { + "type": "string" + }, + "body_truncated": { + "type": "boolean" + }, + "created_at": { + "type": [ + "string", + "null" + ] + }, + "event_page": { + "$ref": "#/components/schemas/QueryPage" + }, + "events": { + "items": { + "$ref": "#/components/schemas/ObjectiveEventDetail" + }, + "type": "array" + }, + "id": { + "type": "string" + }, + "linked_ticket_summaries": { + "items": { + "$ref": "#/components/schemas/ObjectiveLinkedTicketSummary" + }, + "type": "array" + }, + "linked_tickets": { + "items": { + "type": "string" + }, + "type": "array" + }, + "record_source": { + "type": "string" + }, + "resource_key": { + "type": "string" + }, + "resources": { + "items": { + "$ref": "#/components/schemas/ObjectiveResourceSummary" + }, + "type": "array" + }, + "revision": { + "type": "string" + }, + "state": { + "type": "string" + }, + "title": { + "type": "string" + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "resource_key", + "title", + "state", + "revision", + "linked_tickets", + "linked_ticket_summaries", + "resources", + "body", + "body_truncated", + "events", + "event_page", + "record_source" + ], + "type": "object" + }, + "ObjectiveEditRequest": { + "additionalProperties": false, + "properties": { + "new_string": { + "type": [ + "string", + "null" + ] + }, + "old_string": { + "type": [ + "string", + "null" + ] + }, + "replace_all": { + "default": false, + "type": "boolean" + }, + "title": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "ObjectiveEventDetail": { + "additionalProperties": false, + "properties": { + "body": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": "string" + }, + "event_ref": { + "type": "string" + }, + "kind": { + "type": "string" + } + }, + "required": [ + "event_ref", + "kind", + "created_at" + ], + "type": "object" + }, + "ObjectiveLinkSummary": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "resource_key": { + "type": "string" + }, + "state": { + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": [ + "id", + "resource_key", + "title", + "state" + ], + "type": "object" + }, + "ObjectiveLinkTicketRequest": { + "additionalProperties": false, + "properties": { + "ticket_id": { + "type": "string" + } + }, + "required": [ + "ticket_id" + ], + "type": "object" + }, + "ObjectiveLinkedTicketSummary": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "resource_key": { + "type": "string" + }, + "state": { + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": [ + "id", + "resource_key", + "title", + "state" + ], + "type": "object" + }, + "ObjectiveListQuery": { + "additionalProperties": false, + "properties": { + "limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "ObjectiveListResponse": { + "additionalProperties": false, + "properties": { + "invalid_records": { + "items": { + "$ref": "#/components/schemas/InvalidProjectRecord" + }, + "type": "array" + }, + "items": { + "items": { + "$ref": "#/components/schemas/ObjectiveSummary" + }, + "type": "array" + }, + "limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": "integer" + }, + "record_authority": { + "type": "string" + }, + "workspace_id": { + "type": "string" + } + }, + "required": [ + "workspace_id", + "limit", + "items", + "invalid_records", + "record_authority" + ], + "type": "object" + }, + "ObjectiveQueryItem": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "string" + }, + "linked_ticket_count": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "linked_ticket_keys": { + "items": { + "type": "string" + }, + "type": "array" + }, + "linked_tickets": { + "items": { + "type": "string" + }, + "type": "array" + }, + "matched_fields": { + "items": { + "type": "string" + }, + "type": "array" + }, + "resource_key": { + "type": "string" + }, + "snippet": { + "type": [ + "string", + "null" + ] + }, + "state": { + "type": "string" + }, + "title": { + "type": "string" + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "resource_key", + "title", + "state", + "matched_fields", + "linked_ticket_count", + "linked_tickets", + "linked_ticket_keys" + ], + "type": "object" + }, + "ObjectiveQueryRequest": { + "additionalProperties": false, + "properties": { + "cursor": { + "type": [ + "string", + "null" + ] + }, + "limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "linked_ticket_id": { + "type": [ + "string", + "null" + ] + }, + "query": { + "type": [ + "string", + "null" + ] + }, + "sort": { + "type": [ + "string", + "null" + ] + }, + "states": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + }, + "updated_after": { + "type": [ + "string", + "null" + ] + }, + "updated_before": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "ObjectiveQueryResponse": { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/ObjectiveQueryItem" + }, + "type": "array" + }, + "page": { + "$ref": "#/components/schemas/QueryPage" + }, + "record_authority": { + "type": "string" + } + }, + "required": [ + "items", + "page", + "record_authority" + ], + "type": "object" + }, + "ObjectiveResourceSummary": { + "additionalProperties": false, + "properties": { + "bytes": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "media_type": { + "type": [ + "string", + "null" + ] + }, + "path": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "path", + "bytes", + "updated_at" + ], + "type": "object" + }, + "ObjectiveShowRequest": { + "additionalProperties": false, + "properties": { + "event_cursor": { + "type": [ + "string", + "null" + ] + }, + "event_limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "ObjectiveStateRequest": { + "additionalProperties": false, + "properties": { + "state": { + "type": "string" + } + }, + "required": [ + "state" + ], + "type": "object" + }, + "ObjectiveSummary": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "string" + }, + "linked_tickets": { + "items": { + "type": "string" + }, + "type": "array" + }, + "record_source": { + "type": "string" + }, + "resource_key": { + "type": "string" + }, + "state": { + "type": "string" + }, + "summary": { + "type": "string" + }, + "title": { + "type": "string" + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "resource_key", + "title", + "state", + "summary", + "linked_tickets", + "record_source" + ], + "type": "object" + }, + "OpenMergeRequestRequest": { + "additionalProperties": false, + "properties": { + "repository_key": { + "type": "string" + }, + "selector_from": { + "type": "string" + }, + "selector_to": { + "type": "string" + }, + "summary": { + "default": "", + "type": "string" + } + }, + "required": [ + "repository_key", + "selector_from", + "selector_to" + ], + "type": "object" + }, "OperationCounts": { "properties": { "delete": { @@ -2275,6 +4101,69 @@ }, "type": "object" }, + "OrchestrationPlanKind": { + "enum": [ + "before", + "after", + "blocked_by", + "blocks", + "conflicts_with", + "do_not_parallelize", + "waiting_capacity_note", + "accepted_plan" + ], + "type": "string" + }, + "OrchestrationPlanRecord": { + "additionalProperties": false, + "properties": { + "accepted_plan": { + "anyOf": [ + { + "$ref": "#/components/schemas/AcceptedOrchestrationPlan" + }, + { + "type": "null" + } + ] + }, + "at": { + "type": "string" + }, + "author": { + "type": "string" + }, + "id": { + "type": "string" + }, + "kind": { + "$ref": "#/components/schemas/OrchestrationPlanKind" + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "related_ticket": { + "type": [ + "string", + "null" + ] + }, + "ticket_id": { + "type": "string" + } + }, + "required": [ + "id", + "ticket_id", + "kind", + "author", + "at" + ], + "type": "object" + }, "PasskeyLoginOptionsRequest": { "additionalProperties": false, "properties": { @@ -2410,6 +4299,62 @@ ], "type": "object" }, + "PublicMergeRequest": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "merge_request_id": { + "type": "string" + }, + "repository_key": { + "type": "string" + }, + "selector_from": { + "type": [ + "string", + "null" + ] + }, + "selector_to": { + "type": "string" + }, + "state": { + "$ref": "#/components/schemas/MergeRequestState" + }, + "thread": { + "items": { + "$ref": "#/components/schemas/MergeRequestThreadEvent" + }, + "type": "array" + }, + "ticket_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "updated_at": { + "type": "string" + }, + "workspace_id": { + "type": "string" + } + }, + "required": [ + "workspace_id", + "merge_request_id", + "repository_key", + "state", + "selector_to", + "ticket_ids", + "created_at", + "updated_at", + "thread" + ], + "type": "object" + }, "PutFlowRequest": { "additionalProperties": false, "properties": { @@ -2467,6 +4412,55 @@ ], "type": "object" }, + "QueryPage": { + "additionalProperties": false, + "properties": { + "has_more": { + "type": "boolean" + }, + "limit": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "next_cursor": { + "type": [ + "string", + "null" + ] + }, + "returned": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "sort": { + "type": "string" + }, + "source_limit": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "source_truncated": { + "type": "boolean" + } + }, + "required": [ + "limit", + "returned", + "has_more", + "sort", + "source_truncated" + ], + "type": "object" + }, "RecordOperationAudit": { "properties": { "after_hash": { @@ -2564,6 +4558,54 @@ ], "type": "object" }, + "RegisterMergeRequestReviewCapabilityRequest": { + "additionalProperties": false, + "properties": { + "capability_token": { + "type": "string" + }, + "child_session_id": { + "type": "string" + } + }, + "required": [ + "child_session_id", + "capability_token" + ], + "type": "object" + }, + "RegisterReviewerChildSessionRequest": { + "additionalProperties": false, + "properties": { + "child_session_id": { + "type": "string" + } + }, + "required": [ + "child_session_id" + ], + "type": "object" + }, + "RepairMergeRequestSelectorRequest": { + "additionalProperties": false, + "properties": { + "explicit_confirmation": { + "type": "boolean" + }, + "reason": { + "type": "string" + }, + "selector_from": { + "type": "string" + } + }, + "required": [ + "selector_from", + "reason", + "explicit_confirmation" + ], + "type": "object" + }, "RepositoryAccessMode": { "enum": [ "read_only", @@ -3114,6 +5156,158 @@ ], "type": "object" }, + "ReviewDecision": { + "enum": [ + "approve", + "request_changes" + ], + "type": "string" + }, + "ReviewEvent": { + "additionalProperties": false, + "properties": { + "body": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "decision": { + "$ref": "#/components/schemas/ReviewDecision" + }, + "event_id": { + "type": "string" + }, + "findings": { + "items": { + "$ref": "#/components/schemas/ReviewFinding" + }, + "type": "array" + }, + "request_event_id": { + "type": "string" + }, + "reviewer": { + "$ref": "#/components/schemas/MergeRequestWorkerIdentity" + }, + "sequence": { + "format": "uint64", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "subject_ref": { + "type": "string" + } + }, + "required": [ + "event_id", + "sequence", + "request_event_id", + "subject_ref", + "decision", + "body", + "findings", + "reviewer", + "created_at" + ], + "type": "object" + }, + "ReviewFinding": { + "additionalProperties": false, + "properties": { + "body": { + "type": "string" + }, + "code": { + "type": [ + "string", + "null" + ] + }, + "line": { + "format": "uint32", + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "path": { + "type": [ + "string", + "null" + ] + }, + "severity": { + "$ref": "#/components/schemas/FindingSeverity" + } + }, + "required": [ + "severity", + "body" + ], + "type": "object" + }, + "ReviewRevokedEvent": { + "additionalProperties": false, + "properties": { + "created_at": { + "type": "string" + }, + "event_id": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "review_event_id": { + "type": "string" + }, + "revoked_by": { + "$ref": "#/components/schemas/MergeRequestWorkerIdentity" + }, + "sequence": { + "format": "uint64", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "subject_ref": { + "type": "string" + } + }, + "required": [ + "event_id", + "sequence", + "review_event_id", + "subject_ref", + "reason", + "revoked_by", + "created_at" + ], + "type": "object" + }, + "RevokeMergeRequestReviewRequest": { + "additionalProperties": false, + "properties": { + "explicit_confirmation": { + "type": "boolean" + }, + "reason": { + "type": "string" + }, + "review_event_id": { + "type": "string" + } + }, + "required": [ + "review_event_id", + "reason", + "explicit_confirmation" + ], + "type": "object" + }, "RotateRepositorySshCredentialRequest": { "additionalProperties": false, "properties": { @@ -3150,6 +5344,28 @@ "minimum": 0, "type": "integer" }, + "SetTicketRoleAssignmentRequest": { + "additionalProperties": false, + "properties": { + "expected_assignment_id": { + "type": [ + "string", + "null" + ] + }, + "operation_id": { + "type": "string" + }, + "principal": { + "$ref": "#/components/schemas/TicketAssignmentPrincipal" + } + }, + "required": [ + "operation_id", + "principal" + ], + "type": "object" + }, "SkillActivationResponse": { "additionalProperties": false, "properties": { @@ -3610,6 +5826,2303 @@ ], "type": "object" }, + "SubmitMergeRequestReviewRequest": { + "additionalProperties": false, + "properties": { + "body": { + "default": "", + "type": "string" + }, + "capability_token": { + "type": "string" + }, + "decision": { + "$ref": "#/components/schemas/ReviewDecision" + }, + "findings": { + "default": [], + "items": { + "$ref": "#/components/schemas/ReviewFinding" + }, + "type": "array" + } + }, + "required": [ + "capability_token", + "decision" + ], + "type": "object" + }, + "Ticket": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/components/schemas/TicketArtifactRef" + }, + "type": "array" + }, + "document": { + "$ref": "#/components/schemas/TicketDocument" + }, + "events": { + "items": { + "$ref": "#/components/schemas/TicketEvent" + }, + "type": "array" + }, + "meta": { + "$ref": "#/components/schemas/TicketMeta" + }, + "relations": { + "$ref": "#/components/schemas/TicketRelationView" + }, + "resolution": { + "anyOf": [ + { + "$ref": "#/components/schemas/MarkdownText" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "meta", + "document", + "events", + "artifacts", + "relations" + ], + "type": "object" + }, + "TicketActionEligibility": { + "additionalProperties": false, + "properties": { + "blockers": { + "items": { + "type": "string" + }, + "type": "array" + }, + "can_assign_orchestrator": { + "type": "boolean" + }, + "can_queue": { + "type": "boolean" + }, + "can_start_manual_coder": { + "type": "boolean" + }, + "can_unassign_orchestrator": { + "type": "boolean" + }, + "queue_tickets": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "can_assign_orchestrator", + "can_unassign_orchestrator", + "can_queue", + "can_start_manual_coder", + "queue_tickets", + "blockers" + ], + "type": "object" + }, + "TicketArtifactRef": { + "properties": { + "relative_path": { + "description": "Path relative to the ticket's `artifacts/` directory.", + "type": "string" + } + }, + "required": [ + "relative_path" + ], + "type": "object" + }, + "TicketAssignmentPrincipal": { + "oneOf": [ + { + "additionalProperties": false, + "properties": { + "account_id": { + "type": "string" + }, + "kind": { + "const": "user", + "type": "string" + } + }, + "required": [ + "kind", + "account_id" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "kind": { + "const": "worker", + "type": "string" + }, + "runtime_id": { + "type": "string" + }, + "worker_id": { + "type": "string" + } + }, + "required": [ + "kind", + "runtime_id", + "worker_id" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "agent_key": { + "type": "string" + }, + "kind": { + "const": "workspace_agent", + "type": "string" + } + }, + "required": [ + "kind", + "agent_key" + ], + "type": "object" + } + ] + }, + "TicketAssignmentRole": { + "enum": [ + "orchestrator", + "coder", + "owner", + "contributor" + ], + "type": "string" + }, + "TicketAssignmentSummary": { + "additionalProperties": false, + "properties": { + "assignment_id": { + "type": "string" + }, + "runtime_id": { + "type": "string" + }, + "worker_id": { + "type": "string" + }, + "worker_resource_key": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "assignment_id", + "runtime_id", + "worker_id" + ], + "type": "object" + }, + "TicketBodyReplacement": { + "properties": { + "new_string": { + "type": "string" + }, + "old_string": { + "type": "string" + }, + "replace_all": { + "default": false, + "type": "boolean" + } + }, + "required": [ + "old_string", + "new_string" + ], + "type": "object" + }, + "TicketDependencyCheck": { + "properties": { + "blockers": { + "items": { + "$ref": "#/components/schemas/TicketRelationBlocker" + }, + "type": "array" + }, + "queue_guard": { + "$ref": "#/components/schemas/TicketQueueGuard" + }, + "queue_tickets": { + "items": { + "type": "string" + }, + "type": "array" + }, + "recommended_action": { + "$ref": "#/components/schemas/TicketWorkspaceNextAction" + }, + "ticket": { + "$ref": "#/components/schemas/TicketSummary" + } + }, + "required": [ + "ticket", + "blockers", + "queue_guard", + "queue_tickets", + "recommended_action" + ], + "type": "object" + }, + "TicketDetail": { + "additionalProperties": false, + "properties": { + "action_eligibility": { + "$ref": "#/components/schemas/TicketActionEligibility" + }, + "artifact_count": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "artifacts": { + "items": { + "type": "string" + }, + "type": "array" + }, + "assignment_diagnostics": { + "items": { + "type": "string" + }, + "type": "array" + }, + "assignments": { + "items": { + "$ref": "#/components/schemas/TicketRoleAssignmentSummary" + }, + "type": "array" + }, + "body": { + "type": "string" + }, + "body_truncated": { + "type": "boolean" + }, + "created_at": { + "type": [ + "string", + "null" + ] + }, + "current_coder": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketAssignmentSummary" + }, + { + "type": "null" + } + ] + }, + "event_count": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "event_page": { + "$ref": "#/components/schemas/QueryPage" + }, + "events": { + "items": { + "$ref": "#/components/schemas/TicketEventDetail" + }, + "type": "array" + }, + "evidence": { + "$ref": "#/components/schemas/TicketEvidenceSummary" + }, + "id": { + "type": "string" + }, + "implementation_reports": { + "items": { + "$ref": "#/components/schemas/TicketEvidenceEvent" + }, + "type": "array" + }, + "item_revision": { + "type": "string" + }, + "linked_objectives": { + "items": { + "$ref": "#/components/schemas/ObjectiveLinkSummary" + }, + "type": "array" + }, + "merge_request": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketMergeRequestSummary" + }, + { + "type": "null" + } + ] + }, + "priority": { + "type": "string" + }, + "queued_at": { + "type": [ + "string", + "null" + ] + }, + "queued_by": { + "type": [ + "string", + "null" + ] + }, + "readiness": { + "type": [ + "string", + "null" + ] + }, + "record_source": { + "type": "string" + }, + "ref_selector": { + "type": [ + "string", + "null" + ] + }, + "relations": { + "$ref": "#/components/schemas/TicketDetailRelationView" + }, + "repository_key": { + "type": [ + "string", + "null" + ] + }, + "resolution": { + "type": [ + "string", + "null" + ] + }, + "resource_key": { + "type": "string" + }, + "risk_flags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "type": "string" + }, + "title": { + "type": "string" + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "resource_key", + "title", + "state", + "priority", + "item_revision", + "risk_flags", + "body", + "body_truncated", + "event_count", + "events", + "event_page", + "artifact_count", + "artifacts", + "relations", + "linked_objectives", + "implementation_reports", + "assignments", + "assignment_diagnostics", + "action_eligibility", + "evidence", + "record_source" + ], + "type": "object" + }, + "TicketDetailDerivedRelation": { + "additionalProperties": false, + "properties": { + "at": { + "type": "string" + }, + "author": { + "type": "string" + }, + "forward_kind": { + "type": "string" + }, + "inverse_kind": { + "type": "string" + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "source_resource_key": { + "type": [ + "string", + "null" + ] + }, + "source_ticket": { + "type": "string" + } + }, + "required": [ + "source_ticket", + "inverse_kind", + "forward_kind", + "author", + "at" + ], + "type": "object" + }, + "TicketDetailRelation": { + "additionalProperties": false, + "properties": { + "at": { + "type": "string" + }, + "author": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "target": { + "type": "string" + }, + "target_resource_key": { + "type": [ + "string", + "null" + ] + }, + "ticket_id": { + "type": "string" + } + }, + "required": [ + "ticket_id", + "kind", + "target", + "author", + "at" + ], + "type": "object" + }, + "TicketDetailRelationBlocker": { + "additionalProperties": false, + "properties": { + "blocking_resource_key": { + "type": [ + "string", + "null" + ] + }, + "blocking_state": { + "type": "string" + }, + "blocking_ticket": { + "type": "string" + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "reason_kind": { + "type": "string" + }, + "relation_kind": { + "type": "string" + } + }, + "required": [ + "blocking_ticket", + "reason_kind", + "relation_kind", + "blocking_state" + ], + "type": "object" + }, + "TicketDetailRelationNotice": { + "additionalProperties": false, + "properties": { + "kind": { + "type": "string" + }, + "message": { + "type": "string" + }, + "related_ticket": { + "type": "string" + } + }, + "required": [ + "related_ticket", + "kind", + "message" + ], + "type": "object" + }, + "TicketDetailRelationView": { + "additionalProperties": false, + "properties": { + "blockers": { + "items": { + "$ref": "#/components/schemas/TicketDetailRelationBlocker" + }, + "type": "array" + }, + "incoming": { + "items": { + "$ref": "#/components/schemas/TicketDetailDerivedRelation" + }, + "type": "array" + }, + "notices": { + "items": { + "$ref": "#/components/schemas/TicketDetailRelationNotice" + }, + "type": "array" + }, + "outgoing": { + "items": { + "$ref": "#/components/schemas/TicketDetailRelation" + }, + "type": "array" + } + }, + "required": [ + "outgoing", + "incoming", + "blockers", + "notices" + ], + "type": "object" + }, + "TicketDoctorDiagnostic": { + "properties": { + "message": { + "type": "string" + }, + "path": { + "type": [ + "string", + "null" + ] + }, + "severity": { + "$ref": "#/components/schemas/TicketDoctorSeverity" + } + }, + "required": [ + "severity", + "message" + ], + "type": "object" + }, + "TicketDoctorReport": { + "properties": { + "diagnostics": { + "items": { + "$ref": "#/components/schemas/TicketDoctorDiagnostic" + }, + "type": "array" + } + }, + "required": [ + "diagnostics" + ], + "type": "object" + }, + "TicketDoctorSeverity": { + "enum": [ + "Error", + "Warning" + ], + "type": "string" + }, + "TicketDocument": { + "properties": { + "body": { + "$ref": "#/components/schemas/MarkdownText" + }, + "raw_frontmatter": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "body", + "raw_frontmatter" + ], + "type": "object" + }, + "TicketEvent": { + "properties": { + "at": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "author": { + "type": [ + "string", + "null" + ] + }, + "body": { + "$ref": "#/components/schemas/MarkdownText" + }, + "from": { + "type": [ + "string", + "null" + ] + }, + "heading": { + "type": [ + "string", + "null" + ] + }, + "kind": { + "$ref": "#/components/schemas/TicketEventKind" + }, + "reason": { + "type": [ + "string", + "null" + ] + }, + "references": { + "items": { + "$ref": "#/components/schemas/TicketReference" + }, + "type": "array" + }, + "state_field": { + "type": [ + "string", + "null" + ] + }, + "status": { + "type": [ + "string", + "null" + ] + }, + "to": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "kind", + "body", + "references", + "attributes" + ], + "type": "object" + }, + "TicketEventDetail": { + "additionalProperties": false, + "properties": { + "at": { + "type": [ + "string", + "null" + ] + }, + "attributes": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "author": { + "type": [ + "string", + "null" + ] + }, + "body": { + "type": [ + "string", + "null" + ] + }, + "event_ref": { + "type": "string" + }, + "from": { + "type": [ + "string", + "null" + ] + }, + "heading": { + "type": [ + "string", + "null" + ] + }, + "kind": { + "type": "string" + }, + "reason": { + "type": [ + "string", + "null" + ] + }, + "references": { + "items": { + "type": "string" + }, + "type": "array" + }, + "sequence": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "state_field": { + "type": [ + "string", + "null" + ] + }, + "status": { + "type": [ + "string", + "null" + ] + }, + "to": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "sequence", + "event_ref", + "kind", + "attributes", + "references" + ], + "type": "object" + }, + "TicketEventKind": { + "oneOf": [ + { + "enum": [ + "create", + "comment", + "plan", + "decision", + "implementation_report", + "state_changed", + "intake_summary", + "status_changed", + "close" + ], + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "other": { + "type": "string" + } + }, + "required": [ + "other" + ], + "type": "object" + } + ] + }, + "TicketEvidenceEvent": { + "additionalProperties": false, + "properties": { + "at": { + "type": [ + "string", + "null" + ] + }, + "author": { + "type": [ + "string", + "null" + ] + }, + "event_ref": { + "type": "string" + }, + "excerpt": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "sequence": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "event_ref", + "sequence", + "kind", + "excerpt" + ], + "type": "object" + }, + "TicketEvidenceSummary": { + "additionalProperties": false, + "properties": { + "approved_current_subject": { + "type": "boolean" + }, + "complete_for_integration": { + "type": "boolean" + }, + "has_commit": { + "type": "boolean" + }, + "has_current_subject_ref": { + "type": "boolean" + }, + "has_merge_request": { + "type": "boolean" + }, + "has_review_request": { + "type": "boolean" + }, + "missing": { + "items": { + "type": "string" + }, + "type": "array" + }, + "review_after_rescope": { + "type": "boolean" + }, + "review_status": { + "type": [ + "string", + "null" + ] + }, + "unresolved_request_changes": { + "type": "boolean" + } + }, + "required": [ + "has_merge_request", + "has_current_subject_ref", + "has_review_request", + "has_commit", + "approved_current_subject", + "review_after_rescope", + "unresolved_request_changes", + "complete_for_integration", + "missing" + ], + "type": "object" + }, + "TicketIdOrSlug": { + "oneOf": [ + { + "additionalProperties": false, + "properties": { + "Id": { + "type": "string" + } + }, + "required": [ + "Id" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "Slug": { + "type": "string" + } + }, + "required": [ + "Slug" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "Query": { + "type": "string" + } + }, + "required": [ + "Query" + ], + "type": "object" + } + ] + }, + "TicketIntakeSummary": { + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "body": { + "$ref": "#/components/schemas/MarkdownText" + }, + "references": { + "items": { + "$ref": "#/components/schemas/TicketReference" + }, + "type": "array" + } + }, + "required": [ + "body", + "references" + ], + "type": "object" + }, + "TicketItemEdit": { + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "body": { + "anyOf": [ + { + "$ref": "#/components/schemas/MarkdownText" + }, + { + "type": "null" + } + ], + "description": "Whole-body replacement for legacy authoring surfaces. Prefer `body_replacement`\nfor small edits that should be validated against the current body." + }, + "body_replacement": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketBodyReplacement" + }, + { + "type": "null" + } + ], + "default": null + }, + "target": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketTargetEdit" + }, + { + "type": "null" + } + ] + }, + "title": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "TicketListHttpQuery": { + "additionalProperties": false, + "properties": { + "cursor": { + "type": [ + "string", + "null" + ] + }, + "limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "states": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "TicketListItemSummary": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string" + }, + "priority": { + "type": "string" + }, + "queued_at": { + "type": [ + "string", + "null" + ] + }, + "queued_by": { + "type": [ + "string", + "null" + ] + }, + "record_source": { + "type": "string" + }, + "resource_key": { + "type": "string" + }, + "state": { + "type": "string" + }, + "title": { + "type": "string" + }, + "updated_at": { + "type": [ + "string", + "null" + ] + }, + "workspace_action_priority": { + "type": "string" + } + }, + "required": [ + "id", + "resource_key", + "title", + "state", + "priority", + "workspace_action_priority", + "record_source" + ], + "type": "object" + }, + "TicketListResponse": { + "additionalProperties": false, + "properties": { + "invalid_records": { + "items": { + "$ref": "#/components/schemas/InvalidProjectRecord" + }, + "type": "array" + }, + "items": { + "items": { + "$ref": "#/components/schemas/TicketListItemSummary" + }, + "type": "array" + }, + "limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": "integer" + }, + "page": { + "$ref": "#/components/schemas/QueryPage" + }, + "record_authority": { + "type": "string" + }, + "workspace_id": { + "type": "string" + } + }, + "required": [ + "workspace_id", + "limit", + "items", + "page", + "invalid_records", + "record_authority" + ], + "type": "object" + }, + "TicketMarkReadyRequest": { + "additionalProperties": false, + "properties": { + "intake_summary": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketIntakeSummary" + }, + { + "type": "null" + } + ], + "default": null + }, + "operation_key": { + "type": "string" + }, + "reason": { + "default": null, + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "operation_key" + ], + "type": "object" + }, + "TicketMergeRequestSummary": { + "additionalProperties": false, + "properties": { + "current_subject_ref": { + "type": [ + "string", + "null" + ] + }, + "merge_request_id": { + "type": "string" + }, + "repository_key": { + "type": "string" + }, + "review_excerpt": { + "type": [ + "string", + "null" + ] + }, + "review_requested_at": { + "type": [ + "string", + "null" + ] + }, + "review_status": { + "type": "string" + }, + "review_subject_ref": { + "type": [ + "string", + "null" + ] + }, + "review_submitted_at": { + "type": [ + "string", + "null" + ] + }, + "selector_from": { + "type": [ + "string", + "null" + ] + }, + "selector_to": { + "type": "string" + }, + "state": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "merge_request_id", + "repository_key", + "state", + "review_status", + "selector_to", + "updated_at" + ], + "type": "object" + }, + "TicketMeta": { + "properties": { + "assignee": { + "type": [ + "string", + "null" + ] + }, + "created_at": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "labels": { + "items": { + "type": "string" + }, + "type": "array" + }, + "priority": { + "type": "string" + }, + "queued_at": { + "type": [ + "string", + "null" + ] + }, + "queued_by": { + "type": [ + "string", + "null" + ] + }, + "raw": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "readiness": { + "type": [ + "string", + "null" + ] + }, + "ref_selector": { + "type": [ + "string", + "null" + ] + }, + "repository_key": { + "type": [ + "string", + "null" + ] + }, + "resource_key": { + "type": [ + "string", + "null" + ] + }, + "risk_flags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "slug": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/ExtensibleTicketStatus" + }, + "title": { + "type": "string" + }, + "updated_at": { + "type": [ + "string", + "null" + ] + }, + "workflow_state": { + "$ref": "#/components/schemas/TicketWorkflowState" + }, + "workflow_state_explicit": { + "type": "boolean" + } + }, + "required": [ + "id", + "slug", + "title", + "status", + "kind", + "priority", + "labels", + "risk_flags", + "workflow_state", + "workflow_state_explicit", + "raw" + ], + "type": "object" + }, + "TicketOrchestrationPlanSearchRequest": { + "additionalProperties": false, + "properties": { + "kind": { + "anyOf": [ + { + "$ref": "#/components/schemas/OrchestrationPlanKind" + }, + { + "type": "null" + } + ] + }, + "ticket": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketIdOrSlug" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + "TicketQueryItem": { + "additionalProperties": false, + "properties": { + "blocker_count": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "created_at": { + "type": [ + "string", + "null" + ] + }, + "current_coder": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketAssignmentSummary" + }, + { + "type": "null" + } + ] + }, + "evidence": { + "$ref": "#/components/schemas/TicketEvidenceSummary" + }, + "id": { + "type": "string" + }, + "item_revision": { + "type": "string" + }, + "linked_objective_ids": { + "items": { + "type": "string" + }, + "type": "array" + }, + "linked_objective_keys": { + "items": { + "type": "string" + }, + "type": "array" + }, + "matched_fields": { + "items": { + "type": "string" + }, + "type": "array" + }, + "matching_event": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketEvidenceEvent" + }, + { + "type": "null" + } + ] + }, + "merge_request": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketMergeRequestSummary" + }, + { + "type": "null" + } + ] + }, + "priority": { + "type": "string" + }, + "readiness": { + "type": [ + "string", + "null" + ] + }, + "relation_count": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "resource_key": { + "type": "string" + }, + "snippet": { + "type": [ + "string", + "null" + ] + }, + "state": { + "type": "string" + }, + "title": { + "type": "string" + }, + "unresolved_blocker_count": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "unresolved_review_count": { + "format": "uint", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "updated_at": { + "type": [ + "string", + "null" + ] + }, + "workspace_action_priority": { + "type": "string" + } + }, + "required": [ + "id", + "resource_key", + "title", + "state", + "priority", + "item_revision", + "workspace_action_priority", + "matched_fields", + "linked_objective_ids", + "linked_objective_keys", + "relation_count", + "blocker_count", + "unresolved_blocker_count", + "unresolved_review_count", + "evidence" + ], + "type": "object" + }, + "TicketQueryRequest": { + "additionalProperties": false, + "properties": { + "attention": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + }, + "cursor": { + "type": [ + "string", + "null" + ] + }, + "event_kinds": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + }, + "evidence": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + }, + "limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "linked_objective_id": { + "type": [ + "string", + "null" + ] + }, + "query": { + "type": [ + "string", + "null" + ] + }, + "related_ticket_id": { + "type": [ + "string", + "null" + ] + }, + "relation_kind": { + "type": [ + "string", + "null" + ] + }, + "review_status": { + "type": [ + "string", + "null" + ] + }, + "sort": { + "type": [ + "string", + "null" + ] + }, + "states": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + }, + "updated_after": { + "type": [ + "string", + "null" + ] + }, + "updated_before": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "TicketQueryResponse": { + "additionalProperties": false, + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/TicketQueryItem" + }, + "type": "array" + }, + "page": { + "$ref": "#/components/schemas/QueryPage" + }, + "record_authority": { + "type": "string" + } + }, + "required": [ + "items", + "page", + "record_authority" + ], + "type": "object" + }, + "TicketQueueGuard": { + "properties": { + "blocked_reason": { + "type": [ + "string", + "null" + ] + }, + "can_queue_for_orchestrator": { + "type": "boolean" + }, + "reason": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "can_queue_for_orchestrator" + ], + "type": "object" + }, + "TicketQueueOutcome": { + "properties": { + "queued_tickets": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requested_ticket": { + "type": "string" + } + }, + "required": [ + "requested_ticket", + "queued_tickets" + ], + "type": "object" + }, + "TicketRef": { + "properties": { + "id": { + "type": "string" + }, + "resource_key": { + "type": [ + "string", + "null" + ] + }, + "slug": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/TicketStatus" + } + }, + "required": [ + "id", + "slug", + "status" + ], + "type": "object" + }, + "TicketReference": { + "properties": { + "kind": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "required": [ + "kind", + "target" + ], + "type": "object" + }, + "TicketRelation": { + "additionalProperties": false, + "properties": { + "at": { + "type": "string" + }, + "author": { + "type": "string" + }, + "kind": { + "$ref": "#/components/schemas/TicketRelationKind" + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "target": { + "type": "string" + }, + "ticket_id": { + "type": "string" + } + }, + "required": [ + "ticket_id", + "kind", + "target", + "author", + "at" + ], + "type": "object" + }, + "TicketRelationBlocker": { + "properties": { + "blocking_state": { + "$ref": "#/components/schemas/TicketWorkflowState" + }, + "blocking_ticket": { + "type": "string" + }, + "note": { + "type": [ + "string", + "null" + ] + }, + "reason_kind": { + "type": "string" + }, + "relation_kind": { + "$ref": "#/components/schemas/TicketRelationKind" + } + }, + "required": [ + "blocking_ticket", + "reason_kind", + "relation_kind", + "blocking_state" + ], + "type": "object" + }, + "TicketRelationKind": { + "enum": [ + "depends_on", + "blocks", + "related", + "supersedes", + "duplicate_of" + ], + "type": "string" + }, + "TicketRelationNotice": { + "properties": { + "kind": { + "$ref": "#/components/schemas/TicketRelationKind" + }, + "message": { + "type": "string" + }, + "related_ticket": { + "type": "string" + } + }, + "required": [ + "related_ticket", + "kind", + "message" + ], + "type": "object" + }, + "TicketRelationRemoveRequest": { + "additionalProperties": false, + "properties": { + "kind": { + "$ref": "#/components/schemas/TicketRelationKind" + }, + "target": { + "type": "string" + } + }, + "required": [ + "kind", + "target" + ], + "type": "object" + }, + "TicketRelationSearchRequest": { + "additionalProperties": false, + "properties": { + "kind": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketRelationKind" + }, + { + "type": "null" + } + ] + }, + "ticket": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketIdOrSlug" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + "TicketRelationView": { + "properties": { + "blockers": { + "items": { + "$ref": "#/components/schemas/TicketRelationBlocker" + }, + "type": "array" + }, + "incoming": { + "items": { + "$ref": "#/components/schemas/DerivedTicketRelation" + }, + "type": "array" + }, + "notices": { + "items": { + "$ref": "#/components/schemas/TicketRelationNotice" + }, + "type": "array" + }, + "outgoing": { + "items": { + "$ref": "#/components/schemas/TicketRelation" + }, + "type": "array" + } + }, + "required": [ + "outgoing", + "incoming", + "blockers", + "notices" + ], + "type": "object" + }, + "TicketRoleAssignmentMutationResponse": { + "additionalProperties": false, + "properties": { + "assignment": { + "anyOf": [ + { + "$ref": "#/components/schemas/TicketRoleAssignmentRecord" + }, + { + "type": "null" + } + ] + }, + "ticket_id": { + "type": "string" + }, + "workspace_id": { + "type": "string" + } + }, + "required": [ + "workspace_id", + "ticket_id" + ], + "type": "object" + }, + "TicketRoleAssignmentRecord": { + "additionalProperties": false, + "properties": { + "assigned_at": { + "type": "string" + }, + "assigned_by": { + "type": "string" + }, + "assignment_id": { + "type": "string" + }, + "principal": { + "$ref": "#/components/schemas/TicketAssignmentPrincipal" + }, + "role": { + "$ref": "#/components/schemas/TicketAssignmentRole" + }, + "ticket_id": { + "type": "string" + }, + "workspace_id": { + "type": "string" + } + }, + "required": [ + "workspace_id", + "ticket_id", + "assignment_id", + "role", + "principal", + "assigned_by", + "assigned_at" + ], + "type": "object" + }, + "TicketRoleAssignmentSummary": { + "additionalProperties": false, + "properties": { + "assigned_at": { + "type": "string" + }, + "assigned_by": { + "type": "string" + }, + "assignment_id": { + "type": "string" + }, + "principal": { + "$ref": "#/components/schemas/TicketAssignmentPrincipal" + }, + "role": { + "type": "string" + } + }, + "required": [ + "assignment_id", + "role", + "principal", + "assigned_by", + "assigned_at" + ], + "type": "object" + }, + "TicketRoleAssignmentsResponse": { + "additionalProperties": false, + "properties": { + "assignments": { + "items": { + "$ref": "#/components/schemas/TicketRoleAssignmentRecord" + }, + "type": "array" + }, + "ticket_id": { + "type": "string" + }, + "workspace_id": { + "type": "string" + } + }, + "required": [ + "workspace_id", + "ticket_id", + "assignments" + ], + "type": "object" + }, + "TicketShowRequest": { + "additionalProperties": false, + "properties": { + "event_cursor": { + "type": [ + "string", + "null" + ] + }, + "event_limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "TicketStateChange": { + "properties": { + "author": { + "type": [ + "string", + "null" + ] + }, + "body": { + "$ref": "#/components/schemas/MarkdownText" + }, + "from": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "references": { + "items": { + "$ref": "#/components/schemas/TicketReference" + }, + "type": "array" + }, + "to": { + "type": "string" + } + }, + "required": [ + "from", + "to", + "reason", + "body", + "references" + ], + "type": "object" + }, + "TicketStatus": { + "enum": [ + "Open", + "Closed" + ], + "type": "string" + }, + "TicketSummary": { + "properties": { + "id": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "labels": { + "items": { + "type": "string" + }, + "type": "array" + }, + "priority": { + "type": "string" + }, + "queued_at": { + "type": [ + "string", + "null" + ] + }, + "queued_by": { + "type": [ + "string", + "null" + ] + }, + "readiness": { + "type": [ + "string", + "null" + ] + }, + "resource_key": { + "type": [ + "string", + "null" + ] + }, + "slug": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/ExtensibleTicketStatus" + }, + "title": { + "type": "string" + }, + "updated_at": { + "type": [ + "string", + "null" + ] + }, + "workflow_state": { + "$ref": "#/components/schemas/TicketWorkflowState" + }, + "workflow_state_explicit": { + "type": "boolean" + } + }, + "required": [ + "id", + "slug", + "title", + "status", + "kind", + "priority", + "labels", + "workflow_state", + "workflow_state_explicit" + ], + "type": "object" + }, + "TicketSummarySearchQuery": { + "additionalProperties": false, + "properties": { + "limit": { + "format": "uint", + "maximum": 1000, + "minimum": 0, + "type": [ + "integer", + "null" + ] + }, + "state": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "TicketTargetEdit": { + "oneOf": [ + { + "properties": { + "action": { + "const": "set", + "type": "string" + }, + "ref_selector": { + "type": [ + "string", + "null" + ] + }, + "repository_key": { + "type": "string" + } + }, + "required": [ + "action", + "repository_key" + ], + "type": "object" + }, + { + "properties": { + "action": { + "const": "clear", + "type": "string" + } + }, + "required": [ + "action" + ], + "type": "object" + } + ] + }, + "TicketWorkflowState": { + "enum": [ + "planning", + "ready", + "queued", + "in_progress", + "done", + "closed" + ], + "type": "string" + }, + "TicketWorkspaceNextAction": { + "enum": [ + "clarify", + "queue_for_orchestrator", + "close", + "wait_for_orchestrator" + ], + "type": "string" + }, "ToolchainContract": { "additionalProperties": false, "properties": { @@ -4809,7 +9322,7 @@ "info": { "title": "Yoi Server API", "version": "0.1.0", - "x-yoi-source-digest": "sha256:386c56c830b49766e9f523f08c5bd4e24de490ba18c99c3d04063021d6b33352" + "x-yoi-source-digest": "sha256:0026ff3d0f1d267e4de3f154a14f4ef3f7554b603a376820f0775e5deb16a083" }, "openapi": "3.1.0", "paths": { @@ -5227,6 +9740,114 @@ } } }, + "/api/objectives": { + "get": { + "operationId": "objective_list_alias", + "parameters": [ + { + "explode": true, + "in": "query", + "name": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/ObjectiveListQuery" + }, + "style": "form" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveListResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/objectives/{id}": { + "get": { + "operationId": "objective_get_alias", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, "/api/repositories": { "get": { "operationId": "repository_list_alias", @@ -5389,6 +10010,114 @@ ] } }, + "/api/tickets": { + "get": { + "operationId": "ticket_list_alias", + "parameters": [ + { + "explode": true, + "in": "query", + "name": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/TicketListHttpQuery" + }, + "style": "form" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketListResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/tickets/{id}": { + "get": { + "operationId": "ticket_get_alias", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, "/api/w/{workspace_id}/config/projections/prompts": { "get": { "operationId": "workspace_prompt_projection", @@ -6210,6 +10939,98 @@ } } }, + "/api/w/{workspace_id}/internal/reviewer-child-sessions": { + "post": { + "operationId": "merge_request_reviewer_child_register", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterReviewerChildSessionRequest" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, "/api/w/{workspace_id}/memory": { "get": { "operationId": "memory_document", @@ -6602,6 +11423,1163 @@ ] } }, + "/api/w/{workspace_id}/merge-requests": { + "get": { + "operationId": "merge_request_list", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": true, + "in": "query", + "name": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/MergeRequestListQuery" + }, + "style": "form" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MergeRequestListResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/merge-requests/{merge_request_id}": { + "get": { + "operationId": "merge_request_show", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "merge_request_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": true, + "in": "query", + "name": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/MergeRequestThreadQuery" + }, + "style": "form" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MergeRequestDetailResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/objectives": { + "get": { + "operationId": "objective_list", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": true, + "in": "query", + "name": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/ObjectiveListQuery" + }, + "style": "form" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveListResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + }, + "post": { + "operationId": "objective_create", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveCreateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/objectives/query": { + "post": { + "operationId": "objective_query", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveQueryRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveQueryResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/objectives/{objective_id}": { + "get": { + "operationId": "objective_get", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "objective_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + }, + "patch": { + "operationId": "objective_edit", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "objective_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveEditRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/objectives/{objective_id}/show": { + "post": { + "operationId": "objective_show", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "objective_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveShowRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/objectives/{objective_id}/state": { + "post": { + "operationId": "objective_state_set", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "objective_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveStateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/objectives/{objective_id}/ticket-links": { + "post": { + "operationId": "objective_ticket_link", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "objective_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveLinkTicketRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/objectives/{objective_id}/ticket-links/{ticket_id}": { + "delete": { + "operationId": "objective_ticket_unlink", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "objective_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "ticket_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ObjectiveDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, "/api/w/{workspace_id}/repositories": { "get": { "operationId": "repository_list", @@ -9168,6 +15146,4486 @@ } } }, + "/api/w/{workspace_id}/tickets": { + "get": { + "operationId": "ticket_list", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": true, + "in": "query", + "name": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/TicketListHttpQuery" + }, + "style": "form" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketListResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + }, + "post": { + "operationId": "ticket_create_record", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewTicket" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketRef" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/default-intake-ready-body": { + "post": { + "operationId": "ticket_default_intake_ready_body", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DefaultIntakeReadyBodyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/string" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/doctor": { + "get": { + "operationId": "ticket_doctor", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDoctorReport" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/orchestration-plans/search": { + "post": { + "operationId": "ticket_orchestration_plan_query", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketOrchestrationPlanSearchRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Array_of_OrchestrationPlanRecord" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/query": { + "post": { + "operationId": "ticket_query", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketQueryRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketQueryResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/relations/search": { + "post": { + "operationId": "ticket_relation_query", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketRelationSearchRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Array_of_TicketRelation" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/search": { + "get": { + "operationId": "ticket_summary_search", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": true, + "in": "query", + "name": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/TicketSummarySearchQuery" + }, + "style": "form" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Array_of_TicketSummary" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}": { + "get": { + "operationId": "ticket_get", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + }, + "patch": { + "operationId": "ticket_edit", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BrowserEditTicketRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/{id}/assignments": { + "get": { + "operationId": "ticket_assignment_list", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketRoleAssignmentsResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/{id}/assignments/{role}": { + "delete": { + "operationId": "ticket_assignment_clear", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "role", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": true, + "in": "query", + "name": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/ClearTicketRoleAssignmentQuery" + }, + "style": "form" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketRoleAssignmentMutationResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + }, + "put": { + "operationId": "ticket_assignment_set", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "role", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetTicketRoleAssignmentRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketRoleAssignmentMutationResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/{id}/close": { + "post": { + "operationId": "ticket_close", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BrowserCloseTicketRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/{id}/dependency-check": { + "get": { + "operationId": "ticket_dependency_check", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDependencyCheck" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/events": { + "post": { + "operationId": "ticket_event_append", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BrowserAppendTicketEventRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/{id}/implementation-cancellations": { + "post": { + "operationId": "ticket_implementation_cancel", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CancelTicketImplementationRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/{id}/intake-summaries": { + "post": { + "operationId": "ticket_intake_summary_add", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketIntakeSummary" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/item": { + "patch": { + "operationId": "ticket_record_item_edit", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketItemEdit" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ticket" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/merge-request": { + "post": { + "operationId": "merge_request_open", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OpenMergeRequestRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicMergeRequest" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/merge-request/complete": { + "post": { + "operationId": "merge_request_complete", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CompleteMergeRequestRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MergeEvent" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/merge-request/readiness": { + "get": { + "operationId": "merge_request_readiness", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MergeRequestReadinessResponse" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/merge-request/repair-source": { + "post": { + "operationId": "merge_request_selector_repair", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepairMergeRequestSelectorRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublicMergeRequest" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/{id}/merge-request/review-capabilities": { + "post": { + "operationId": "merge_request_review_capability_register", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterMergeRequestReviewCapabilityRequest" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/merge-request/reviews": { + "post": { + "operationId": "merge_request_review_submit", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubmitMergeRequestReviewRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReviewEvent" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/merge-request/reviews/revoke": { + "post": { + "operationId": "merge_request_review_revoke", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RevokeMergeRequestReviewRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReviewRevokedEvent" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/merge-request/thread": { + "get": { + "operationId": "merge_request_thread", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": true, + "in": "query", + "name": "query", + "required": true, + "schema": { + "$ref": "#/components/schemas/MergeRequestThreadQuery" + }, + "style": "form" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Array_of_MergeRequestThreadEvent" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/orchestration-plans": { + "post": { + "operationId": "ticket_orchestration_plan_record", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewOrchestrationPlanRecord" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrchestrationPlanRecord" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/queue": { + "post": { + "operationId": "ticket_queue", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BrowserQueueTicketRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketQueueOutcome" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/{id}/ready": { + "post": { + "operationId": "ticket_ready", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketMarkReadyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/{id}/record": { + "get": { + "operationId": "ticket_record_get", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ticket" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/relation-view": { + "get": { + "operationId": "ticket_relation_view", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketRelationView" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/relations": { + "delete": { + "operationId": "ticket_relation_remove", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketRelationRemoveRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketRelation" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + }, + "post": { + "operationId": "ticket_relation_record", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewTicketRelation" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketRelation" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/show": { + "post": { + "operationId": "ticket_show", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketShowRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/state": { + "post": { + "operationId": "ticket_state_transition", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BrowserTransitionTicketStateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketDetail" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "browserSession": [] + } + ] + } + }, + "/api/w/{workspace_id}/tickets/{id}/state-changes": { + "post": { + "operationId": "ticket_state_change_add", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketStateChange" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/state-fields/{field}": { + "post": { + "operationId": "ticket_state_field_set", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "field", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketStateChange" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/thread-events": { + "post": { + "operationId": "ticket_thread_event_add", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewTicketEvent" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/workflow-state": { + "post": { + "operationId": "ticket_workflow_state_set", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketStateChange" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/workflow/close": { + "post": { + "operationId": "ticket_close_record", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MarkdownText" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/workflow/mark-ready": { + "post": { + "operationId": "ticket_mark_ready_record", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketMarkReadyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Ticket" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, + "/api/w/{workspace_id}/tickets/{id}/workflow/queue": { + "post": { + "operationId": "ticket_queue_record", + "parameters": [ + { + "explode": false, + "in": "path", + "name": "workspace_id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + }, + { + "explode": false, + "in": "path", + "name": "id", + "required": true, + "schema": { + "$ref": "#/components/schemas/string" + }, + "style": "simple" + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TicketQueueOutcome" + } + } + }, + "description": "Successful response" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "401": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RepositoryApiError" + } + } + }, + "description": "Error response" + } + } + } + }, "/api/w/{workspace_id}/workspace": { "get": { "operationId": "workspace_scoped", diff --git a/web/workspace/src/lib/generated/repository-api.ts b/web/workspace/src/lib/generated/repository-api.ts index 05261c9bb..c450bf1e9 100644 --- a/web/workspace/src/lib/generated/repository-api.ts +++ b/web/workspace/src/lib/generated/repository-api.ts @@ -1,6 +1,6 @@ // @generated by yoi-repository-openapi-typescript@1. Do not edit. // Input: openapi/server-api.json -// Input contract: 0.1.0 (sha256:386c56c830b49766e9f523f08c5bd4e24de490ba18c99c3d04063021d6b33352) +// Input contract: 0.1.0 (sha256:0026ff3d0f1d267e4de3f154a14f4ef3f7554b603a376820f0775e5deb16a083) // Options: repository-operation-schema-closure,openapi-3.1,format:uint64=safe-number,strict-safe-integers,sorted-output // Output: web/workspace/src/lib/generated/repository-api.ts // Regenerate/check: cargo run -q -p server-api --example generate_repository_openapi_types -- --check