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 store;
16
17/// OS keychain 里存交易密码用的 service 名 —— futu-mcp 和 futucli 双边读写同一
18/// keychain 条目,常量放这里单源
19pub const KEYRING_SERVICE: &str = "futu-opend-rs";
20/// OS keychain 里存交易密码的 legacy username,与 [`KEYRING_SERVICE`] 配对。
21///
22/// v1.4.109 前 `futucli set-trade-pwd` 把所有登录账号共用写到这一条,导致
23/// 多账号用户后写覆盖先写。新代码只把它作为向后兼容读取兜底,不再作为
24/// `set-trade-pwd --account` 的写入目标。
25pub const KEYRING_USERNAME_TRADE_PWD: &str = "trade-password";
26/// 交易密码的账号级 keychain username 前缀。完整 username 是
27/// `trade-password.<login-account>`,与登录密码的账号级隔离模型一致。
28pub const KEYRING_USERNAME_TRADE_PWD_PREFIX: &str = "trade-password.";
29
30/// 登录密码的 keychain username 前缀(v1.4.18+)。一个账号一条独立条目,
31/// 完整 username 是 `login-password.<account>`,避免多账号互相覆盖。
32pub const KEYRING_USERNAME_LOGIN_PWD_PREFIX: &str = "login-password.";
33
34/// 计算某账号对应的交易密码 keychain username。
35pub fn keyring_username_for_trade_pwd(account: &str) -> String {
36    format!("{KEYRING_USERNAME_TRADE_PWD_PREFIX}{account}")
37}
38
39/// 计算某账号对应的登录密码 keychain username。
40pub fn keyring_username_for_login_pwd(account: &str) -> String {
41    format!("{KEYRING_USERNAME_LOGIN_PWD_PREFIX}{account}")
42}
43
44#[cfg(test)]
45mod tests;
46
47pub use key::{KeyRecord, hash_plaintext};
48pub use limits::{
49    CheckCtx, LimitGuard, LimitOutcome, Limits, RuntimeCounters, ValueRejectReason,
50    market_to_currency, validate_order_value,
51};
52pub use machine::{MachineError, fingerprint_for, fingerprint_from_raw, raw_machine_id};
53pub use metrics::Registry as MetricsRegistry;
54pub use scope::{
55    COVERAGE_EXCEPTIONS, CoverageException, EXPLICIT_NO_BODY_AWARE_PROTOS, SCOPED_ACC_READ_PROTOS,
56    SCOPED_TRADE_REAL_PROTOS, SCOPED_TRADE_UNLOCK_PROTOS, Scope, ScopeParseError,
57    is_internal_proto_id, scope_for_proto_id,
58};
59pub use store::{KeyStore, KeyStoreError};