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. This is should be a logical delete rather than
92    /// a physical removal from the repository.
93    ///
94    /// Returns the deleted authorization record if successful, or an AuthFailure if
95    /// the auth does not exist or the bidder lacks delete permission.
96    fn delete(
97        &self,
98        bidder_id: BidderId,
99        auth_id: AuthId,
100        timestamp: OffsetDateTime,
101        portfolio_options: Self::PortfolioOptions,
102    ) -> impl Future<Output = Result<Result<AuthRecord, AuthFailure>, Self::Error>> + Send;
103
104    /// Retrieves all active authorizations that involve the specified product as of
105    /// the given timestamp for the specified bidder.
106    ///
107    /// Returns a vector of matching authorization records.
108    fn query_by_product(
109        &self,
110        bidder_id: BidderId,
111        product_id: ProductId,
112        as_of: OffsetDateTime,
113    ) -> impl Future<Output = Result<Vec<AuthRecord>, Self::Error>> + Send;
114
115    /// Retrieves the historical records for a specific authorization within the
116    /// given time range.
117    ///
118    /// The `limit` parameter restricts the maximum number of records returned.
119    /// Returns a paginated response of auth history records if successful, or an AuthFailure if
120    /// the auth does not exist or the bidder lacks access permission.
121    fn get_history(
122        &self,
123        bidder_id: BidderId,
124        auth_id: AuthId,
125        query: DateTimeRangeQuery,
126        limit: usize,
127    ) -> impl Future<
128        Output = Result<Result<DateTimeRangeResponse<AuthHistoryRecord>, AuthFailure>, Self::Error>,
129    > + Send;
130
131    /// Retrieves the auction outcomes associated with a specific authorization
132    /// within the given time range.
133    ///
134    /// The `limit` parameter restricts the maximum number of outcomes returned.
135    /// Returns a paginated response of auction outcomes if successful, or an AuthFailure if
136    /// the auth does not exist or the bidder lacks access permission.
137    fn get_outcomes(
138        &self,
139        bidder_id: BidderId,
140        auth_id: AuthId,
141        query: DateTimeRangeQuery,
142        limit: usize,
143    ) -> impl Future<
144        Output = Result<
145            Result<DateTimeRangeResponse<AuctionOutcome<()>>, AuthFailure>,
146            Self::Error,
147        >,
148    > + Send;
149}