Files
quant-os/docs/SECURITY.md
T

202 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Quant OS data, credential and live-trading safety
Quant OS 仓库需要能够被 review、clone 和推送,但不能携带可复用凭据、账户
身份、受许可限制的数据或券商专有运行时。Obsidian 只保存项目说明,也不能
成为密码、cookie 或行情文件的旁路存储。
## Never commit or copy into documentation
- JoinQuant/JQData username、password、cookie、token、session export
- QMT/MiniQMT account ID、terminal profile、userdata directory、session
file、device fingerprint
- 从持牌 QMT 安装复制出的 `xtquant` binary
- broker statement、raw callback 或含账户/个人信息的截图;
- private key、API key、`.env`、subscription URL、带凭据的 clone URL
- provider licence 不允许再分发的 raw/derived market data
- Colab notebook output 中的 secret、完整账户值或授权数据;
- MLflow/Recorder artifact 中意外缓存的环境变量、machine path 或身份信息。
`.gitignore` 不是安全边界。每次提交前必须检查 staged diff 和所有 generated
artifacts。
## Credential injection
提交到 Git 的配置只能含 placeholder。推荐本地变量:
```text
JQDATA_USERNAME
JQDATA_PASSWORD
QMT_ACCOUNT_ID
QMT_USERDATA_PATH
QMT_SESSION_ID
QMT_ACCOUNT_HASH_KEY_FILE
```
JQData adapter 优先读取本地环境变量,也支持交互式读取;密码提示无回显。
不得把密码作为 CLI 参数,因为 shell history/process list 会泄漏。
Colab 可选 JQData cell 必须在 runtime 内通过无回显 prompt/Colab secret
注入。禁止:
- 把 secret 写在 notebook source 或共享链接里;
- `print(os.environ)`、输出 auth object 或异常中的 credential
- 把带 secret 的 notebook output 下载、同步或提交;
- 运行结束后继续复用包含授权数据和 secret 的共享 runtime。
用完后清除 runtime。Colab secret 只是注入渠道,不授予数据再分发权。
QMT 账号不应作为 CLI 参数。`.env.example` 只列变量名和安全默认值;
真实 `.env` 必须保留在 operator-controlled local secret store。
不得在 `--help`、exception、run manifest、test snapshot 或 OB 文档打印上述
值。低熵账户号的普通 SHA-256 可枚举恢复;对外证据应使用 keyed one-way
identifier,并把 key 保存在独立 secret store。
`QMT_ACCOUNT_HASH_KEY_FILE` 只指向本地 HMAC key,不是 key 本身。
`qmt_shadow_plan.py plan` 在文件不存在时生成至少 32 byte 的安全随机 keyUnix
要求文件 mode 0600,并且不会为了创建 key 而放宽或改写一个已经存在的父目录
权限。`verify` 只读取既有 key,绝不会在 key 丢失时静默生成替代品。该 key
必须稳定备份和最小权限访问:轮换后账户 hash 会变化,历史 broker snapshot
与 decision 会按设计失配,历史 authenticated evidence 也无法再验签。key
内容不得进入 Git、OB、notebook、artifact、stdout、异常或聊天。
shadow manifest 保存的是 `QMT_SHADOW_EVIDENCE_V1` HMAC,不是 secret。
它用与账户标识不同的 domain 签署 canonical evidence envelope,覆盖完整
plan、broker observation、broker snapshot 的内容 hash 和三份实际发布文件
原始 byte SHA-256、原始 decision manifest hash、planner/engine 以及
`tools/qmt_shadow_plan.py` operator entrypoint source hash,并绑定固定
semantic/policy ID 和阈值。四个发布 JSON(含不自签的 manifest)必须符合
唯一 deterministic writer bytesminify、key 重排和空白变化不是等价发布物。
verifier 必须同时拿到原始 decision 与既有 key,并读取磁盘实际 bytes 重建
envelope 后用
constant-time compare 验证。普通 SHA-256 重新封装、替换 decision、改写
observation 或同步修改 plan 派生字段都不能在不知道 key 时伪造该 MAC。
这个 HMAC 的信任主体是“持有本地 key 的 Quant OS evidence publisher”。
它证明发布后没有被无 key 的第三方改写;它**不是** QMT/券商对 API 返回值的
签名,不证明终端、账号或 callback 未在采集前被攻陷。key 泄漏后攻击者可以
伪造本地 envelope,应立即按 credential incident 轮换、隔离旧证据并重新做
可信采集。
## JQData and provider-data licence
`jqdatasdk==1.9.8` adapter 可获取 raw OHLCV/money、factor、pre-close、
daily limits/paused、PIT `is_st` 和历史指数成员。可获取不等于可再分发。
首次真实 snapshot 前记录:
- provider、账户 entitlement 和允许用途;
- local/Colab 是否允许持久保存、保存期限;
- raw 与 derived data 是否可共享;
- API/field semantic version
- query、retrieval time、event/effective/available time
- partition/data hash、retention 和 deletion policy。
snapshot manifest 不含密码,但 snapshot 本身仍可能是受许可数据。默认放在
被 Git 忽略的 local storage,不上传代码仓库、OB、公开 object storage 或
公开 Colab drive。
synthetic fixture 可共享但不是市场证据。真实 JQData snapshot 只有在许可、
lineage 和语义 verifier 都完成后,才可能成为 G1 的候选证据。
## QMT proprietary and licensed boundary
`xtquant` 由持牌 QMT/MiniQMT 与券商分发。Quant OS
- 不 vendoring、不上传、不从非官方 PyPI 模仿包安装;
- 仅在 QMT-specific path 内 lazy import
- 没有专有运行时也能跑核心/fake tests
- 只使用实际券商支持的 Python 和 client/plugin 组合。
QMT 并非只提供用户名密码即可运行。还需要已授权 QMT/MiniQMT client、
匹配的 `xtquant`、userdata path、行情/历史数据 entitlement 和登录会话。
复制其他用户安装不能建立许可或兼容性。
平台导出必须先脱敏:raw account、broker order ID、userdata path、device
信息和专有异常字符串不进入 Git。
只读 shadow 的 `broker_observation.json` 只保存 keyed account hash、query
安全 envelope 和通过标准化的资产、持仓、委托、成交事实;不保存原始
account ID。manifest 通过 authenticated evidence HMAC 将 observation、
broker snapshot、plan、decision、source 和 canonical policy 绑定。即便如此,
它仍可能包含敏感持仓/交易信息,只能放在被 Git 忽略且访问受控的证据目录。
## Qlib, MLflow and Colab artifacts
Qlib 固定为 CPython 3.12 + `pyqlib==0.9.7`。Alpha158 runner 为本地
MLflow file store 使用:
```text
MLFLOW_ALLOW_FILE_STORE=true
```
这是对 local backend 的显式兼容确认,不是安全授权,也不会替代访问控制。
Recorder 目录可能包含 model、label、prediction、code cache/status 和
provider-derived output;提交前必须按 provider licence 与 secret scan
检查。真实模型 artifact 应存放在访问受控、可审计的 artifact store。
不要在公开 Colab runtime 上加载券商文件。JQData/Qlib 可选流程只处理研究
数据;QMT/XtTrader 应留在受控且持牌的本地/Windows 环境。
## Default live posture
所有 broker-facing 路径默认只能是:
```text
BACKTEST
SIMULATION
SHADOW
```
QMT built-in 和 qmttools supplied runner 硬限制 backtest/history。XtTrader
`allow_live_orders` 默认 false,仓库不提供 live launch command。
未来任何 live mutation 至少还要求:
1. broker read-only preflight 成功;
2. market data 与完整 broker snapshot 新鲜且带时区;
3. account allow-list 匹配;
4. 无 unknown open order 或 reconciliation difference
5. notional/order/rate limit 已配置;
6. operator approval 与 kill switch 已演练;
7. 程序化交易报告和软件/频率要求由实际券商确认;
8. shadow、重启恢复和连续日终对账达到 release 条件。
环境变量本身不构成批准。mock guard、fake broker 和单元测试也不构成券商认证。
## Safe evidence and redaction
可安全导出的候选内容:
- source/config/data/rules/model hash
- canonical symbols 和非受限聚合;
- order state/reason code
- keyed account hash
- 在不需要精确值时脱敏/取整的 operational metric。
需要删除或保护:
- raw account 和可关联 broker order ID
- 用户 machine path、用户名、device/profile 信息;
- proprietary client exception
- notebook cell output 中的 token/credential
- provider licence 不允许公开的数据行。
审计所需原始版本应留在加密、访问受控的本地/企业存储,而不是为了方便直接
提交 Git。
## Incident response
如果 credential、账户标识或授权数据进入 Git/OB/Colab output
1. 停止新订单和相关自动任务;
2. 通过 provider/broker 撤销或轮换 credential
3. 在仓库外保存 incident timeline
4. 从当前树移除,并在明确批准后清理历史和 mirror;
5. 检查 CI、artifact、OB sync、Colab/Drive 和 downstream clone
6. 评估数据许可/个人信息泄漏范围并完成必要通知;
7. 记录恢复和复发预防。
删除可见文件不等于 credential rotation。交易与数据故障流程见
[`runbooks/INCIDENTS.md`](../runbooks/INCIDENTS.md)。