chio_api_protect/proxy/config.rs
1use super::*;
2use std::time::Duration;
3
4/// Default wall-clock ceiling on a single upstream proxy hop, including reading
5/// the full response body. Kept below the serve site's drain window so an
6/// in-flight hop is resolved and receipted before a shutdown force-closes the
7/// connection.
8pub const DEFAULT_UPSTREAM_REQUEST_TIMEOUT: Duration = Duration::from_secs(20);
9
10/// Configuration for the protect proxy.
11pub struct ProtectConfig {
12 /// Upstream URL to proxy to.
13 pub upstream: String,
14 /// Optional in-memory OpenAPI spec content (YAML or JSON).
15 pub spec_content: Option<String>,
16 /// Optional OpenAPI spec path. When omitted, the proxy auto-discovers the spec.
17 pub spec_path: Option<String>,
18 /// Address to listen on (e.g., "127.0.0.1:9090").
19 pub listen_addr: String,
20 /// Optional SQLite path for receipt persistence.
21 pub receipt_db: Option<String>,
22 /// Explicit opt-in to run without a durable receipt store. A durable audit
23 /// log is the product's core promise, so a `None` `receipt_db` is refused at
24 /// startup unless this is set, mirroring the CLI boot gate. When set, the
25 /// proxy runs with in-memory receipts and revocations that are lost on every
26 /// restart. Leave it `false` for durable-by-default embedding.
27 pub allow_ephemeral_receipts: bool,
28 /// Optional bearer token that authorizes remote sidecar control requests.
29 pub sidecar_control_token: Option<String>,
30 /// Optional seed used to keep the sidecar signer stable across restarts.
31 pub signer_seed_hex: Option<String>,
32 /// Explicit capability issuers trusted by the HTTP authority.
33 pub trusted_capability_issuers: Vec<PublicKey>,
34 /// Control-plane URL. When set, budget holds go through a `RemoteBudgetStore`.
35 pub control_url: Option<String>,
36 /// Bearer token for the control-plane budget endpoints.
37 pub control_token: Option<String>,
38 /// Local SQLite budget-store path used when no `control_url` is configured.
39 pub budget_db: Option<String>,
40 /// Optional durable SQLite revocation-store path. When set, the sidecar
41 /// loads its revoked capability ids at startup so operator revocations
42 /// recorded through `chio trust revoke --revocation-db <path>` are enforced
43 /// on `/v1/evaluate` and every other path that consults the revoked set.
44 /// Opening or reading a configured store that fails is fatal (fail-closed):
45 /// the sidecar refuses to start rather than run without the revocations it
46 /// was told to enforce.
47 pub revocation_db: Option<String>,
48 /// Retained for API compatibility. The kernel-mediated `/v1/evaluate`
49 /// route is a pre-execution authorization gate and always runs the
50 /// mediation kernel in execution-nonce strict mode, so this flag no
51 /// longer changes mediation behavior.
52 pub require_nonce: bool,
53 /// When true, the `/v1/evaluate/advisory` route is active.
54 /// Defaults to false; production deployments should leave this off to
55 /// prevent agents from receiving advisory receipts and bypassing the
56 /// kernel-mediated route.
57 pub allow_advisory: bool,
58 /// Wall-clock ceiling on a single upstream proxy hop, including reading the
59 /// full response body. Raise it for upstreams with legitimately slow calls or
60 /// large bounded responses; the serve site widens its drain window to match so
61 /// an in-flight hop is still receipted before shutdown force-closes it.
62 /// Defaults to [`DEFAULT_UPSTREAM_REQUEST_TIMEOUT`].
63 pub upstream_request_timeout: Duration,
64}
65
66impl std::fmt::Debug for ProtectConfig {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 f.debug_struct("ProtectConfig")
69 .field("upstream", &self.upstream)
70 .field(
71 "spec_content",
72 &self.spec_content.as_ref().map(|_| "<inline>"),
73 )
74 .field("spec_path", &self.spec_path)
75 .field("listen_addr", &self.listen_addr)
76 .field("receipt_db", &self.receipt_db)
77 .field("allow_ephemeral_receipts", &self.allow_ephemeral_receipts)
78 .field(
79 "sidecar_control_token",
80 &self.sidecar_control_token.as_ref().map(|_| "<redacted>"),
81 )
82 .field(
83 "signer_seed_hex",
84 &self.signer_seed_hex.as_ref().map(|_| "<redacted>"),
85 )
86 .field(
87 "trusted_capability_issuers",
88 &self.trusted_capability_issuers,
89 )
90 .field("control_url", &self.control_url)
91 .field("budget_db", &self.budget_db)
92 .field("revocation_db", &self.revocation_db)
93 .field("require_nonce", &self.require_nonce)
94 .field("allow_advisory", &self.allow_advisory)
95 .field("upstream_request_timeout", &self.upstream_request_timeout)
96 .finish()
97 }
98}