fix: simplify Ticket reporting and speed up browser lists
Remove model-supplied assignment and retry identities from implementation reports; retain Host idempotency, authentication and notification evidence. Add a SQL-only browser projection and decouple auxiliary page loads. Preserve authoritative MR evidence queries. Include regression tests and component benchmarks, documenting the remaining no-match search cost.
This commit is contained in:
@@ -9,6 +9,8 @@ pub use api_macros::{ApiContract, BinaryBody, HttpMethod, TransportMetadata, Web
|
||||
mod drive;
|
||||
mod notification;
|
||||
pub use notification::*;
|
||||
mod ticket_browse;
|
||||
pub use ticket_browse::*;
|
||||
pub mod repository_openapi_typescript;
|
||||
pub use drive::*;
|
||||
mod workspace_config;
|
||||
@@ -376,6 +378,8 @@ impl_openapi_schema!(
|
||||
TicketAssignmentDiagnosticsPage,
|
||||
TicketQueryRequest,
|
||||
TicketQueryResponse,
|
||||
TicketBrowseQueryRequest,
|
||||
TicketBrowseQueryResponse,
|
||||
TicketQueueResponse,
|
||||
TicketRecord,
|
||||
TicketRecordRef,
|
||||
@@ -3033,6 +3037,14 @@ pub trait ServerApi {
|
||||
#[body] request: TicketTagsSetRequest,
|
||||
) -> Result<WorkspaceTicketTagList, RepositoryApiError>;
|
||||
|
||||
/// Lightweight browser list; deliberately excludes live MR evidence and external observations.
|
||||
#[post("/api/w/{workspace_id}/tickets/browse", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500], bearer_auth = true, browser_auth = true)]
|
||||
async fn ticket_browse(
|
||||
&self,
|
||||
#[path] workspace_id: String,
|
||||
#[body] request: TicketBrowseQueryRequest,
|
||||
) -> Result<TicketBrowseQueryResponse, RepositoryApiError>;
|
||||
|
||||
#[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,
|
||||
@@ -8058,9 +8070,8 @@ pub enum TicketImplementationResultKind {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct TicketImplementationResultRequest {
|
||||
/// Host-owned replay identity; model-facing tools derive it from the Tool call.
|
||||
pub operation_key: String,
|
||||
pub assignment_id: String,
|
||||
pub orchestrator_assignment_id: String,
|
||||
pub kind: TicketImplementationResultKind,
|
||||
pub body: String,
|
||||
pub merge_request: Option<MergeRequestReviewSubject>,
|
||||
|
||||
@@ -459,6 +459,13 @@ fn validate_ticket_browser_operations(
|
||||
request: Some("TicketTagSetRequest"),
|
||||
successes: &[("200", "Array_of_WorkspaceTag")],
|
||||
},
|
||||
OperationContract {
|
||||
path: "/api/w/{workspace_id}/tickets/browse",
|
||||
method: "post",
|
||||
operation_id: "ticket_browse",
|
||||
request: Some("TicketBrowseQueryRequest"),
|
||||
successes: &[("200", "TicketBrowseQueryResponse")],
|
||||
},
|
||||
OperationContract {
|
||||
path: "/api/w/{workspace_id}/tickets/query",
|
||||
method: "post",
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
//! Lightweight Tickets browser contract, separate from authoritative evidence queries.
|
||||
use crate::{BrowserTicketState, QueryPage};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct TicketBrowseQueryRequest {
|
||||
pub query: Option<String>,
|
||||
#[serde(default)]
|
||||
#[cfg_attr(feature = "typescript", ts(type = "Array<BrowserTicketState>"))]
|
||||
pub states: Vec<ticket::TicketState>,
|
||||
/// Every supplied active tag ID must match (AND).
|
||||
#[serde(default)]
|
||||
pub tag_ids: Vec<String>,
|
||||
#[cfg_attr(
|
||||
feature = "typescript",
|
||||
ts(type = "TicketAssignmentPrincipalSnapshot | null")
|
||||
)]
|
||||
pub assigned_principal: Option<ticket::TicketAssignmentPrincipalSnapshot>,
|
||||
#[cfg_attr(
|
||||
feature = "typescript",
|
||||
ts(type = "TicketAssignmentTrackingStatus | null")
|
||||
)]
|
||||
pub handling_status: Option<ticket::TicketAssignmentTrackingStatus>,
|
||||
/// Exact current closed-case reason; historical reasons do not match this filter.
|
||||
#[cfg_attr(feature = "typescript", ts(type = "TicketClosureReason | null"))]
|
||||
pub closure_reason: Option<ticket::TicketClosureReason>,
|
||||
/// Only updated_desc is supported; defaults to updated_desc.
|
||||
pub sort: Option<String>,
|
||||
#[schemars(range(min = 0, max = 1000))]
|
||||
pub limit: Option<usize>,
|
||||
/// Browse-only cursor bound to the Workspace, canonical filters, and sort.
|
||||
pub cursor: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct TicketBrowseQueryItem {
|
||||
pub id: String,
|
||||
pub resource_key: String,
|
||||
pub title: String,
|
||||
pub state: BrowserTicketState,
|
||||
pub updated_at: Option<String>,
|
||||
#[cfg_attr(feature = "typescript", ts(type = "Array<WorkspaceTag>"))]
|
||||
pub tags: Vec<ticket::WorkspaceTag>,
|
||||
#[cfg_attr(feature = "typescript", ts(type = "TicketClosureJudgment | null"))]
|
||||
pub current_closure: Option<ticket::TicketClosureJudgment>,
|
||||
#[cfg_attr(
|
||||
feature = "typescript",
|
||||
ts(type = "Array<TicketAssignmentTrackingProjection>")
|
||||
)]
|
||||
pub assignment_tracking: Vec<ticket::TicketAssignmentTrackingProjection>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct TicketBrowseQueryResponse {
|
||||
pub items: Vec<TicketBrowseQueryItem>,
|
||||
pub page: QueryPage,
|
||||
pub record_authority: String,
|
||||
}
|
||||
Reference in New Issue
Block a user