feat: expose read-only notification routing and delivery diagnostics
This commit is contained in:
@@ -7,6 +7,8 @@ pub use api_macros::axum as server_support;
|
||||
pub use api_macros::reqwest as client_support;
|
||||
pub use api_macros::{ApiContract, BinaryBody, HttpMethod, TransportMetadata, WebSocketOperation};
|
||||
mod drive;
|
||||
mod notification;
|
||||
pub use notification::*;
|
||||
pub mod repository_openapi_typescript;
|
||||
pub use drive::*;
|
||||
mod workspace_config;
|
||||
@@ -366,6 +368,8 @@ impl_openapi_schema!(
|
||||
TicketAssignmentsPage,
|
||||
TicketAssignmentAnswerRequest,
|
||||
TicketAssignmentAnswerResponse,
|
||||
NotificationDiagnosticsQuery,
|
||||
NotificationDiagnosticsPage,
|
||||
TicketAssignmentDiagnosticsQuery,
|
||||
TicketAssignmentDiagnosticsPage,
|
||||
TicketQueryRequest,
|
||||
@@ -3241,6 +3245,14 @@ pub trait ServerApi {
|
||||
#[query] query: TicketAssignmentsQuery,
|
||||
) -> Result<TicketAssignmentsPage, RepositoryApiError>;
|
||||
|
||||
#[get("/api/w/{workspace_id}/notification-diagnostics", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500], bearer_auth = true, browser_auth = true)]
|
||||
async fn notification_diagnostics(
|
||||
&self,
|
||||
#[extension] context: ServerRequestContext,
|
||||
#[path] workspace_id: String,
|
||||
#[query] query: NotificationDiagnosticsQuery,
|
||||
) -> Result<NotificationDiagnosticsPage, RepositoryApiError>;
|
||||
|
||||
#[get("/workspaces/{workspace_id}/tickets/{ticket_id}/assignment-diagnostics", status = 200, error_status = 400, additional_error_statuses = [401, 403, 404, 500], bearer_auth = true, browser_auth = true)]
|
||||
async fn ticket_assignment_diagnostics(
|
||||
&self,
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
//! Read-only notification evidence. Acceptance is not model processing or execution authority.
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NotificationDiagnosticsQuery {
|
||||
pub ticket: Option<String>,
|
||||
pub merge_request_id: Option<String>,
|
||||
pub job_id: Option<String>,
|
||||
pub source_event_id: Option<String>,
|
||||
pub assignment_id: Option<String>,
|
||||
pub delivery_id: Option<String>,
|
||||
/// Exact source identity for a single-record lookup.
|
||||
pub source_id: Option<String>,
|
||||
pub cursor: Option<String>,
|
||||
pub limit: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum NotificationDiagnosticStage {
|
||||
Historical,
|
||||
AwaitingRouting,
|
||||
Suppressed,
|
||||
Deferred,
|
||||
Pending,
|
||||
Reserved,
|
||||
RequestPersisted,
|
||||
RuntimeRejected,
|
||||
AcceptanceUnknown,
|
||||
DeliveryFailed,
|
||||
RuntimeAccepted,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NotificationDiagnostic {
|
||||
pub source_id: String,
|
||||
pub source_event_id: String,
|
||||
pub event_kind: String,
|
||||
pub ticket: Option<String>,
|
||||
pub merge_request_id: Option<String>,
|
||||
pub job_id: Option<String>,
|
||||
pub recipient_role: String,
|
||||
pub assignment_id: Option<String>,
|
||||
/// Current assignment identity only; null for fixed-worker or absent recipients.
|
||||
pub recipient_current: Option<bool>,
|
||||
pub disposition: Option<String>,
|
||||
pub reason: Option<String>,
|
||||
pub purpose: Option<String>,
|
||||
pub delivery_id: Option<String>,
|
||||
pub stage: NotificationDiagnosticStage,
|
||||
pub target_runtime_id: Option<String>,
|
||||
pub target_worker_id: Option<String>,
|
||||
pub last_failure_code: Option<String>,
|
||||
pub last_failure_at: Option<String>,
|
||||
/// Saved delivery candidate, NOT permission to send. Live recipient and binding checks remain required.
|
||||
pub retry_candidate: bool,
|
||||
/// No model-processing evidence is currently collected by this read contract.
|
||||
pub model_processing_confirmed: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NotificationSourceCheck {
|
||||
pub resource_kind: String,
|
||||
pub reference: String,
|
||||
/// Whether an exact durable origin is present; null means that reference form was not verified.
|
||||
pub origin_present: Option<bool>,
|
||||
/// Whether the origin has any captured source (independent of pagination/recipient filters).
|
||||
/// A present origin with false here is unconnected, not intentionally suppressed.
|
||||
pub captured: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct NotificationDiagnosticsPage {
|
||||
pub items: Vec<NotificationDiagnostic>,
|
||||
pub next_cursor: Option<String>,
|
||||
pub source_checks: Vec<NotificationSourceCheck>,
|
||||
}
|
||||
@@ -536,6 +536,13 @@ fn validate_ticket_browser_operations(
|
||||
request: None,
|
||||
successes: &[("200", "TicketAssignmentsPage")],
|
||||
},
|
||||
OperationContract {
|
||||
path: "/api/w/{workspace_id}/notification-diagnostics",
|
||||
method: "get",
|
||||
operation_id: "notification_diagnostics",
|
||||
request: None,
|
||||
successes: &[("200", "NotificationDiagnosticsPage")],
|
||||
},
|
||||
OperationContract {
|
||||
path: "/workspaces/{workspace_id}/tickets/{ticket_id}/assignment-diagnostics",
|
||||
method: "get",
|
||||
|
||||
Reference in New Issue
Block a user