bezant_server/state.rs
1//! Shared application state.
2
3use std::sync::Arc;
4
5/// State shared across all axum handlers.
6#[derive(Clone)]
7pub struct AppState {
8 inner: Arc<Inner>,
9}
10
11struct Inner {
12 client: bezant::Client,
13 /// Optional token guarding the `/debug/*` endpoints. When `None`,
14 /// debug endpoints return 404. When `Some`, callers must present a
15 /// matching token via `?token=…` query string or
16 /// `X-Bezant-Debug-Token` header.
17 debug_token: Option<String>,
18}
19
20impl AppState {
21 /// Build app state from a configured [`bezant::Client`].
22 ///
23 /// Debug endpoints are disabled by default. Use
24 /// [`AppState::with_debug_token`] to enable them with token gating.
25 #[must_use]
26 pub fn new(client: bezant::Client) -> Self {
27 Self {
28 inner: Arc::new(Inner {
29 client,
30 debug_token: None,
31 }),
32 }
33 }
34
35 /// Enable the `/debug/*` endpoints, requiring the given token on
36 /// every request (via `?token=…` or `X-Bezant-Debug-Token` header).
37 /// Without this, all `/debug/*` routes 404.
38 ///
39 /// **Security:** the cookie jar holds live IBKR session cookies
40 /// — anyone who can read it can resume the IBKR session and
41 /// trade the account. Pick a long, random token (>=32 bytes
42 /// from `/dev/urandom`) and treat it like a credential.
43 #[must_use]
44 pub fn with_debug_token(client: bezant::Client, token: impl Into<String>) -> Self {
45 Self {
46 inner: Arc::new(Inner {
47 client,
48 debug_token: Some(token.into()),
49 }),
50 }
51 }
52
53 /// Borrow the underlying Bezant client.
54 #[must_use]
55 pub fn client(&self) -> &bezant::Client {
56 &self.inner.client
57 }
58
59 /// Borrow the configured debug token, if any.
60 #[must_use]
61 pub fn debug_token(&self) -> Option<&str> {
62 self.inner.debug_token.as_deref()
63 }
64}