Skip to main content

backbone_support/application/service/
support_ports.rs

1//! Support's one outbound port (hand-authored, user-owned) โ€” the optional seam where a ticket becomes
2//! delivery work. Support holds only this trait + its own DTOs; a composing service wires the real
3//! backbone-project behind it. **Zero normal Cargo edge** to project โ€” the two Tier-4 modules stay
4//! independent (brief ยง7), and the DTOs are the wire contract, duplicated per consumer by design.
5//! Support posts no GL and has no ledger seam; escalation just spawns a delivery Project.
6
7use serde::{Deserialize, Serialize};
8use uuid::Uuid;
9
10/// Escalate a support ticket into a delivery project (open a backbone-project Project for the customer).
11///
12/// `company_id` is the legacy tenancy echo (ADR-0029): the ambient org scope's company when the
13/// composing service bound one, nil otherwise. Support neither stores nor fences on it, and
14/// backbone-project needs none.
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
16pub struct ProjectFromIssue {
17    pub company_id: Uuid,
18    pub issue_id: Uuid,
19    pub customer_id: Uuid,
20    pub subject: String,
21}
22
23/// The spawned delivery project's id.
24#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
25pub struct ProjectAck {
26    pub project_id: Uuid,
27}
28
29/// The project seam โ€” a composing service implements it over backbone-project.
30#[async_trait::async_trait]
31pub trait ProjectPort: Send + Sync {
32    async fn open_delivery_project(
33        &self,
34        req: &ProjectFromIssue,
35    ) -> Result<ProjectAck, SupportRejected>;
36}
37
38/// A downstream rejection surfaced to support.
39#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
40pub struct SupportRejected {
41    pub code: String,
42    pub message: String,
43}