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}