fts_core/ports/
auth.rs

1use crate::{
2    models::{
3        AuctionOutcome, AuthData, AuthHistoryRecord, AuthId, AuthRecord, BidderId,
4        DateTimeRangeQuery, DateTimeRangeResponse, ProductId,
5    },
6    ports::ProductRepository,
7};
8use serde::Serialize;
9use serde::de::DeserializeOwned;
10use std::{borrow::Borrow, future::Future};
11use time::OffsetDateTime;
12
13/// AuthRepository methods are expected to enforce various restrictions on user access.
14/// In particular, if a client-generated ID conflicts with one already present in the system,
15/// an error must be returned. If a bidder tries to obtain information on a different bidder's
16/// auth, this action must fail.
17#[derive(Debug)]
18pub enum AuthFailure {
19    /// Returned when a bidder attempts to access or modify an auth they don't have permission for
20    AccessDenied,
21    /// Returned when the requested authorization does not exist in the system
22    DoesNotExist,
23    /// Returned when attempting to create an auth with an ID that already exists
24    IdConflict,
25}
26
27/// Repository for managing authorization records and related operations.
28///
29/// In the flow trading system, an *auth* (short for authorization) represents:
30/// 1. A *portfolio*, which is a weighted bundle of products.
31/// 2. Constraints on how this portfolio can be traded.
32///
33/// Portfolios define what combination of products an auth trades, with weights determining
34/// the relative proportions. Positive weights indicate buying the product, negative weights
35/// indicate selling.
36///
37/// Auth constraints include:
38/// - Rate constraints (min_rate, max_rate) which limit how fast a portfolio can be traded
39/// - Trade constraints (min_trade, max_trade) which limit the total accumulated trade
40///
41/// This trait extends ProductRepository to provide functionality for creating,
42/// reading, updating, and deleting authorization records, as well as querying
43/// authorizations by product and retrieving historical records and auction outcomes.
44pub trait AuthRepository: ProductRepository {
45    /// Implementations may elect to display (or not) the porfolio in various
46    /// ways. At a minimum, this should be a bool on whether or not to include
47    /// the portfolio in a response; in a forward market application with
48    /// increasingly granular products, this might be an option to display the
49    /// original portfolio or the "effective" portfolio.
50    type PortfolioOptions: Default + Serialize + DeserializeOwned + Send;
51
52    /// Create a new authorization associated to the given bidder.
53    ///
54    /// If `auth_id` is None, assigns a system-generated ID.
55    fn create<K: Borrow<ProductId>, V: Borrow<f64>, P: Borrow<(K, V)>>(
56        &self,
57        bidder_id: BidderId,
58        auth_id: Option<AuthId>,
59        portfolio: impl Iterator<Item = P> + Send,
60        data: AuthData,
61        timestamp: OffsetDateTime,
62        portfolio_options: Self::PortfolioOptions,
63    ) -> impl Future<Output = Result<Result<AuthRecord, AuthFailure>, Self::Error>> + Send;
64
65    /// Retrieves the authorization record for the specified bidder and auth ID
66    /// as of the given timestamp.
67    ///
68    /// Returns the authorization record if successful, or an AuthFailure if
69    /// the auth does not exist or the bidder lacks access permission.
70    fn read(
71        &self,
72        bidder_id: BidderId,
73        auth_id: AuthId,
74        as_of: OffsetDateTime,
75        portfolio_options: Self::PortfolioOptions,
76    ) -> impl Future<Output = Result<Result<AuthRecord, AuthFailure>, Self::Error>> + Send;
77
78    /// Updates the data associated with an existing authorization.
79    ///
80    /// Returns the updated authorization record if successful, or an AuthFailure if
81    /// the auth does not exist or the bidder lacks update permission.
82    fn update(
83        &self,
84        bidder_id: BidderId,
85        auth_id: AuthId,
86        data: AuthData,
87        timestamp: OffsetDateTime,
88        portfolio_options: Self::PortfolioOptions,
89    ) -> impl Future<Output = Result<Result<AuthRecord, AuthFailure>, Self::Error>> + Send;
90
91    /// Marks the authorization as deleted / inactive. (This is a logical designation, not an actual removal.)
92    ///
93    /// Returns the deleted authorization record if successful, or an AuthFailure if
94    /// the auth does not exist or the bidder lacks delete permission.
95    fn delete(
96        &self,
97        bidder_id: BidderId,
98        auth_id: AuthId,
99        timestamp: OffsetDateTime,
100        portfolio_options: Self::PortfolioOptions,
101    ) -> impl Future<Output = Result<Result<AuthRecord, AuthFailure>, Self::Error>> + Send;
102
103    /// Retrieves all active authorizations that involve the specified product as of
104    /// the given timestamp for the specified bidder.
105    ///
106    /// Returns a vector of matching authorization records.
107    fn query_by_product(
108        &self,
109        bidder_id: BidderId,
110        product_id: ProductId,
111        as_of: OffsetDateTime,
112    ) -> impl Future<Output = Result<Vec<AuthRecord>, Self::Error>> + Send;
113
114    /// Retrieves the historical records for a specific authorization within the
115    /// given time range.
116    ///
117    /// The `limit` parameter restricts the maximum number of records returned.
118    /// Returns a paginated response of auth history records if successful, or an AuthFailure if
119    /// the auth does not exist or the bidder lacks access permission.
120    fn get_history(
121        &self,
122        bidder_id: BidderId,
123        auth_id: AuthId,
124        query: DateTimeRangeQuery,
125        limit: usize,
126    ) -> impl Future<
127        Output = Result<Result<DateTimeRangeResponse<AuthHistoryRecord>, AuthFailure>, Self::Error>,
128    > + Send;
129
130    /// Retrieves the auction outcomes associated with a specific authorization
131    /// within the given time range.
132    ///
133    /// The `limit` parameter restricts the maximum number of outcomes returned.
134    /// Returns a paginated response of auction outcomes if successful, or an AuthFailure if
135    /// the auth does not exist or the bidder lacks access permission.
136    fn get_outcomes(
137        &self,
138        bidder_id: BidderId,
139        auth_id: AuthId,
140        query: DateTimeRangeQuery,
141        limit: usize,
142    ) -> impl Future<
143        Output = Result<Result<DateTimeRangeResponse<AuctionOutcome>, AuthFailure>, Self::Error>,
144    > + Send;
145}