feat: migrate ticket and objective domains to ServerApi

This commit is contained in:
2026-09-23 05:42:50 +09:00
parent 6cbc3a6988
commit 6d65d50ec1
11 changed files with 13759 additions and 495 deletions
Generated
+4
View File
@@ -2579,6 +2579,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"rusqlite", "rusqlite",
"schemars",
"serde", "serde",
"serde_json", "serde_json",
"tempfile", "tempfile",
@@ -3910,6 +3911,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc"
dependencies = [ dependencies = [
"chrono",
"dyn-clone", "dyn-clone",
"ref-cast", "ref-cast",
"schemars_derive", "schemars_derive",
@@ -4150,12 +4152,14 @@ version = "0.1.0"
dependencies = [ dependencies = [
"api-macros", "api-macros",
"memory", "memory",
"merge-request",
"protocol", "protocol",
"runtime-api", "runtime-api",
"schemars", "schemars",
"serde", "serde",
"serde_json", "serde_json",
"sha2 0.11.0", "sha2 0.11.0",
"ticket",
"tokio", "tokio",
"ts-rs", "ts-rs",
"webauthn-rs-proto", "webauthn-rs-proto",
+3 -3
View File
@@ -68,7 +68,7 @@ impl From<server_api::client_support::ClientError<server_api::RepositoryApiError
} }
} }
fn server_client_error( pub(crate) fn server_client_error(
backend: &BackendApiClient, backend: &BackendApiClient,
error: server_api::client_support::ClientError<server_api::RepositoryApiError>, error: server_api::client_support::ClientError<server_api::RepositoryApiError>,
) -> BackendWorkspaceClientError { ) -> BackendWorkspaceClientError {
@@ -92,7 +92,7 @@ fn server_client_error(
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct ServerBearerAuthorizer { pub(crate) struct ServerBearerAuthorizer {
authorization: String, authorization: String,
} }
@@ -114,7 +114,7 @@ impl server_api::client_support::RequestAuthorizer for ServerBearerAuthorizer {
const SERVER_RESPONSE_LIMIT: usize = 16 * 1024 * 1024; const SERVER_RESPONSE_LIMIT: usize = 16 * 1024 * 1024;
fn server_api_client( pub(crate) fn server_api_client(
backend: &BackendApiClient, backend: &BackendApiClient,
) -> Result<server_api::ServerApiClient<ServerBearerAuthorizer>, BackendWorkspaceClientError> { ) -> Result<server_api::ServerApiClient<ServerBearerAuthorizer>, BackendWorkspaceClientError> {
server_api::ServerApiClient::builder(backend.origin().as_str()) server_api::ServerApiClient::builder(backend.origin().as_str())
+292 -206
View File
@@ -1,13 +1,12 @@
use reqwest::Method; use reqwest::Method;
use serde::Serialize;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use server_api::{ use server_api::{
BrowserCreateWorkerResponse, BrowserWorkspaceOrchestratorResponse, BrowserCreateWorkerResponse, BrowserWorkspaceOrchestratorResponse,
CreateWorkspaceWorkerRequest, ListResponse, MemoryDocumentResponse, MemoryStagingListResponse, CreateWorkspaceWorkerRequest, ListResponse, MemoryDocumentResponse, MemoryStagingListResponse,
ObjectiveCreateRequest, ObjectiveDetail, ObjectiveEditRequest, ObjectiveLinkTicketRequest, ObjectiveCreateRequest, ObjectiveDetail, ObjectiveEditRequest, ObjectiveLinkTicketRequest,
ObjectiveStateRequest, ObjectiveSummary, RevokeRuntimeTrustKeyRequest, ObjectiveStateRequest, ObjectiveSummary, RevokeRuntimeTrustKeyRequest,
RuntimeTrustKeyRevealResponse, TICKET_ORCHESTRATION_PLANS_QUERY_PATH, RuntimeTrustKeyRevealResponse, WorkerLaunchOptionsResponse, WorkspaceRuntimeDetail,
TICKET_RELATIONS_QUERY_PATH, WorkerLaunchOptionsResponse, WorkspaceRuntimeDetail,
WorkspaceRuntimeResource, WorkspaceRuntimeResource,
}; };
use ticket::{ use ticket::{
@@ -22,21 +21,6 @@ use crate::{BackendApiClient, BackendWorkspaceClientError};
const DEFAULT_PRODUCT_LIST_LIMIT: usize = 1_000; const DEFAULT_PRODUCT_LIST_LIMIT: usize = 1_000;
#[derive(Debug, Deserialize)]
struct BackendObjectiveListResponse {
workspace_id: String,
limit: usize,
items: Vec<ObjectiveSummary>,
invalid_records: Vec<BackendInvalidProjectRecord>,
record_authority: String,
}
#[derive(Debug, Deserialize)]
struct BackendInvalidProjectRecord {
label: String,
reason: String,
}
/// Workspace-scoped Backend client for Ticket and Objective product state. /// Workspace-scoped Backend client for Ticket and Objective product state.
/// ///
/// Construction requires both the selected Backend URL and Workspace identity. /// Construction requires both the selected Backend URL and Workspace identity.
@@ -85,26 +69,71 @@ impl BackendWorkspaceProductClient {
&self.workspace_id &self.workspace_id
} }
fn generated<T, F, Fut>(&self, operation: F) -> Result<T, BackendWorkspaceClientError>
where
F: FnOnce(
server_api::ServerApiClient<crate::backend_workspace::ServerBearerAuthorizer>,
) -> Fut,
Fut: std::future::Future<
Output = Result<
T,
server_api::client_support::ClientError<server_api::RepositoryApiError>,
>,
>,
{
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( pub fn list_tickets(
&self, &self,
query: &TicketListQuery, query: &TicketListQuery,
) -> Result<Vec<TicketSummary>, BackendWorkspaceClientError> { ) -> Result<Vec<TicketSummary>, BackendWorkspaceClientError> {
let workspace_id = self.workspace_id.clone();
let state = ticket_list_state_query(query); 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<Ticket, BackendWorkspaceClientError> { pub fn show_ticket(&self, id: &TicketIdOrSlug) -> Result<Ticket, BackendWorkspaceClientError> {
self.get_json(&format!( let workspace_id = self.workspace_id.clone();
"/tickets/{}/record", let id = ticket_reference(id);
encode_path_segment(&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( pub fn create_ticket(
&self, &self,
input: &NewTicket, input: &NewTicket,
) -> Result<TicketRef, BackendWorkspaceClientError> { ) -> Result<TicketRef, BackendWorkspaceClientError> {
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( pub fn add_ticket_event(
@@ -112,14 +141,18 @@ impl BackendWorkspaceProductClient {
id: &TicketIdOrSlug, id: &TicketIdOrSlug,
event: &NewTicketEvent, event: &NewTicketEvent,
) -> Result<(), BackendWorkspaceClientError> { ) -> Result<(), BackendWorkspaceClientError> {
self.send_unit( let workspace_id = self.workspace_id.clone();
Method::POST, let id = ticket_reference(id);
&format!( let event = event.clone();
"/tickets/{}/thread-events", self.generated(move |client| async move {
encode_path_segment(&ticket_reference(id)) client
), .ticket_thread_event_add(
Some(event), workspace_id,
) id,
server_api::TicketThreadEventRequest(event),
)
.await
})
} }
pub fn set_ticket_workflow_state( pub fn set_ticket_workflow_state(
@@ -127,14 +160,18 @@ impl BackendWorkspaceProductClient {
id: &TicketIdOrSlug, id: &TicketIdOrSlug,
change: &TicketStateChange, change: &TicketStateChange,
) -> Result<(), BackendWorkspaceClientError> { ) -> Result<(), BackendWorkspaceClientError> {
self.send_unit( let workspace_id = self.workspace_id.clone();
Method::POST, let id = ticket_reference(id);
&format!( let change = change.clone();
"/tickets/{}/workflow-state", self.generated(move |client| async move {
encode_path_segment(&ticket_reference(id)) client
), .ticket_workflow_state_set(
Some(change), workspace_id,
) id,
server_api::TicketStateChangeRequest(change),
)
.await
})
} }
pub fn close_ticket( pub fn close_ticket(
@@ -142,14 +179,18 @@ impl BackendWorkspaceProductClient {
id: &TicketIdOrSlug, id: &TicketIdOrSlug,
resolution: &MarkdownText, resolution: &MarkdownText,
) -> Result<(), BackendWorkspaceClientError> { ) -> Result<(), BackendWorkspaceClientError> {
self.send_unit( let workspace_id = self.workspace_id.clone();
Method::POST, let id = ticket_reference(id);
&format!( let resolution = resolution.clone();
"/tickets/{}/workflow/close", self.generated(move |client| async move {
encode_path_segment(&ticket_reference(id)) client
), .ticket_close_record(
Some(resolution), workspace_id,
) id,
server_api::TicketCloseRecordRequest(resolution),
)
.await
})
} }
pub fn add_ticket_relation( pub fn add_ticket_relation(
@@ -157,14 +198,19 @@ impl BackendWorkspaceProductClient {
id: &TicketIdOrSlug, id: &TicketIdOrSlug,
relation: &NewTicketRelation, relation: &NewTicketRelation,
) -> Result<TicketRelation, BackendWorkspaceClientError> { ) -> Result<TicketRelation, BackendWorkspaceClientError> {
self.send_json( let workspace_id = self.workspace_id.clone();
Method::POST, let id = ticket_reference(id);
&format!( let relation = relation.clone();
"/tickets/{}/relations", self.generated(move |client| async move {
encode_path_segment(&ticket_reference(id)) client
), .ticket_relation_record(
Some(relation), workspace_id,
) id,
server_api::CreateTicketRelationRequest(relation),
)
.await
.map(|response| response.0)
})
} }
pub fn query_ticket_relations( pub fn query_ticket_relations(
@@ -172,28 +218,42 @@ impl BackendWorkspaceProductClient {
ticket: Option<&TicketIdOrSlug>, ticket: Option<&TicketIdOrSlug>,
kind: Option<TicketRelationKind>, kind: Option<TicketRelationKind>,
) -> Result<Vec<TicketRelation>, BackendWorkspaceClientError> { ) -> Result<Vec<TicketRelation>, BackendWorkspaceClientError> {
#[derive(Serialize)] let workspace_id = self.workspace_id.clone();
struct Query<'a> { let ticket = ticket.cloned();
ticket: Option<&'a TicketIdOrSlug>, self.generated(move |client| async move {
kind: Option<TicketRelationKind>, client
} .ticket_relation_query(
self.send_json( workspace_id,
Method::POST, server_api::TicketRelationSearchRequest { ticket, kind },
TICKET_RELATIONS_QUERY_PATH, )
Some(&Query { ticket, kind }), .await
) .map(|response| response.0)
})
} }
pub fn ticket_doctor(&self) -> Result<TicketDoctorReport, BackendWorkspaceClientError> { pub fn ticket_doctor(&self) -> Result<TicketDoctorReport, BackendWorkspaceClientError> {
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( pub fn list_objectives(
&self, &self,
limit: usize, limit: usize,
) -> Result<ListResponse<ObjectiveSummary>, BackendWorkspaceClientError> { ) -> Result<ListResponse<ObjectiveSummary>, BackendWorkspaceClientError> {
let response: BackendObjectiveListResponse = let workspace_id = self.workspace_id.clone();
self.get_json(&format!("/objectives?limit={limit}"))?; let response = self.generated(move |client| async move {
client
.objective_list(
workspace_id,
server_api::ObjectiveListQuery { limit: Some(limit) },
)
.await
})?;
Ok(ListResponse { Ok(ListResponse {
workspace_id: response.workspace_id, workspace_id: response.workspace_id,
limit: response.limit, limit: response.limit,
@@ -212,14 +272,20 @@ impl BackendWorkspaceProductClient {
} }
pub fn show_objective(&self, id: &str) -> Result<ObjectiveDetail, BackendWorkspaceClientError> { pub fn show_objective(&self, id: &str) -> Result<ObjectiveDetail, BackendWorkspaceClientError> {
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( pub fn create_objective(
&self, &self,
input: &ObjectiveCreateRequest, input: &ObjectiveCreateRequest,
) -> Result<ObjectiveDetail, BackendWorkspaceClientError> { ) -> Result<ObjectiveDetail, BackendWorkspaceClientError> {
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( pub fn edit_objective(
@@ -227,10 +293,11 @@ impl BackendWorkspaceProductClient {
id: &str, id: &str,
input: &ObjectiveEditRequest, input: &ObjectiveEditRequest,
) -> Result<ObjectiveDetail, BackendWorkspaceClientError> { ) -> Result<ObjectiveDetail, BackendWorkspaceClientError> {
self.send_json( let workspace_id = self.workspace_id.clone();
Method::PATCH, let id = id.to_string();
&format!("/objectives/{}", encode_path_segment(id)), let input = input.clone();
Some(input), self.generated(
move |client| async move { client.objective_edit(workspace_id, id, input).await },
) )
} }
@@ -239,11 +306,12 @@ impl BackendWorkspaceProductClient {
id: &str, id: &str,
input: &ObjectiveStateRequest, input: &ObjectiveStateRequest,
) -> Result<ObjectiveDetail, BackendWorkspaceClientError> { ) -> Result<ObjectiveDetail, BackendWorkspaceClientError> {
self.send_json( let workspace_id = self.workspace_id.clone();
Method::POST, let id = id.to_string();
&format!("/objectives/{}/state", encode_path_segment(id)), let input = input.clone();
Some(input), self.generated(move |client| async move {
) client.objective_state_set(workspace_id, id, input).await
})
} }
pub fn link_objective_ticket( pub fn link_objective_ticket(
@@ -251,11 +319,12 @@ impl BackendWorkspaceProductClient {
id: &str, id: &str,
input: &ObjectiveLinkTicketRequest, input: &ObjectiveLinkTicketRequest,
) -> Result<ObjectiveDetail, BackendWorkspaceClientError> { ) -> Result<ObjectiveDetail, BackendWorkspaceClientError> {
self.send_json( let workspace_id = self.workspace_id.clone();
Method::POST, let id = id.to_string();
&format!("/objectives/{}/ticket-links", encode_path_segment(id)), let input = input.clone();
Some(input), self.generated(move |client| async move {
) client.objective_ticket_link(workspace_id, id, input).await
})
} }
pub fn unlink_objective_ticket( pub fn unlink_objective_ticket(
@@ -263,15 +332,14 @@ impl BackendWorkspaceProductClient {
id: &str, id: &str,
ticket_id: &str, ticket_id: &str,
) -> Result<ObjectiveDetail, BackendWorkspaceClientError> { ) -> Result<ObjectiveDetail, BackendWorkspaceClientError> {
self.send_json::<(), _>( let workspace_id = self.workspace_id.clone();
Method::DELETE, let id = id.to_string();
&format!( let ticket_id = ticket_id.to_string();
"/objectives/{}/ticket-links/{}", self.generated(move |client| async move {
encode_path_segment(id), client
encode_path_segment(ticket_id) .objective_ticket_unlink(workspace_id, id, ticket_id)
), .await
None, })
)
} }
pub fn list_runtimes( pub fn list_runtimes(
@@ -387,17 +455,6 @@ impl BackendWorkspaceProductClient {
response.json().map_err(BackendWorkspaceClientError::Http) response.json().map_err(BackendWorkspaceClientError::Http)
} }
fn send_unit<B: Serialize + ?Sized>(
&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<B: Serialize + ?Sized>( fn request<B: Serialize + ?Sized>(
&self, &self,
method: Method, method: Method,
@@ -419,15 +476,17 @@ impl BackendWorkspaceProductClient {
impl TicketBackend for BackendWorkspaceProductClient { impl TicketBackend for BackendWorkspaceProductClient {
fn default_intake_ready_state_change_body(&self, from: &str) -> String { fn default_intake_ready_state_change_body(&self, from: &str) -> String {
#[derive(Serialize)] let workspace_id = self.workspace_id.clone();
struct Request<'a> { let from = from.to_string();
from: &'a str, self.generated(move |client| async move {
} client
self.send_json( .ticket_default_intake_ready_body(
Method::POST, workspace_id,
"/tickets/default-intake-ready-body", server_api::DefaultIntakeReadyBodyRequest { from },
Some(&Request { from }), )
) .await
.map(|response| response.0)
})
.unwrap_or_else(|error| error.to_string()) .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<Ticket> { fn edit_item(&self, id: TicketIdOrSlug, edit: TicketItemEdit) -> ticket::Result<Ticket> {
self.send_json( let workspace_id = self.workspace_id.clone();
Method::PATCH, let id = ticket_reference(&id);
&format!( self.generated(move |client| async move {
"/tickets/{}/item", client
encode_path_segment(&ticket_reference(&id)) .ticket_record_item_edit(
), workspace_id,
Some(&edit), id,
) server_api::EditTicketRecordItemRequest(edit),
)
.await
.map(|response| response.0)
})
.map_err(ticket_client_error) .map_err(ticket_client_error)
} }
fn dependency_check(&self, id: TicketIdOrSlug) -> ticket::Result<TicketDependencyCheck> { fn dependency_check(&self, id: TicketIdOrSlug) -> ticket::Result<TicketDependencyCheck> {
self.get_json(&format!( let workspace_id = self.workspace_id.clone();
"/tickets/{}/dependency-check", let id = ticket_reference(&id);
encode_path_segment(&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) .map_err(ticket_client_error)
} }
@@ -473,14 +540,17 @@ impl TicketBackend for BackendWorkspaceProductClient {
id: TicketIdOrSlug, id: TicketIdOrSlug,
change: TicketStateChange, change: TicketStateChange,
) -> ticket::Result<()> { ) -> ticket::Result<()> {
self.send_unit( let workspace_id = self.workspace_id.clone();
Method::POST, let id = ticket_reference(&id);
&format!( self.generated(move |client| async move {
"/tickets/{}/state-changes", client
encode_path_segment(&ticket_reference(&id)) .ticket_state_change_add(
), workspace_id,
Some(&change), id,
) server_api::TicketStateChangeRequest(change),
)
.await
})
.map_err(ticket_client_error) .map_err(ticket_client_error)
} }
@@ -489,14 +559,17 @@ impl TicketBackend for BackendWorkspaceProductClient {
id: TicketIdOrSlug, id: TicketIdOrSlug,
summary: TicketIntakeSummary, summary: TicketIntakeSummary,
) -> ticket::Result<()> { ) -> ticket::Result<()> {
self.send_unit( let workspace_id = self.workspace_id.clone();
Method::POST, let id = ticket_reference(&id);
&format!( self.generated(move |client| async move {
"/tickets/{}/intake-summaries", client
encode_path_segment(&ticket_reference(&id)) .ticket_intake_summary_add(
), workspace_id,
Some(&summary), id,
) server_api::TicketIntakeSummaryRequest(summary),
)
.await
})
.map_err(ticket_client_error) .map_err(ticket_client_error)
} }
@@ -506,15 +579,19 @@ impl TicketBackend for BackendWorkspaceProductClient {
field: &str, field: &str,
change: TicketStateChange, change: TicketStateChange,
) -> ticket::Result<()> { ) -> ticket::Result<()> {
self.send_unit( let workspace_id = self.workspace_id.clone();
Method::POST, let id = ticket_reference(&id);
&format!( let field = field.to_string();
"/tickets/{}/state-fields/{}", self.generated(move |client| async move {
encode_path_segment(&ticket_reference(&id)), client
encode_path_segment(field) .ticket_state_field_set(
), workspace_id,
Some(&change), id,
) field,
server_api::TicketStateChangeRequest(change),
)
.await
})
.map_err(ticket_client_error) .map_err(ticket_client_error)
} }
@@ -528,14 +605,19 @@ impl TicketBackend for BackendWorkspaceProductClient {
} }
fn mark_ready(&self, id: TicketIdOrSlug, request: TicketMarkReady) -> ticket::Result<Ticket> { fn mark_ready(&self, id: TicketIdOrSlug, request: TicketMarkReady) -> ticket::Result<Ticket> {
self.send_json( let workspace_id = self.workspace_id.clone();
Method::POST, let id = ticket_reference(&id);
&format!( let request = server_api::TicketMarkReadyRequest {
"/tickets/{}/workflow/mark-ready", operation_key: request.operation_key,
encode_path_segment(&ticket_reference(&id)) reason: request.reason,
), intake_summary: request.intake_summary,
Some(&request), };
) 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) .map_err(ticket_client_error)
} }
@@ -544,14 +626,14 @@ impl TicketBackend for BackendWorkspaceProductClient {
id: TicketIdOrSlug, id: TicketIdOrSlug,
_queued_by: &str, _queued_by: &str,
) -> ticket::Result<ticket::TicketQueueOutcome> { ) -> ticket::Result<ticket::TicketQueueOutcome> {
self.send_json::<(), _>( let workspace_id = self.workspace_id.clone();
Method::POST, let id = ticket_reference(&id);
&format!( self.generated(move |client| async move {
"/tickets/{}/workflow/queue", client
encode_path_segment(&ticket_reference(&id)) .ticket_queue_record(workspace_id, id)
), .await
None, .map(|response| response.0)
) })
.map_err(ticket_client_error) .map_err(ticket_client_error)
} }
@@ -575,22 +657,19 @@ impl TicketBackend for BackendWorkspaceProductClient {
kind: TicketRelationKind, kind: TicketRelationKind,
target: TicketIdOrSlug, target: TicketIdOrSlug,
) -> ticket::Result<TicketRelation> { ) -> ticket::Result<TicketRelation> {
#[derive(Serialize)] let workspace_id = self.workspace_id.clone();
struct Request { let id = ticket_reference(&id);
kind: TicketRelationKind, let target = ticket_reference(&target);
target: String, self.generated(move |client| async move {
} client
self.send_json( .ticket_relation_remove(
Method::DELETE, workspace_id,
&format!( id,
"/tickets/{}/relations", server_api::TicketRelationRemoveRequest { kind, target },
encode_path_segment(&ticket_reference(&id)) )
), .await
Some(&Request { .map(|response| response.0)
kind, })
target: ticket_reference(&target),
}),
)
.map_err(ticket_client_error) .map_err(ticket_client_error)
} }
@@ -604,10 +683,14 @@ impl TicketBackend for BackendWorkspaceProductClient {
} }
fn relation_view(&self, id: TicketIdOrSlug) -> ticket::Result<TicketRelationView> { fn relation_view(&self, id: TicketIdOrSlug) -> ticket::Result<TicketRelationView> {
self.get_json(&format!( let workspace_id = self.workspace_id.clone();
"/tickets/{}/relation-view", let id = ticket_reference(&id);
encode_path_segment(&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) .map_err(ticket_client_error)
} }
@@ -616,14 +699,18 @@ impl TicketBackend for BackendWorkspaceProductClient {
id: TicketIdOrSlug, id: TicketIdOrSlug,
record: NewOrchestrationPlanRecord, record: NewOrchestrationPlanRecord,
) -> ticket::Result<OrchestrationPlanRecord> { ) -> ticket::Result<OrchestrationPlanRecord> {
self.send_json( let workspace_id = self.workspace_id.clone();
Method::POST, let id = ticket_reference(&id);
&format!( self.generated(move |client| async move {
"/tickets/{}/orchestration-plans", client
encode_path_segment(&ticket_reference(&id)) .ticket_orchestration_plan_record(
), workspace_id,
Some(&record), id,
) server_api::CreateTicketOrchestrationPlanRequest(record),
)
.await
.map(|response| response.0)
})
.map_err(ticket_client_error) .map_err(ticket_client_error)
} }
@@ -632,16 +719,16 @@ impl TicketBackend for BackendWorkspaceProductClient {
ticket: Option<TicketIdOrSlug>, ticket: Option<TicketIdOrSlug>,
kind: Option<OrchestrationPlanKind>, kind: Option<OrchestrationPlanKind>,
) -> ticket::Result<Vec<OrchestrationPlanRecord>> { ) -> ticket::Result<Vec<OrchestrationPlanRecord>> {
#[derive(Serialize)] let workspace_id = self.workspace_id.clone();
struct Query { self.generated(move |client| async move {
ticket: Option<TicketIdOrSlug>, client
kind: Option<OrchestrationPlanKind>, .ticket_orchestration_plan_query(
} workspace_id,
self.send_json( server_api::TicketOrchestrationPlanSearchRequest { ticket, kind },
Method::POST, )
TICKET_ORCHESTRATION_PLANS_QUERY_PATH, .await
Some(&Query { ticket, kind }), .map(|response| response.0)
) })
.map_err(ticket_client_error) .map_err(ticket_client_error)
} }
@@ -649,7 +736,6 @@ impl TicketBackend for BackendWorkspaceProductClient {
self.ticket_doctor().map_err(ticket_client_error) self.ticket_doctor().map_err(ticket_client_error)
} }
} }
fn ticket_client_error(error: BackendWorkspaceClientError) -> TicketError { fn ticket_client_error(error: BackendWorkspaceClientError) -> TicketError {
TicketError::Sqlite(format!("Backend request failed: {error}")) TicketError::Sqlite(format!("Backend request failed: {error}"))
} }
+1
View File
@@ -7,6 +7,7 @@ license.workspace = true
[dependencies] [dependencies]
chrono = { version = "0.4", default-features = false, features = ["clock", "serde"] } chrono = { version = "0.4", default-features = false, features = ["clock", "serde"] }
rusqlite.workspace = true rusqlite.workspace = true
schemars = { workspace = true, features = ["chrono04"] }
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true serde_json.workspace = true
thiserror.workspace = true thiserror.workspace = true
+22 -16
View File
@@ -18,7 +18,7 @@ const DOMAIN_TABLES: [&str; 5] = [
"merge_request_reviewer_child_sessions", "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")] #[serde(rename_all = "snake_case")]
pub enum MergeRequestState { pub enum MergeRequestState {
Open, 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")] #[serde(rename_all = "snake_case")]
pub enum ReviewDecision { pub enum ReviewDecision {
Approve, Approve,
RequestChanges, RequestChanges,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum FindingSeverity { pub enum FindingSeverity {
Blocker, Blocker,
@@ -57,7 +57,7 @@ pub enum FindingSeverity {
Minor, Minor,
Note, Note,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ReviewFinding { pub struct ReviewFinding {
pub severity: FindingSeverity, pub severity: FindingSeverity,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -68,7 +68,7 @@ pub struct ReviewFinding {
pub line: Option<u32>, pub line: Option<u32>,
pub body: String, pub body: String,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct WorkerIdentity { pub struct WorkerIdentity {
pub runtime_id: String, pub runtime_id: String,
pub worker_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 struct ReviewRequestedEvent {
pub event_id: String, pub event_id: String,
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub sequence: u64, pub sequence: u64,
pub subject_ref: String, pub subject_ref: String,
pub requested_by: WorkerIdentity, pub requested_by: WorkerIdentity,
pub reviewer: WorkerIdentity, pub reviewer: WorkerIdentity,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ReviewEvent { pub struct ReviewEvent {
pub event_id: String, pub event_id: String,
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub sequence: u64, pub sequence: u64,
pub request_event_id: String, pub request_event_id: String,
pub subject_ref: String, pub subject_ref: String,
@@ -112,9 +114,10 @@ pub struct ReviewEvent {
pub reviewer: WorkerIdentity, pub reviewer: WorkerIdentity,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ReviewRevokedEvent { pub struct ReviewRevokedEvent {
pub event_id: String, pub event_id: String,
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub sequence: u64, pub sequence: u64,
pub review_event_id: String, pub review_event_id: String,
pub subject_ref: String, pub subject_ref: String,
@@ -122,39 +125,42 @@ pub struct ReviewRevokedEvent {
pub revoked_by: WorkerIdentity, pub revoked_by: WorkerIdentity,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ReviewCancelledEvent { pub struct ReviewCancelledEvent {
pub event_id: String, pub event_id: String,
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub sequence: u64, pub sequence: u64,
pub request_event_id: String, pub request_event_id: String,
pub subject_ref: String, pub subject_ref: String,
pub reason: String, pub reason: String,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct CommentEvent { pub struct CommentEvent {
pub event_id: String, pub event_id: String,
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub sequence: u64, pub sequence: u64,
pub body: String, pub body: String,
pub author: WorkerIdentity, pub author: WorkerIdentity,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum MergeStrategy { pub enum MergeStrategy {
FastForward, FastForward,
Merge, Merge,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum ConflictResolution { pub enum ConflictResolution {
None, None,
Clean, Clean,
ConflictsResolved, ConflictsResolved,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct MergeEvent { pub struct MergeEvent {
pub event_id: String, pub event_id: String,
#[schemars(range(min = 0, max = 9_007_199_254_740_991_u64))]
pub sequence: u64, pub sequence: u64,
pub operation_id: String, pub operation_id: String,
pub approval_event_id: String, pub approval_event_id: String,
@@ -166,7 +172,7 @@ pub struct MergeEvent {
pub merged_by: WorkerIdentity, pub merged_by: WorkerIdentity,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")] #[serde(tag = "kind", rename_all = "snake_case")]
pub enum MergeRequestThreadEvent { pub enum MergeRequestThreadEvent {
ReviewRequested(ReviewRequestedEvent), 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 struct MergeRequest {
pub workspace_id: String, pub workspace_id: String,
pub merge_request_id: String, pub merge_request_id: String,
@@ -313,7 +319,7 @@ pub struct ReadinessCheck {
pub current_subject_ref: Option<String>, pub current_subject_ref: Option<String>,
pub auth: MergeRequestAuth, pub auth: MergeRequestAuth,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ReadinessReport { pub struct ReadinessReport {
pub ready: bool, pub ready: bool,
pub blockers: Vec<String>, pub blockers: Vec<String>,
+2
View File
@@ -12,12 +12,14 @@ typescript = ["dep:ts-rs", "protocol/typescript"]
[dependencies] [dependencies]
api-macros = { workspace = true, features = ["reqwest", "axum", "openapi"] } api-macros = { workspace = true, features = ["reqwest", "axum", "openapi"] }
memory.workspace = true memory.workspace = true
merge-request.workspace = true
protocol.workspace = true protocol.workspace = true
runtime-api.workspace = true runtime-api.workspace = true
schemars.workspace = true schemars.workspace = true
serde = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true serde_json.workspace = true
sha2.workspace = true sha2.workspace = true
ticket.workspace = true
ts-rs = { version = "12.0.1", optional = true } ts-rs = { version = "12.0.1", optional = true }
webauthn-rs-proto = "0.5.5" webauthn-rs-proto = "0.5.5"
workdir.workspace = true workdir.workspace = true
File diff suppressed because it is too large Load Diff
+89 -39
View File
@@ -133,7 +133,19 @@ fn sqlite_err(error: impl std::fmt::Display) -> TicketError {
TicketError::Sqlite(error.to_string()) 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 { pub enum TicketStatus {
Open, Open,
Closed, 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 { pub enum ExtensibleTicketStatus {
Open, Open,
Closed, Closed,
@@ -206,7 +220,19 @@ impl From<TicketStatus> 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")] #[serde(rename_all = "snake_case")]
pub enum TicketWorkflowState { pub enum TicketWorkflowState {
Planning, 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); pub struct MarkdownText(pub String);
impl MarkdownText { impl MarkdownText {
@@ -298,7 +324,7 @@ impl From<String> for MarkdownText {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub enum TicketIdOrSlug { pub enum TicketIdOrSlug {
Id(String), Id(String),
Slug(String), Slug(String),
@@ -325,7 +351,7 @@ impl From<String> for TicketIdOrSlug {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum TicketEventKind { pub enum TicketEventKind {
Create, 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 struct TicketReference {
pub kind: String, pub kind: String,
pub target: String, pub target: String,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct NewTicketEvent { pub struct NewTicketEvent {
pub kind: TicketEventKind, pub kind: TicketEventKind,
pub author: Option<String>, pub author: Option<String>,
@@ -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 struct TicketStateChange {
pub from: String, pub from: String,
pub to: 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 struct TicketIntakeSummary {
pub author: Option<String>, pub author: Option<String>,
pub body: MarkdownText, 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 struct NewTicket {
pub title: String, pub title: String,
pub slug: Option<String>, pub slug: Option<String>,
@@ -533,7 +559,7 @@ pub trait TicketTargetAuthority: Send + Sync {
) -> Result<ResolvedTicketTarget>; ) -> Result<ResolvedTicketTarget>;
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketMarkReady { pub struct TicketMarkReady {
pub operation_key: String, pub operation_key: String,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -685,7 +711,7 @@ fn validate_generic_state_change(
Ok(()) Ok(())
} }
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketItemEdit { pub struct TicketItemEdit {
pub title: Option<String>, pub title: Option<String>,
/// Whole-body replacement for legacy authoring surfaces. Prefer `body_replacement` /// Whole-body replacement for legacy authoring surfaces. Prefer `body_replacement`
@@ -697,7 +723,7 @@ pub struct TicketItemEdit {
pub author: Option<String>, pub author: Option<String>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketBodyReplacement { pub struct TicketBodyReplacement {
pub old_string: String, pub old_string: String,
pub new_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 struct TicketDependencyCheck {
pub ticket: TicketSummary, pub ticket: TicketSummary,
pub blockers: Vec<TicketRelationBlocker>, pub blockers: Vec<TicketRelationBlocker>,
@@ -796,7 +822,7 @@ pub struct TicketDependencyCheck {
pub recommended_action: TicketWorkspaceNextAction, pub recommended_action: TicketWorkspaceNextAction,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketQueueOutcome { pub struct TicketQueueOutcome {
pub requested_ticket: String, pub requested_ticket: String,
pub queued_tickets: Vec<String>, pub queued_tickets: Vec<String>,
@@ -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 struct TicketRef {
pub id: String, pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -932,7 +958,19 @@ pub struct TicketRef {
pub status: TicketStatus, 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")] #[serde(rename_all = "snake_case")]
pub enum TicketRelationKind { pub enum TicketRelationKind {
DependsOn, 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 struct NewTicketRelation {
pub kind: TicketRelationKind, pub kind: TicketRelationKind,
pub target: String, pub target: String,
@@ -979,7 +1017,7 @@ pub struct NewTicketRelation {
pub author: Option<String>, pub author: Option<String>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct TicketRelation { pub struct TicketRelation {
pub ticket_id: String, pub ticket_id: String,
@@ -991,7 +1029,7 @@ pub struct TicketRelation {
pub at: String, pub at: String,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct DerivedTicketRelation { pub struct DerivedTicketRelation {
pub source_ticket: String, pub source_ticket: String,
pub inverse_kind: String, pub inverse_kind: String,
@@ -1001,7 +1039,7 @@ pub struct DerivedTicketRelation {
pub at: String, pub at: String,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketRelationBlocker { pub struct TicketRelationBlocker {
pub blocking_ticket: String, pub blocking_ticket: String,
pub reason_kind: String, pub reason_kind: String,
@@ -1010,14 +1048,14 @@ pub struct TicketRelationBlocker {
pub blocking_state: TicketWorkflowState, pub blocking_state: TicketWorkflowState,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketRelationNotice { pub struct TicketRelationNotice {
pub related_ticket: String, pub related_ticket: String,
pub kind: TicketRelationKind, pub kind: TicketRelationKind,
pub message: String, 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 struct TicketRelationView {
pub outgoing: Vec<TicketRelation>, pub outgoing: Vec<TicketRelation>,
pub incoming: Vec<DerivedTicketRelation>, pub incoming: Vec<DerivedTicketRelation>,
@@ -1033,7 +1071,7 @@ pub enum TicketWorkspaceActionPriority {
Background, Background,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum TicketWorkspaceNextAction { pub enum TicketWorkspaceNextAction {
Clarify, Clarify,
@@ -1057,7 +1095,7 @@ pub struct TicketWorkspaceStateOverlay {
pub workflow_state: TicketWorkflowState, pub workflow_state: TicketWorkflowState,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketQueueGuard { pub struct TicketQueueGuard {
pub can_queue_for_orchestrator: bool, pub can_queue_for_orchestrator: bool,
pub reason: Option<String>, pub reason: Option<String>,
@@ -1473,7 +1511,19 @@ fn format_workspace_relation_blockers(blockers: &[&TicketRelationBlocker]) -> St
formatted 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")] #[serde(rename_all = "snake_case")]
pub enum OrchestrationPlanKind { pub enum OrchestrationPlanKind {
Before, 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)] #[serde(deny_unknown_fields)]
pub struct AcceptedOrchestrationPlan { pub struct AcceptedOrchestrationPlan {
pub summary: String, pub summary: String,
@@ -1545,7 +1595,7 @@ pub struct AcceptedOrchestrationPlan {
pub role_plan: Option<String>, pub role_plan: Option<String>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct NewOrchestrationPlanRecord { pub struct NewOrchestrationPlanRecord {
pub kind: OrchestrationPlanKind, pub kind: OrchestrationPlanKind,
pub related_ticket: Option<String>, pub related_ticket: Option<String>,
@@ -1554,7 +1604,7 @@ pub struct NewOrchestrationPlanRecord {
pub author: Option<String>, pub author: Option<String>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct OrchestrationPlanRecord { pub struct OrchestrationPlanRecord {
pub id: String, pub id: String,
@@ -1570,7 +1620,7 @@ pub struct OrchestrationPlanRecord {
pub at: String, pub at: String,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketMeta { pub struct TicketMeta {
pub id: String, pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -1596,7 +1646,7 @@ pub struct TicketMeta {
pub raw: BTreeMap<String, String>, pub raw: BTreeMap<String, String>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketSummary { pub struct TicketSummary {
pub id: String, pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -1651,13 +1701,13 @@ pub struct SqliteTicketListPage {
pub next: Option<SqliteTicketListCursor>, pub next: Option<SqliteTicketListCursor>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketDocument { pub struct TicketDocument {
pub body: MarkdownText, pub body: MarkdownText,
pub raw_frontmatter: BTreeMap<String, String>, pub raw_frontmatter: BTreeMap<String, String>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketEvent { pub struct TicketEvent {
pub kind: TicketEventKind, pub kind: TicketEventKind,
pub author: Option<String>, pub author: Option<String>,
@@ -1673,13 +1723,13 @@ pub struct TicketEvent {
pub attributes: BTreeMap<String, String>, pub attributes: BTreeMap<String, String>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketArtifactRef { pub struct TicketArtifactRef {
/// Path relative to the ticket's `artifacts/` directory. /// Path relative to the ticket's `artifacts/` directory.
pub relative_path: PathBuf, pub relative_path: PathBuf,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct Ticket { pub struct Ticket {
pub meta: TicketMeta, pub meta: TicketMeta,
pub document: TicketDocument, pub document: TicketDocument,
@@ -1689,20 +1739,20 @@ pub struct Ticket {
pub resolution: Option<MarkdownText>, pub resolution: Option<MarkdownText>,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub enum TicketDoctorSeverity { pub enum TicketDoctorSeverity {
Error, Error,
Warning, Warning,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketDoctorDiagnostic { pub struct TicketDoctorDiagnostic {
pub severity: TicketDoctorSeverity, pub severity: TicketDoctorSeverity,
pub message: String, pub message: String,
pub path: Option<PathBuf>, pub path: Option<PathBuf>,
} }
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TicketDoctorReport { pub struct TicketDoctorReport {
pub diagnostics: Vec<TicketDoctorDiagnostic>, pub diagnostics: Vec<TicketDoctorDiagnostic>,
} }
File diff suppressed because it is too large Load Diff
+10459 -1
View File
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
// @generated by yoi-repository-openapi-typescript@1. Do not edit. // @generated by yoi-repository-openapi-typescript@1. Do not edit.
// Input: openapi/server-api.json // 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 // 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 // Output: web/workspace/src/lib/generated/repository-api.ts
// Regenerate/check: cargo run -q -p server-api --example generate_repository_openapi_types -- --check // Regenerate/check: cargo run -q -p server-api --example generate_repository_openapi_types -- --check