Skip to main content

futu_auth/
lib.rs

1//! FutuOpenD-rs 授权子系统
2//!
3//! 提供 API Key + Scope + 限额 三层鉴权:
4//! - [`scope`] — 能力分组枚举
5//! - [`key`] — 单条 key 记录 + SHA-256 校验
6//! - [`store`] — keys.json 加载 / 原子热替换 / 明文验证
7//! - [`limits`] — 日累计 / 单笔上限 / 市场 / 品种白名单 / 时间窗口
8
9pub mod audit;
10pub mod key;
11pub mod limits;
12pub mod machine;
13pub mod metrics;
14pub mod scope;
15pub mod secret_store;
16pub mod store;
17pub mod websocket;
18
19/// OS keychain 里存交易密码用的 service 名 —— futu-mcp 和 futucli 双边读写同一
20/// keychain 条目,常量放这里单源
21pub const KEYRING_SERVICE: &str = "futu-opend-rs";
22/// OS keychain 里存交易密码的 legacy username,与 [`KEYRING_SERVICE`] 配对。
23///
24/// v1.4.109 前 `futucli set-trade-pwd` 把所有登录账号共用写到这一条,导致
25/// 多账号用户后写覆盖先写。新代码只把它作为向后兼容读取兜底,不再作为
26/// `set-trade-pwd --account` 的写入目标。
27pub const KEYRING_USERNAME_TRADE_PWD: &str = "trade-password";
28/// 交易密码的账号级 keychain username 前缀。完整 username 是
29/// `trade-password.<login-account>`,与登录密码的账号级隔离模型一致。
30pub const KEYRING_USERNAME_TRADE_PWD_PREFIX: &str = "trade-password.";
31
32/// 登录密码的 keychain username 前缀(v1.4.18+)。一个账号一条独立条目,
33/// 完整 username 是 `login-password.<account>`,避免多账号互相覆盖。
34pub const KEYRING_USERNAME_LOGIN_PWD_PREFIX: &str = "login-password.";
35
36/// 计算某账号对应的交易密码 keychain username。
37pub fn keyring_username_for_trade_pwd(account: &str) -> String {
38    format!("{KEYRING_USERNAME_TRADE_PWD_PREFIX}{account}")
39}
40
41/// 计算某账号对应的登录密码 keychain username。
42pub fn keyring_username_for_login_pwd(account: &str) -> String {
43    format!("{KEYRING_USERNAME_LOGIN_PWD_PREFIX}{account}")
44}
45
46#[cfg(test)]
47mod tests;
48
49pub use key::{KeyRecord, hash_plaintext};
50pub use limits::{
51    CheckCtx, LimitGuard, LimitOutcome, LimitPolicy, Limits, RuntimeCounters, ValueRejectReason,
52    market_to_currency, validate_order_value,
53};
54pub use machine::{MachineError, fingerprint_for, fingerprint_from_raw, raw_machine_id};
55pub use metrics::Registry as MetricsRegistry;
56pub use scope::{
57    COVERAGE_EXCEPTIONS, CoverageException, EXPLICIT_NO_BODY_AWARE_PROTOS, SCOPED_ACC_READ_PROTOS,
58    SCOPED_TRADE_REAL_PROTOS, SCOPED_TRADE_UNLOCK_PROTOS, Scope, ScopeParseError,
59    is_internal_proto_id, scope_for_proto_id, trade_scope_for_env_is_real,
60};
61pub use store::{KeyStore, KeyStoreError};