mini_chat_sdk/plugin_api.rs
1use async_trait::async_trait;
2use tokio_util::sync::CancellationToken;
3use uuid::Uuid;
4
5use crate::audit_models::{
6 TurnAuditEvent, TurnDeleteAuditEvent, TurnEditAuditEvent, TurnRetryAuditEvent,
7};
8use crate::error::{MiniChatAuditPluginError, MiniChatModelPolicyPluginError, PublishError};
9use crate::models::{PolicySnapshot, PolicyVersionInfo, UsageEvent, UserLicenseStatus, UserLimits};
10
11/// Plugin API trait for mini-chat model policy implementations.
12///
13/// Plugins implement this trait to provide model catalog and policy data.
14/// The mini-chat module discovers plugins via GTS types-registry and
15/// delegates policy queries to the selected plugin.
16///
17/// Every method accepts a [`CancellationToken`] so callers can abort
18/// in-flight HTTP requests on shutdown or request cancellation.
19#[async_trait]
20pub trait MiniChatModelPolicyPluginClientV1: Send + Sync {
21 /// Get the current policy version for a user.
22 async fn get_current_policy_version(
23 &self,
24 user_id: Uuid,
25 cancel: CancellationToken,
26 ) -> Result<PolicyVersionInfo, MiniChatModelPolicyPluginError>;
27
28 /// Get the full policy snapshot for a given version, including
29 /// model catalog and kill switches.
30 async fn get_policy_snapshot(
31 &self,
32 user_id: Uuid,
33 policy_version: u64,
34 cancel: CancellationToken,
35 ) -> Result<PolicySnapshot, MiniChatModelPolicyPluginError>;
36
37 /// Get per-user credit limits for a specific policy version.
38 async fn get_user_limits(
39 &self,
40 user_id: Uuid,
41 policy_version: u64,
42 cancel: CancellationToken,
43 ) -> Result<UserLimits, MiniChatModelPolicyPluginError>;
44
45 /// Check whether a user holds an active `CyberChat` license in the caller's tenant.
46 ///
47 /// Returns `active: true` when the user's status is `active`.
48 /// Returns `active: false` for any other status (`invited`, `deactivated`,
49 /// `deleted`) or when the user is not found — this is not an error condition.
50 ///
51 /// The default implementation returns `active: false` so that existing
52 /// out-of-tree V1 plugins remain compatible without code changes.
53 async fn check_user_license(
54 &self,
55 _user_id: Uuid,
56 _cancel: CancellationToken,
57 ) -> Result<UserLicenseStatus, MiniChatModelPolicyPluginError> {
58 Ok(UserLicenseStatus { active: false })
59 }
60
61 /// Publish a usage event after turn finalization.
62 ///
63 /// Called by the outbox processor after the finalization transaction
64 /// commits. Plugins can forward the event to external billing systems.
65 async fn publish_usage(
66 &self,
67 payload: UsageEvent,
68 cancel: CancellationToken,
69 ) -> Result<(), PublishError>;
70}
71
72/// Plugin API trait for mini-chat audit event publishing.
73///
74/// Plugins implement this trait to receive audit events from the mini-chat
75/// module. The mini-chat module discovers plugins via GTS types-registry and
76/// dispatches audit events to all registered implementations.
77///
78/// # Caller contract
79///
80/// The **caller** (mini-chat domain service) MUST redact secret patterns and
81/// truncate string content (max 8 KiB per field) *before* invoking any method
82/// on this trait. Plugins MUST assume all content fields are already sanitized.
83/// See DESIGN.md "Audit content handling (P1)" for the full redaction rule table.
84///
85/// # Delivery semantics
86///
87/// Audit emission is best-effort (fire-and-forget after DB commit). There is no
88/// transactional outbox for audit events. If the process crashes between DB
89/// commit and audit emission, the event is lost. Callers SHOULD track emission
90/// outcomes via `mini_chat_audit_emit_total{result}` metrics.
91///
92/// # Independence
93///
94/// When multiple audit plugin instances are registered, each MUST be
95/// independent. A failure in one plugin MUST NOT prevent delivery to others.
96#[async_trait]
97pub trait MiniChatAuditPluginClientV1: Send + Sync {
98 /// Emit a turn audit event (turn completed or failed).
99 async fn emit_turn_audit(&self, event: TurnAuditEvent) -> Result<(), MiniChatAuditPluginError>;
100
101 /// Emit a turn-retry audit event.
102 async fn emit_turn_retry_audit(
103 &self,
104 event: TurnRetryAuditEvent,
105 ) -> Result<(), MiniChatAuditPluginError>;
106
107 /// Emit a turn-edit audit event.
108 async fn emit_turn_edit_audit(
109 &self,
110 event: TurnEditAuditEvent,
111 ) -> Result<(), MiniChatAuditPluginError>;
112
113 /// Emit a turn-delete audit event.
114 async fn emit_turn_delete_audit(
115 &self,
116 event: TurnDeleteAuditEvent,
117 ) -> Result<(), MiniChatAuditPluginError>;
118}