1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//! Machine Payments Protocol (MPP / Tempo) integration for polychrome.
//!
//! This is the polychrome-specific composition layer: the control-plane
//! payment proxy chokepoint, the wallet self-service view renderers, and the
//! env-driven [`config`] that assembles the standalone `polyc-*` payment
//! primitive crates into the shape polychrome's control plane needs (see
//! issue #717's crate map). It stays `publish = false` — a third party
//! building their own agent depends on the primitive crates directly instead:
//!
//! - **Outbound** 402-gated payment client (`TempoProvider`-backed, pays a
//! `PAYMENT-REQUIRED` challenge via the MPP `PaymentMiddleware`/`PaymentExt`
//! path, plus the per-call spend-cap wrapper, chain-id pinning guard,
//! settlement-token balance reads, and verified explorer-link resolution) now
//! lives in the standalone `polyc-payments-client` crate; [`PaymentsConfig`](config::PaymentsConfig)
//! composes its `OutboundConfig` from its own broader configuration and
//! delegates to it ([`PaymentsConfig::resolve_client`](config::PaymentsConfig::resolve_client),
//! [`PaymentsConfig::resolve_outbound_client`](config::PaymentsConfig::resolve_outbound_client)).
//! - **Inbound**: 402 challenge issuance and credential verification lives in
//! the standalone `polyc-payments-server` crate. This deployment mounts no
//! inbound gate, so this crate composes nothing for it. A consumer that
//! wants the inbound server depends on `polyc-payments-server` directly.
//!
//! The control-plane payment proxy ([`proxy`]) gates every paid fetch
//! (approval binding, SSRF, spend cap, budget) and renders the caller-facing
//! wallet self-service views ([`view`]); `polyc_wallet_delegation::provision`
//! mints and provisions a delegated key when a caller links a wallet.
//! Configuration for all of this is loaded from the environment via
//! [`config`].
//!
//! The full non-custodial Tempo wallet-delegation lifecycle — `keys.toml`
//! parsing, TIP-1053 witness binding, scoped-key provisioning, and secret
//! custody — lives in the standalone `polyc-wallet-delegation` crate; this
//! crate composes it into polychrome's own control-plane proxy and wallet
//! self-service views.
//!
//! The default network is Tempo's Moderato testnet
//! ([`MODERATO_RPC_URL`], chain id [`MODERATO_CHAIN_ID`]).
/// Settlement-amount units: dollars ↔ base units + reader-facing rendering.
/// Configuration loaded from the environment for both payment directions.
/// Control-plane payment proxy core (approval-bind + SSRF + budget + fetch).
/// Pure wallet self-service views (state machine + tool-result renderings).
/// Force-register this crate's Prometheus settlement-amount counter.
///
/// Makes `polychrome_settlement_amount_unreadable_total` appear in a
/// `/metrics` scrape — with every bounded `direction` × `reason` child
/// zero-valued — before any receipt has failed to read, so an unread amount
/// shows up as a rate on an existing series rather than a series appearing
/// from nowhere. Idempotent (backed by a `OnceLock`); call once at process
/// startup, alongside any other crate's own `init_metrics`.
/// Chain id of the Tempo Moderato testnet.
///
/// Used to build the inbound server challenge; outbound validates the chain id
/// from the challenge rather than asserting this value.
pub const MODERATO_CHAIN_ID: u64 = 42431;
/// Default JSON-RPC endpoint for the Tempo Moderato testnet.
pub const MODERATO_RPC_URL: &str = "https://rpc.moderato.tempo.xyz";
/// Default block-explorer base for the Tempo Moderato testnet.
///
/// The mainnet `explore.tempo.xyz` host does NOT index testnet transactions or
/// addresses, so any payer/settlement link must default to this testnet host.
/// The single source both the inbound config default and the harness payer link
/// resolve from.
pub const MODERATO_EXPLORER_URL: &str = "https://explore.testnet.tempo.xyz";
/// Returns the default RPC endpoint used when no override is configured.
pub const
/// Hard ceiling on how long a caller-delegated access key may stay valid, in
/// seconds (seven days).
///
/// Polychrome is **non-custodial**: a linked wallet's funds stay in the caller's
/// own onchain wallet, and the control plane holds only a short-lived, spend-
/// and call-scoped *delegation* the caller authorized from their passkey — never
/// a balance. This ceiling is what keeps that delegation from becoming
/// open-ended: every minted authorization expires at or before `now + this`, so
/// authority the caller granted lapses on its own and must be re-authorized by a
/// fresh passkey approval (re-link). Minting clamps to this bound and the
/// passkey can only sign an expiry at or under the minted one, so no
/// configuration or client can hold spend authority indefinitely.
pub const MAX_DELEGATION_LIFETIME_SECS: u64 = 7 * 86_400;