hft-mm-engine 工程文档
本项目的目标是构建最终用于真实资金交易、面向生产部署的低延迟、高可靠、可审计 HFT/MM 交易引擎。
当前仓库包含工程治理、架构文档、文档部署工具和空 Rust workspace,尚无行情、订单、风控或交易能力,不可投入真实资金,也没有 production-ready(生产就绪)声明。
阅读入口
- 从架构了解已经决定的原则和目标依赖方向。
- 从逻辑模块契约了解状态所有权、失败语义和受控交易路径。
- 从路线图了解验证门禁和当前阶段。
- 从工程工作流了解 Issue、worktree、PR、审查和 QA 流程。
- 从文档治理政策了解文档更新、人工审阅和 ship 前扫描规则。
- 从文档站运行手册了解本地构建、Cloudflare 发布状态和访问边界。
人工审阅与讨论
- 查看 Pull Requests:逐行审查当前变更、提交 suggestion 并执行 ship 门禁。
- 进入文档讨论:讨论跨 PR、跨版本的长期问题。
- 每页顶部的 GitHub 图标可返回私有仓库;“Suggest an edit”可基于权威 Markdown 提议修改。
Discussion 不是权威文档。任何被采纳的结论都必须通过 Issue 和 PR 回写文档,完成审查与验证后才生效。
架构
状态:规划
最后复核:2026-08-15
长期讨论:GitHub Discussions
当前仓库状态
本仓库当前是一个空的 Rust 2024 workspace,尚不存在 domain、engine、adapter、runtime、application、状态机或交易能力。
目标系统最终面向生产部署和真实资金交易;这是 target state(目标状态),不是对当前成熟度的声明。
已决定的原则
- 从单进程模块化单体(modular monolith)开始。
- 先构建市场数据,且只通过已经验证的垂直切片增加能力。
- 正确性、确定性和资金安全优先于延迟优化;状态未知、陈旧、无效或不完整时必须 fail-closed(失败关闭)。
- 将确定性行为表达为
event in -> state/effect out,使相同输入可以重放。 - 价格和数量使用整数 tick 与 lot 表示。
- 每个热路径当前状态只分配一个写入者;I/O、持久化、日志、Dashboard 和其他冷路径工作移出热路径。
- 所有订单意图在进入 Trading Adapter 前必须经过独立 pre-trade risk(盘前风控);风控不可用时禁止放行。
- 订单、成交、持仓与余额转换必须可审计,并支持从权威事件或快照恢复/重建。
- 本地状态必须能与交易所订单、成交、持仓和余额对账;优先使用 drop-copy 或等价的独立执行回报来源。
- 可观测性不得阻塞热路径,但必须支持故障定位、恢复验证和审计追踪。
- 延迟必须端到端测量并基于明确预算验收;当前没有延迟保证。
- venue 传输 DTO 保持在 domain 之外;Adapter 在明确边界转换外部表示。
- 只有两个真实 Adapter 证明存在替换 Seam 后,才引入 trait。
- 不允许策略逻辑发送网络请求,也不允许把 MARKET order 用作回退。
术语:
- Module(模块): 内聚的行为及其拥有的状态。
- Interface(接口): Module 的狭窄公开契约。
- Seam(接缝): 可以替换实现的有意边界。
- Adapter(适配器): 外部系统与 Seam 之间的转换。
规划中的依赖方向
目标方向为:
domain <- engine <- adapters/runtime <- apps
这是对未来代码的约束,不代表这些模块或目录已经存在。domain 代码预计包含单位、身份、不变量、事件、确定性状态转换和 effect,但不依赖 venue DTO、网络、数据库、异步 runtime、系统时钟、环境变量或可观测性投递。
这些生产约束从第一条切片开始参与验收,但架构只在已验证切片确有需要时扩展;不得为未来层预建空骨架。
逻辑 Layer、Module、Interface、状态所有权与受控事件流的详细契约见 MODULES.md。该契约约束后续 Issue,但不代表对应实现、目录或部署已经存在。
架构图索引
图只负责展示关系,精确语义仍以 MODULES.md 的职责卡和状态所有者表为准。每张图均提供 SVG 预览和 Excalidraw 权威源文件:
逻辑模块契约
状态:规划
最后复核:2026-08-15
长期讨论:GitHub Discussions
状态与目的
本文定义目标系统的逻辑架构约束,供后续 Issue 设计和验收使用。它描述 target state(目标状态),不代表这些 Module 已实现,也不授权真实下单。
当前仓库包含工程治理、架构文档、文档部署工具和空 Rust workspace;没有行情、订单、风控或交易能力,不可投入真实资金,也未达到生产就绪状态。
设计层次与术语
- Layer(层): 依赖政策,规定哪些知识可以指向哪些知识;它不等于目录、crate 或独立进程。
- Module(模块): 通过一个 Interface 拥有一组内聚状态与行为的逻辑单元;它不等于 crate。Module 应隐藏足够复杂度,删除它会迫使这些复杂度散回多个调用者;纯转发不构成独立 Module。
- Interface(接口): 调用者正确使用 Module 必须知道的完整契约,包括输入输出、不变量、顺序、失败语义、配置和性能特征;它不只是 Rust 函数签名或
trait。 - Seam(接缝): 确有替换需求时放置 Interface、允许替换行为的位置。
- Adapter(适配器): 在 Seam 处满足 Interface、把外部表示或传输语义转换为内部契约的具体实现。一个实现只说明潜在 Seam;两个真实 Adapter 才证明需要稳定 Seam,不为每个 Module 预设
trait。 - Deployment/sharding(部署/分片): 将逻辑 Module 映射到进程、机器和 shard 的后续决策,不等于逻辑分层,也不改变状态所有权。
依赖政策
既定总方向是:
domain <- engine <- adapters/runtime <- apps
A <- B 的精确定义是“B 可以在编译期依赖 A 的稳定 Interface,A 不得依赖 B”。运行时事件可以双向流动,但回报流不反转编译依赖。
允许依赖:
domain只使用语言与标准库能力,不知道网络、venue DTO、持久化、异步 runtime、系统时钟、环境变量或观测出口。engine可依赖domain;核心状态转换通过显式输入产生新状态和 effect。adapters/runtime可依赖engine与domain,负责外部协议、I/O、调度、持久化出口和事件投递。apps可依赖前三层以完成组装和运维入口,但不得承载或旁路业务决策。
禁止依赖:
domain或engine不得依赖 venue DTO、具体 Adapter、runtime、app、数据库或观测后端。- Adapter 不得相互调用来形成隐藏业务流程;跨 Adapter 协调必须回到拥有状态的 engine Module。
- app、Control Plane 或 Observability 不得直接写 book、order、risk 或 account 权威状态。
- 逻辑分层不得被解释为预先创建同名目录、crate、trait、进程或网络 Seam。
逻辑 Module map
下图中的实线箭头表示同步或受控主路径;虚线表示异步出口、只读反馈或控制输入。它展示依赖政策和职责区域,不规定目录、crate、进程或部署。
编辑源:module-architecture.excalidraw
Market Data Ingress / Venue Normalization、Market Data Synchronization + Authoritative Book、Execution Coordination / Quote Reconciliation、Reconciliation + Recovery 和 Journal / Replay 各自合并紧密耦合的步骤:分开只会暴露中间状态并形成浅层转发 Module。只有后续证据显示它们存在独立状态所有权或真实替换需求时才拆分。
venue/drop-copy 等外部对账输入在实现时也必须先由 adapters/runtime 中的具体 Adapter 终止 DTO 并规范化;这个外部输入角色不在本文预建为独立 Module、稳定 Seam 或 trait。
Module 职责卡
Domain Kernel
- Purpose: 统一价格、数量、身份、事件、effect 和跨 Module 不变量的业务含义。
- Owns: 不拥有运行时可变业务状态;拥有整数 tick/lot、身份、事件/effect 与不变量的权威语义。
- Inputs: 已规范化、显式版本化的业务值。
- Outputs/effects: 可验证的值、事件和 effect 描述,不执行 effect。
- Invariants: 相同输入产生相同结果;价格和数量只用整数 tick/lot;无 venue DTO。
- Failure semantics: 非法单位、身份或状态转换被明确拒绝,不猜测或修复输入。
- Hot / warm / cold path: hot;纯确定性计算。
- Allowed dependencies: 语言与标准库。
- Must not: I/O、系统时钟、随机数、环境变量、异步 runtime、持久化、策略或 venue 逻辑。
- Observable acceptance surface: 未来 Issue 通过合法/非法值、顺序和重放样例验证不变量与确定性 effect。
Market Data Ingress / Venue Normalization
- Purpose: 解码 wire DTO,附加显式接收时间与来源身份,并把 venue 语义转换成内部市场事件。
- Owns: 仅拥有输入连接/解码会话上下文;不拥有 book 或业务 sequence 权威状态。
- Inputs: venue wire frame 或已记录的原始输入、版本化连接元数据和时间戳。
- Outputs/effects: 规范化市场事件或明确的解码/协议错误。
- Invariants: DTO 在此终止;来源、时间、精度和 venue 特有语义不丢失也不伪造。
- Failure semantics: 无法解码、未知版本或不完整输入被拒绝并触发不可用信号;不生成猜测事件。
- Hot / warm / cold path: hot 解码;连接建立、重连与协议诊断为 warm。
- Allowed dependencies: Domain Kernel、目标 Market Data Synchronization Interface,以及必要的外部协议/runtime 能力。
- Must not: 维护权威 book、计算信号、决定报价、写订单、执行风控或把 DTO 泄漏给 engine/domain。
- Observable acceptance surface: 用记录输入验证规范化结果、来源/时间保真、错误分类和 DTO 不越过 Interface。
Market Data Synchronization + Authoritative Book
- Purpose: 将 snapshot/delta 对齐,处理 sequence、gap、stale 与 generation,并维护唯一有效 L2 book。
- Owns: validated order book 及其 generation、sequence、stale/valid 状态。
- Inputs: 规范化 snapshot/delta、显式时间/配置 epoch、恢复或失效事件。
- Outputs/effects: 非权威只读
BookView、book 更新事件、失效/重同步 effect。 - Invariants: 每个 shard 单写者;只发布通过顺序与完整性验证的 generation;同一有序输入产生同一 book 和 effect。
- Failure semantics: gap、乱序、陈旧、未知 generation 或恢复不完整时立即失效并 fail-closed,直到新的有效同步证据建立。
- Hot / warm / cold path: hot 更新与校验;snapshot 获取/恢复协调为 warm;记录与诊断为 cold。
- Allowed dependencies: Domain Kernel;由 Runtime 注入的显式输入,不依赖具体 Ingress Adapter。
- Must not: 访问网络/系统时钟、计算策略、发送订单、共享可变 book、把
BookView当作第二权威副本。 - Observable acceptance surface: 通过 snapshot/delta、gap、stale、generation 切换与重放序列验证 book、有效性和 effect。
Feature / Signal Engine
- Purpose: 从已验证 market/account view 增量计算可复现的微观结构特征与信号。
- Owns: feature state、输入版本游标和已发布 signal generation。
- Inputs: 有效
BookView、显式时间/配置输入,以及确有需要的非权威 account view。 - Outputs/effects: 带输入版本的非权威
FeatureView/signal;不产生网络 effect。 - Invariants: 不接受无效 book;相同有序输入和配置产生相同 feature state。
- Failure semantics: 输入 stale、gap、未知或配置不匹配时使输出失效,不沿用旧信号。
- Hot / warm / cold path: hot 增量计算;重建为 warm;分析导出为 cold。
- Allowed dependencies: Domain Kernel 与 Market Data Synchronization 的 Interface;必要时读取 Account 的非权威 view。
- Must not: 写 book/account 状态、决定订单、执行 I/O、隐式读取时间/随机数或保留无版本缓存作为权威。
- Observable acceptance surface: 用版本化 book 序列验证增量结果、失效传播、重建等价性和确定性。
Strategy / Quote Policy
- Purpose: 根据有效 market、feature、account 与 risk view 形成目标报价/撤单意图。
- Owns: strategy state、desired quotes 及其决策 generation。
- Inputs: 版本化
BookView、FeatureView、account/risk view、配置、时间与显式随机输入(若未来确有需要)。 - Outputs/effects: 带因果版本的目标报价和撤单意图,不是交易命令。
- Invariants: 相同有序输入产生相同意图;任何依赖 view 无效时不产生新增风险意图。
- Failure semantics: stale/unknown/recovery incomplete 时输出停止/撤单意图并 fail-closed;不复用无法证明安全的旧报价。
- Hot / warm / cold path: hot 决策;参数切换与状态重建为 warm;分析为 cold。
- Allowed dependencies: Domain Kernel 及 market/feature/account/risk 的只读 Interface。
- Must not: I/O、网络访问、直接下单、分配 client order id、修改 live order/account/risk 权威状态或旁路 Execution。
- Observable acceptance surface: 通过固定输入序列验证意图、因果版本、失效行为、撤单优先和确定性。
Execution Coordination / Quote Reconciliation
- Purpose: 比较 desired quotes 与 OMS 提供的 live-order view,生成最小候选下单/改单/撤单操作并确定安全优先级。
- Owns: reconciliation cursor、已处理目标 generation 与候选计划的因果状态;不拥有 desired quotes 或 live order 生命周期。
- Inputs: Strategy 意图、OMS 非权威
LiveOrderView、venue 能力与显式配置。 - Outputs/effects: 带因果关系和优先级的候选操作,必须交给 Independent Pre-trade Risk。
- Invariants: 撤销风险的操作优先;重复输入幂等;候选操作可追溯到目标和 live-order generation。
- Failure semantics: 任一输入 unknown/stale 或 diff 无法证明安全时不产生新增风险操作,只允许经政策定义的风险降低候选。
- Hot / warm / cold path: hot diff/排序;能力/配置切换为 warm;解释记录为 cold。
- Allowed dependencies: Domain Kernel、Strategy 与 OMS 的只读 Interface。
- Must not: 绕过 Risk/OMS、发送网络命令、分配订单身份、确认订单状态、拥有风险限额或实现策略。
- Observable acceptance surface: 从目标与 live-order 组合验证最小 diff、替换/撤单顺序、幂等、因果关系和 fail-closed。
Independent Pre-trade Risk
- Purpose: 独立评估每个候选操作,执行硬限制、stale/unknown/recovery 门禁与 kill gate。
- Owns: risk limits、计数器、额度占用、gate/kill 投影视图和风险判定 generation;Control Plane 仍是 operator kill 命令的权威来源。
- Inputs: 候选操作、OMS/account/book 的版本化只读 view、Control Plane 的配置/模式/kill 事件和恢复门禁。
- Outputs/effects: 明确许可或拒绝结果及原因;许可只对绑定的候选与输入 generation 有效。仅取消 OMS 已知 live order 的候选可以获得范围受限的 cancel-only permit(仅撤单许可)。
- Invariants: 默认拒绝;所有新增或增加风险的操作必须经过完整风险评估。cancel-only permit 只能绑定已知订单身份且不能创建、替换或扩大订单;限额与计数更新单写者且可审计。
- Failure semantics: 风险状态 stale、gap、unknown、版本不一致或恢复未完成时,拒绝所有新增/增加风险操作,只允许经最小身份与操作类型校验的 cancel-only 候选。Risk 执行本身不可用时不签发任何许可,转由实盘准入前已验证并预置的 venue dead-man、cancel-on-disconnect 或等价会话安全机制撤销挂单,随后保持 recovery not-ready 直到完成对账。
- Hot / warm / cold path: hot 判定/计数;限额版本切换和恢复为 warm;审计导出为 cold。
- Allowed dependencies: Domain Kernel 与 book/OMS/account/control/recovery 的只读 Interface。
- Must not: 生成策略意图、分配 client order id、发送命令、接受旁路调用、把 Observability 当门禁状态或允许 MARKET order 作为回退。
- Observable acceptance surface: 验证每条硬限制、计数和确定性原因;普通许可必须绑定候选与输入 generation,cancel-only permit 必须额外绑定同一 OMS 已知 live order。stale/unknown/kill/recovery 状态下应拒绝所有新增/增加风险操作且仅允许这种受限撤单;Risk 执行不可用时不得产生任何许可。
OMS
- Purpose: 把经风险许可的候选操作转为可审计交易命令,并维护订单完整生命周期与幂等因果关系。
- Owns: client order id、live order lifecycle,以及 pending/ack/reject/fill/cancel 状态和命令幂等键。
- Inputs: 风险许可的候选操作、Trading Venue Adapter 执行回报、恢复/对账修正事件和显式时间/配置。
- Outputs/effects: 交易命令 effect、订单状态事件和非权威
LiveOrderView。 - Invariants: 每条交易命令都必须匹配有效 Risk 许可:创建/替换使用完整许可,显式撤单使用绑定同一 OMS 已知 live order 与输入 generation 的 cancel-only permit。client order id 唯一;状态迁移按因果顺序且可重放。
- Failure semantics: 重复回报幂等;未知、矛盾或缺失回报使相关订单/账户进入不确定状态并触发恢复门禁,不猜测成交或成功。
- Hot / warm / cold path: hot 命令与回报状态转换;超时、恢复、对账为 warm;审计导出为 cold。
- Allowed dependencies: Domain Kernel、Risk 许可 Interface 和 Reconciliation/Recovery 输入;交易命令以 transport-neutral effect(传输无关效果)交由外层路由。
- Must not: 自行放宽风险、实现策略、直接读取 venue DTO、让 Adapter 成为订单权威状态或把 MARKET order 作为错误回退。
- Observable acceptance surface: 验证创建/替换与显式撤单各自匹配正确许可、cancel-only 的订单身份/generation 绑定、无许可不形成命令,以及 ID 唯一、状态机、重复/乱序回报、幂等、因果链与恢复触发。
Trading Venue Adapter
- Purpose: 对交易命令做协议编码、认证与发送,并把执行回报解码为 OMS 可消费的内部事件。
- Owns: 仅拥有 transport/auth session、请求关联与协议级发送状态;不拥有订单业务生命周期。
- Inputs: OMS 交易命令 effect、venue wire 执行回报、显式凭据句柄和连接配置。
- Outputs/effects: wire 发送结果、规范化执行回报和连接健康事件。
- Invariants: 命令身份与因果标识不变;凭据不进入 domain、日志或 journal 明文;回报 DTO 在此终止。进入真实交易模式前必须证明并预置 venue dead-man、cancel-on-disconnect 或等价会话安全机制。
- Failure semantics: 发送结果未知、认证失败或断线时报告不确定性并触发恢复,不擅自重试可能重复的命令。Risk/OMS 显式撤单路径不可用时只执行预先授权的会话失效安全动作;该动作不是下单旁路,其结果仍须由 OMS 和 Recovery 对账。
- Hot / warm / cold path: hot 编解码/发送;连接、认证与重连为 warm;协议诊断为 cold。
- Allowed dependencies: Domain Kernel、OMS Interface,以及必要的协议、网络和 runtime 能力。
- Must not: 包含策略/风险决策、生成未获许可命令、修改 OMS/account 权威状态、记录密钥或以 MARKET order 回退。
- Observable acceptance surface: 用协议样例验证编码、关联、回报转换、未知发送结果、重复回报、断线和密钥不泄漏;另须证明预置会话安全机制不编码订单,触发与结果可审计,并把结果送回 OMS/Recovery 对账。
Account / Portfolio State
- Purpose: 依据已确认执行与权威账户事件维护持仓、余额、敞口和费用状态。
- Owns: 本地 positions、balances、exposure、fees 的权威投影及其 generation;venue/drop-copy 是外部核对来源,不直接共享写入。
- Inputs: OMS 成交/更正事件、经外部 Adapter 规范化的 venue/drop-copy 等价账户事件、配置和对账结果。
- Outputs/effects: 版本化非权威
AccountView、差异事件和恢复/对账请求。 - Invariants: 状态变更有唯一事件因果来源;重复成交幂等;资产、账户和 generation 不混用。
- Failure semantics: 缺失、冲突或无法对账的事件使相关范围 unknown 并关闭交易门禁,不猜测余额或敞口。
- Hot / warm / cold path: fill 驱动的必要风险投影为 hot/warm;全量余额与费用对账为 warm;报表为 cold。
- Allowed dependencies: Domain Kernel、OMS 事件 Interface 与 Reconciliation/Recovery 的核对输入。
- Must not: 发送订单、批准风险、采信 UI/metrics 为权威来源、让 Strategy 写持仓或并存第二个可写账户副本。
- Observable acceptance surface: 验证成交/更正/重复序列、余额与敞口计算、generation、差异检测和 unknown 传播。
Reconciliation + Recovery
- Purpose: 对比本地权威状态与 venue/drop-copy 等价来源,并协调启动、断线和不确定状态的恢复门禁。
- Owns: reconciliation run、差异集合、recovery phase/readiness 与恢复证据状态。
- Inputs: OMS/account/book 快照,经外部 Adapter 规范化的 venue/drop-copy 等价快照或事件,checkpoint、配置 epoch 和连接状态。
- Outputs/effects: 差异、确定性的修正/重建事件、恢复请求和绑定范围的 ready/not-ready 门禁。
- Invariants: 未有完整对账证据不得宣告 ready;修正经拥有状态的 Module 应用,不直接双写其状态。
- Failure semantics: 来源缺失、generation 不一致、差异未解决或恢复中断时保持 not-ready 并 fail-closed。
- Hot / warm / cold path: assurance/recovery warm path;大规模扫描和证据归档为 cold,不进入逐事件热路径。
- Allowed dependencies: Domain Kernel,以及 book、OMS、Account、Control 的快照/事件 Interface;checkpoint 作为外层注入的显式输入。
- Must not: 直接拥有或写 book/order/account/risk 状态、绕过 Risk 打开交易、把 Observability 或 UI 视为恢复证据。
- Observable acceptance surface: 模拟启动、断线、缺失/冲突事件、checkpoint 恢复和会话安全机制触发,验证差异、修正路由,并证明其结果完成对账前始终保持 not-ready。
Journal / Replay
- Purpose: 对原始输入、规范化事件、决策、风险结果、订单命令与回报建立可审计顺序记录,并以相同输入重放核心行为。
- Owns: journal offsets、segment/checkpoint 元数据和已持久化范围;记录内容不取代各业务 Module 的权威状态。
- Inputs: 带因果/版本标识的记录 effect、原始输入,以及显式 replay 配置。
- Outputs/effects: 持久化确认、checkpoint、按确定顺序读取的 replay stream 与完整性错误。
- Invariants: 顺序、来源、版本和因果关系可验证;秘密不得落盘;replay 不隐式读取当前时间或配置。
- Failure semantics: sink 迟滞、写入失败或完整性损坏显式上报并按安全政策触发门禁;不得静默丢弃必需审计记录。
- Hot / warm / cold path: 热路径只产生非阻塞记录 effect;持久化、checkpoint 和 replay 在 warm/cold path。
- Allowed dependencies: Domain Kernel 与 runtime/存储能力;通过稳定记录契约消费 engine effect。
- Must not: 阻塞热路径、直接修改业务权威状态、把日志文本当 replay 契约、引入未证明需要的通用存储 Seam。
- Observable acceptance surface: 验证顺序、完整性、缺失/损坏检测、checkpoint 与相同输入的核心状态/effect 等价性。
Runtime / Shard Coordinator
- Purpose: 为逻辑 Module 提供事件排序、单写者执行、显式时钟/调度、背压和 shard 生命周期。
- Owns: shard assignment/lifecycle、事件队列顺序、背压状态和调度 epoch;不拥有业务状态。
- Inputs: 外部/内部事件、版本化时钟 tick、控制命令和 runtime 配置。
- Outputs/effects: 有序投递、生命周期/背压事件、待执行 I/O effect,以及预先授权且不编码订单的会话失效安全 effect。
- Invariants: 每个 shard 的热状态同时只有一个写入者;排序规则明确;配置/时钟切换有 epoch;会话安全 effect 必须可审计且不能表达创建、替换或扩大订单。
- Failure semantics: 队列溢出、调度未知、所有权冲突或时钟异常时停止相关 shard 的新增风险行为并触发恢复;Risk/OMS 路径不可用时按已验证政策激活预置会话安全机制。
- Hot / warm / cold path: hot 排序/投递;shard 迁移、背压恢复为 warm;诊断为 cold。
- Allowed dependencies: Domain Kernel 与 engine Module Interface,以及必要的 runtime/I/O Adapter。
- Must not: 承载策略、book、风险或订单语义,隐式读取纯逻辑所需时间/随机数,通过多写者提高吞吐,或把会话失效安全 effect 扩展成普通交易命令旁路。
- Observable acceptance surface: 验证顺序、单写者、epoch、背压、生命周期和故障时的 fail-closed 投递;会话安全 effect 必须不编码订单,触发/结果可审计,并使 Recovery 在对账完成前保持 not-ready。
Control Plane
- Purpose: 管理版本化配置、trading mode、启动/停止、operator command 和 kill switch,并把它们变成可审计事件。
- Owns: config epoch、trading mode、operator kill state 和控制命令生命周期。
- Inputs: 经认证授权的 operator command、配置候选、运行/恢复状态。
- Outputs/effects: 版本化控制事件、拒绝原因,以及供 Runtime/Risk 消费的非权威 view;kill 可请求 Runtime 激活预置的会话安全机制。
- Invariants: kill/停止优先;配置切换原子且带 epoch;所有控制命令进入同一可审计状态转换。
- Failure semantics: 身份、版本、状态或授权未知时拒绝;Control Plane 不可用不能打开交易。
- Hot / warm / cold path: control/warm path;kill 传播具有安全优先级但不把 UI 放入热业务路径;审计为 cold。
- Allowed dependencies: Domain Kernel 与 Reconciliation/Recovery 的状态 Interface;operator/runtime 状态由外层转换成显式输入事件。
- Must not: 旁路 Risk/OMS/Runtime 直接触达 Trading Adapter、直接写业务权威状态、从 UI 状态推断交易许可。
- Observable acceptance surface: 验证授权、epoch、模式转换、kill 优先级、重复命令幂等、审计链与不可用时拒绝;kill 必须同时关闭 Risk 门禁,并按既定政策请求 Runtime 激活预置会话安全机制。
Observability / Audit Export
- Purpose: 异步导出 metrics、log、trace 和审计副本,支持诊断、恢复验证和生产准入证据。
- Owns: 仅拥有出口缓冲、投递游标和后端健康状态;所有观测数据都是非权威副本。
- Inputs: 结构化观测/审计 effect 和显式标签/配置版本。
- Outputs/effects: 后端投递、丢弃/降级计数和出口健康信号。
- Invariants: 不阻塞热路径;敏感信息被过滤;标签基数与采样政策显式版本化。
- Failure semantics: 后端失败不得反向修改业务状态;必需审计出口失败通过 Control/Risk 政策触发安全门禁,而非由 exporter 自行控制。
- Hot / warm / cold path: cold async path;热路径只产生有界、非阻塞 effect。
- Allowed dependencies: 结构化 effect 契约、runtime 与外部观测 Adapter。
- Must not: 成为 book/order/risk/account 权威来源、回调控制热路径、记录密钥、承载业务恢复逻辑。
- Observable acceptance surface: 验证异步性、背压/丢弃可见性、敏感信息过滤、游标和后端故障不反向写业务状态。
App / Operator Surface
- Purpose: 组装具体 Module/Adapter/runtime,提供受约束的启动、停止与运维入口。
- Owns: 不拥有交易业务状态;仅拥有进程级组装与入口生命周期。
- Inputs: 启动参数、经认证 operator input 和部署环境提供的资源句柄。
- Outputs/effects: Module 组装、受控 operator command 提交和进程退出状态。
- Invariants: 所有控制动作进入 Control Plane;所有交易动作经过 Execution、Risk、OMS 与 Trading Adapter。
- Failure semantics: 配置、依赖或身份校验失败时不启动/不进入交易模式;关闭时保持审计与恢复语义。
- Hot / warm / cold path: control/cold path,不参与逐事件热业务决策。
- Allowed dependencies: domain、engine、adapters/runtime,仅用于 composition root(组装根)与入口。
- Must not: 直接写 book/order/risk/account,旁路 Control/Risk/OMS 触达 Adapter,嵌入策略语义或成为第二状态机。
- Observable acceptance surface: 验证组装失败、启动/停止、命令路由、权限拒绝和不存在任何交易旁路。
唯一状态所有者
“权威”表示只有该 Module 能提交对应状态转换;其他 Module 只能消费带 generation/epoch 的不可变快照、事件或 derived view(派生视图)。
| 状态 | 唯一权威 Module | 非权威暴露 |
|---|---|---|
| validated order book、generation、sequence、stale/valid | Market Data Synchronization + Authoritative Book | BookView、book 事件 |
| feature state、signal generation | Feature / Signal Engine | FeatureView、signal |
| strategy state、desired quotes、决策 generation | Strategy / Quote Policy | 报价/撤单意图 |
| execution reconciliation cursor、候选计划因果状态 | Execution Coordination / Quote Reconciliation | 候选操作 |
| live order lifecycle、client order id、命令幂等键 | OMS | LiveOrderView、订单事件 |
| risk limits、counters、额度占用、gate 判定状态 | Independent Pre-trade Risk | RiskView、许可/拒绝事件 |
| positions、balances、exposure、fees | Account / Portfolio State | AccountView、差异事件 |
| reconciliation run、recovery phase/readiness | Reconciliation + Recovery | ready/not-ready view、恢复证据 |
| config epoch、trading mode、operator kill state | Control Plane | 版本化控制事件/view |
| journal offsets、segments、checkpoints | Journal / Replay | replay stream、持久化确认 |
| shard lifecycle、事件顺序、背压与调度 epoch | Runtime / Shard Coordinator | runtime 健康/生命周期事件 |
Trading Adapter 的 transport session、Ingress 的 decode session、Observability 的出口游标和 app 的进程生命周期只在各自实现范围内权威;它们不得被提升为 book、order、risk、account 或交易许可的权威来源。
受控事件流
下图是事件/effect 流,不代表编译依赖。虚线反馈均为带版本的只读 view 或事件;任何真实交易操作只有一条受控路径。
编辑源:order-lifecycle-sequence.excalidraw
市场数据与恢复时序
市场数据时序区分正常发布与 gap/stale 的 fail-closed 分支;Feature Engine 标为未来能力,异步 Journal 不阻塞热路径。
编辑源:market-data-sequence.excalidraw
恢复与对账时序覆盖启动、断线、market-data gap 和进程重启;只有权威状态一致且 recovery complete 才能进入 trading-ready。
编辑源:recovery-reconciliation-sequence.excalidraw
跨 Module 固定规则
- 核心转换统一为
event in -> state/effect out;相同有序输入、配置、时间与随机输入必须产生相同核心状态和 effect。 - 每个 shard 的热状态只有一个写入者;冷路径异步,I/O、持久化和观测不得阻塞热路径。
- 时间、随机数和配置必须作为显式、版本化输入;纯逻辑不得隐式读取系统时钟、随机源或环境变量。
- stale、gap、unknown 或 recovery incomplete 一律 fail-closed。
- Observability、UI 和 journal sink 都不是业务权威状态。
- 不设置全局共享可变 order book、order、risk 或 account 状态;跨 Module 只传递不可变事件、effect 和带版本的非权威 view。
- Strategy 不做 I/O,不直接发送网络请求或交易命令。
- 真实交易命令只能沿
Execution -> Risk -> OMS -> Trading Adapter路径;Control、app、Strategy 和恢复流程都不得旁路。 - 显式撤单同样经过 Risk 的 cancel-only 校验和 OMS。Risk 执行本身不可用时,只能激活实盘准入前已验证并预置的 venue dead-man、cancel-on-disconnect 或等价会话安全机制;这不是普通交易命令旁路,触发和结果必须记录,并在恢复/对账完成前保持禁止交易。
- 延迟只定义未来测量边界:输入接收、book 生效、决策产生、风险完成、命令交付和执行回报归因;在真实测量前不给出数字或保证。
固定与暂缓决策
现在固定:
- 单进程 modular monolith 起步。
- 本文的逻辑 Module 边界、唯一状态所有者和受控交易路径。
- 每 shard 热状态单写者、确定性输入模型、fail-closed 和独立 Risk 不可旁路。
- 冷路径异步,外部 DTO 在 Adapter 终止,Interface 是未来 Issue/QA 的验收面。
暂缓到真实 vertical slice 提供证据后决定:
- crate/file 布局、具体 Rust
trait/function/event schema。 - async runtime、内存数据结构、持久化格式和第三方依赖。
- 进程拆分、机器部署、shard key、跨进程协议和具体 latency budget。
- 任何 Seam 的代码形式;只有两个真实 Adapter 证明替换需求后才稳定 Seam。
Phase 1 最小映射
第一条 deterministic market-data vertical slice 只映射:
- Domain Kernel 中该切片真实需要的整数 tick/lot、身份、市场事件与 effect 类型。
- 一个 recorded input Adapter 或等价的最小输入边界;它是具体输入角色,不预先创建通用
trait或可替换 Seam。 - Market Data Synchronization + Authoritative Book,覆盖 snapshot/delta、sequence/gap/stale/generation 与唯一权威 L2 状态。
- Journal / Replay 中仅用于证明相同记录输入产生相同 book 状态/effect 的 deterministic replay harness;不预建持久化平台。
本映射不实现 Strategy、Execution、Risk、OMS、Trading Venue Adapter、Account、Control 或生产部署能力,也不在本 Issue 创建任何代码或目录骨架。
架构图维护规则
状态:已实现
最后复核:2026-08-15
长期讨论:GitHub Discussions
同名 .excalidraw 是权威可编辑源,.svg 是派生预览。每张图独立使用一个基础文件名,并始终成对提交;不使用 .excalidraw.svg、PNG、PDF 或单个超大画布。
用 Excalidraw 打开 .excalidraw 源文件。修改后以 SVG、light mode(浅色模式)、白色背景重新导出;编辑器支持时嵌入字体。不得手工修改 SVG 来替代源文件更新。
Markdown 使用相对路径内嵌预览并在下一行链接编辑源:

[编辑源:example.excalidraw](diagrams/example.excalidraw)
同一 PR 必须同步更新 source 与 SVG。QA 应解析 .excalidraw JSON 和 SVG XML,检查文件配对及 Markdown 相对链接,并实际渲染每张 SVG,验证中文、文字裁切或重叠、箭头端点、连线、图例、背景、对比度和页面宽度下的可读性。
路线图
状态:规划
最后复核:2026-08-15
长期讨论:GitHub Discussions
目标是分阶段达到可投入真实资金、面向生产部署的低延迟高可靠 HFT/MM 引擎。进度由可观察的验证结果控制,而不是由预建层级推动;每个阶段必须先定义输入契约、状态所有者、失败语义、确定性检查和完成证据,才能进入下一阶段。
1. 确定性市场数据垂直切片——下一阶段
按 MODULES.md 的 Phase 1 最小映射,只实现 Domain Kernel 中真实需要的类型、一个 recorded input Adapter(或等价最小输入)、Market Data Synchronization + Authoritative Book,以及 deterministic replay harness。不实现 Strategy、Execution、Risk、OMS 或 Trading。
完成证据必须证明:单一写入者更新唯一权威 book 状态;相同有效记录输入产生相同 book 状态与 effect;无效、陈旧、有缺口或乱序输入采用 fail-closed。具体 crate、trait、runtime、数据结构和持久化格式仍由该切片的证据决定。
后续阶段——仅在前序门禁通过后
- 增加 raw journal、时间戳、可观测性、延迟测量,以及 book 状态恢复/重建。
- 接入复用相同已验证行为的 venue 市场数据 Adapter,并验证断线、缺口和恢复语义。
- 在仅仿真执行的边界内建立可审计 OMS 与 Trading Adapter 契约;此阶段仍禁止真实下单。
- 建立持仓/余额状态,以及基于 drop-copy 或等价来源的交易所订单、成交和账户对账。
- 建立独立 pre-trade risk、硬限制、kill switch、故障恢复和重启后对账门禁。
- 在 replay/simulation 中接入简单报价策略,并验证确定性、风险拒绝和订单审计。
- 依次通过 replay、paper 与 shadow 验收,不使用真实资金。
- 只有专门 Issue、风险门禁、恢复演练、审计证据、可观测性与延迟预算全部验收且用户明确授权后,才进行小资金灰度和生产准入验收。
以上 OMS、风控、策略、恢复、对账和生产准入目前仅是路线图条目,仓库中尚无对应实现或骨架。
工程工作流
状态:已实现
最后复核:2026-08-15
长期讨论:GitHub Discussions
工作契约
- **Milestone(里程碑)**是阶段目标和进度容器。
- Issue 是唯一任务契约,其可观察验收标准约束实现和 QA。
- 一个内聚 outcome 对应一个 Codex 任务:一个 Issue、一个
issue/<number>-<slug>分支、一个仓库外 worktree 和一个 PR。 - 每个实现只有一个 tracked-file 写入者。负责统筹的工程 Agent 只承担治理与协调;每个 Issue 都在独立 worktree 任务中实现。
当 Issue 的 outcome、范围、可观察验收标准、验证命令、安全或风险约束和依赖均已明确,必要决策已解决,且规模足以由一个内聚 PR 完成时,Issue 才是 Ready。
角色
- Implementer(实现者): 唯一写入者。每个代码任务都必须在实现全程使用已安装的
ponytail:ponytailskillfull模式。Implementer 负责自检、发布 Issue 分支、维护 Draft PR、修复 finding,并在冻结最终 SHA 前完成文档影响扫描。 - Reviewer(审查者): 在同一最终 SHA 上执行只读审查。先审查正确性、架构、安全、回归风险、测试缺口、文档语言与实现/测试/图表的语义一致性,并单独报告 Documentation Consistency Review;涉及订单、风控或状态时,必须检查资金安全、fail-closed、恢复、对账和审计语义。随后运行已安装的
ponytail:ponytail-reviewskill 查找不必要复杂度。Ponytail 绝不替代标准审查。Reviewer 不修复文件,并分别报告结果。 - QA(质量验收): 不运行 Ponytail。QA 使用真实命令,依据 Issue 的可观察验收标准验证精确的最终 head SHA,并报告 SHA、环境、命令、结果和未验证项;同时确认本次范围内面向人的文档以简体中文为主。QA 必须构建文档 HTML 并人工检查目录、关键页面和图表渲染;涉及资金或交易状态时,还必须验证 fail-closed、恢复、对账和审计的可观察验收标准。QA 可以生成已忽略的构建产物,但绝不编辑源码、测试、配置、文档或其他 tracked file。
- 用户: 唯一 merge authority(合并权威)。
Reviewer 和 QA 的 finding 都返回 Implementer。subagent 审查是证据,不等于 GitHub required approval;使用同一 GitHub 身份的 Agent 绝不伪装成独立审批者。
PR 流程
- 创建 Issue,fetch
origin/main,并在仓库外 worktree 中创建对应分支。 - 首次 push 后,默认创建目标为
main的 Draft PR,并写入Closes #<number>。只有 Issue 明确记录依赖关系且用户授权 stacked workflow 时,分支才可从依赖 PR 的冻结 head 创建,并以依赖分支为临时 PR base;PR 正文必须标明依赖 PR 和后续 retarget 计划。 - Implementer 完成 Issue 验收标准、运行仓库检查、更新 PR 证据并冻结 head SHA。
- Implementer 按
DOCUMENTATION_POLICY.md阅读相对 PR base 的完整 diff,更新背离的正文/图表,运行文档校验、测试和构建,并在 PR 记录Documentation Impact与证据。 - Reviewer 针对该 head SHA 与当前 PR base 的 merge-base(审查 fixed point)先运行标准审查及 Documentation Consistency Review,再运行
ponytail:ponytail-review,并记录 base 名称、base SHA、merge-base 与 head SHA,全程不编辑文件。 - Implementer 修复 finding、重跑检查、push 新 SHA,并要求 Reviewer 重跑受影响的审查。
- QA 验证最终 SHA,并确认验证前后 tracked diff 不变。
- 只有 Standard Review、Ponytail Review(改动代码或工具时)、Documentation Consistency Review、QA 和适用的 docs CI 在同一最终 SHA 上全部
PASS后,PR 才能从 Draft 转为 Ready for review。 - 由用户决定是否 merge。
任何新 commit 都会使之前的最终 SHA 证据失效,并触发受影响的 Reviewer 与 QA 步骤重跑。
Stacked PR 的依赖 PR 合并后,Implementer 必须先 fetch origin/main,确认新 main 已包含依赖 PR 的预期结果,再用安全 rebase 或等价的无损方式把当前分支更新到新 base,并将 PR base retarget 为 main。base、merge-base 或 head 的任何变化都会使既有 diff、Review 与 QA 证据失效,必须按新的 fixed point 重跑检查;不得通过丢弃提交或覆盖他人改动来迁移 base。
仅在 Milestone 或阶段结束时使用 ponytail:ponytail-audit。只有存在 ponytail: 标记时,才在阶段结束或发布前运行 ponytail:ponytail-debt。ponytail:ponytail-gain 与 ponytail:ponytail-help 仅手动使用,绝不作为 merge 门禁。
授权与安全
明确分配的 Issue 实现任务授权创建对应 Issue 分支/worktree、commit 和 push 该分支,以及创建或更新匹配的 PR;它绝不授权直接 push main 或 merge。产品目标包含真实资金交易,但任何真实下单仍始终需要未来专门 Issue 的风险门禁、验收证据和用户新的明确授权;未知或不安全的交易状态继续采用 fail-closed。
合并与清理
只使用 squash merge。目标为默认分支的 PR 合并后,通过 Closes #<number> 关闭对应 Issue;随后由 GitHub 删除远端 head branch。确认合并后,再删除本地 worktree 和本地 Issue 分支。
首个真实 Rust target 出现前,不得添加空洞或伪造的 Rust CI。文档站已经具有真实可验证的构建目标,因此允许运行唯一命名的 docs job;Rust 格式化、Clippy 和测试仍须等对应 target 存在后再启用。
当前仓库已迁移至 caasxyz 组织私有仓库,并启用 Protect main ruleset;该 ruleset 目前只要求经 PR 合并并禁止删除与 non-fast-forward,尚未把 docs 配置为 required status check。因此 docs 仍通过用户 merge discipline(合并纪律)、PR 检查结果和最终 SHA 审查证据执行门禁,不得声称平台已经强制。只有通过独立 Issue 配置并验证 required check 后,文档才可改为平台强制状态;首个真实 Rust target 出现且唯一命名的 ci job 成功前,仍不得添加 Rust required check。
文档治理政策
状态:已实现
最后复核:2026-08-15
长期讨论:GitHub Discussions
目的与权威来源
文档是安全、开发和运维控制面的一部分。实现、测试、图表和文档必须描述同一系统事实;已经背离实现的文档不得以“后续补充”为由进入 ship。
- Markdown 是正文权威源。
.excalidraw是架构图和时序图的权威可编辑源;同名.svg是派生预览。SUMMARY.md是文档站唯一目录来源。book/是可删除、可重建的 HTML 产物,不提交 Git。- Issue 定义任务契约,PR 中通过审查的文档才会改变项目权威描述。
- Discussion 只保存长期讨论上下文,不能替代 Issue、PR、ADR 或已合并文档。
内容规则
- 面向人的文档默认使用简体中文;代码标识符、协议字段、命令和难以准确翻译的标准术语可以保留英文。
- 文档必须明确区分
规划、已实现、已验证和已废弃,不得把目标状态写成当前能力。 - 架构、治理、运行手册等长期文档必须在标题后记录状态、最后复核日期、关联 Issue/PR;存在长期讨论时附 Discussion 链接。
- 没有可复现证据时,不得声称 production-ready、延迟、吞吐、盈利或故障恢复能力。
- 不得记录 API Key、Token、私钥、账户凭证、真实生产数据或其他秘密。
- 不得引用外部图片或公开 Excalidraw 分享地址;文档所需资源必须随仓库保存。
- 架构图、模块图、数据流图和时序图使用 Excalidraw,不以 Mermaid 替代。
必须更新文档的变更
| 变更 | 至少检查或更新 |
|---|---|
| Module 职责、依赖方向、线程或状态所有权 | ARCHITECTURE.md、MODULES.md、对应架构图 |
| Event、Command、状态机和顺序语义 | 领域契约、对应时序图 |
| 行情、order book、sequence、gap 或 stale 行为 | 市场数据架构与恢复时序 |
| OMS、订单生命周期和成交处理 | 订单生命周期文档与时序图 |
| 风控、限额、kill switch 或 fail-closed | 架构、安全说明与运行手册 |
| 重连、恢复、重放、对账或审计 | 恢复时序与运行手册 |
| 配置、CLI、环境变量、构建或部署 | README、工作流或运行手册 |
| 阶段门禁和当前能力 | ROADMAP.md 与首页状态 |
| 长期有效且影响广泛的设计选择 | 新增或更新 ADR |
没有可观察行为、契约或运维影响的内部重构可以不修改正文,但 PR 必须说明 Documentation Impact: not-required 的具体理由。
人工审阅与讨论边界
mdBook:阅读最终效果
mdBook 提供目录、搜索、页面导航、SVG 渲染以及返回仓库/建议修改入口。它只负责阅读,不承载审批、评论或身份授权。
GitHub PR:当前变更的正式审查
逐行评论、suggestion、Standard Review、Ponytail Review、Documentation Consistency Review 和 QA 证据都归属于当前 PR 的精确最终 SHA。任何新 commit 都会使受影响的证据失效。
GitHub Discussions:跨版本长期讨论
Discussion 用于尚未形成任务契约的架构问题、备选方案和跨 PR 讨论。被接受的结论必须创建或关联 Issue,并通过 PR 回写权威文档;未回写的 Discussion 结论不生效。不得自动为每页创建 Discussion,也不嵌入第三方评论系统。
GitHub 私有仓库权限和 Cloudflare Access 权限彼此独立。能够阅读 Cloudflare 文档站但没有仓库权限的用户,不能访问私有 PR、编辑入口或 Discussion。
Ship 前文档扫描
Implementer 在 PR 从 Draft 转为 Ready for review 前必须:
- 阅读
git diff --name-status <base>...HEAD和完整 diff。 - 确认 PR 中的
Documentation Impact为required或给出not-required理由。 - 逐项检查模块职责、数据流、状态机、配置、风控、恢复、对账、审计、阶段状态和图表是否仍与实现一致。
- 修正目标能力被误写成已实现、已经实现却仍标为规划、以及没有证据的性能或安全声明。
- 运行文档校验器、测试和
mdbook build,并在 PR 中记录命令与结果。 - 将需要长期讨论的未决事项链接到 Discussion;已经采纳的 Discussion 结论必须在本 PR 回写。
Reviewer 对最终 SHA 报告 Documentation Consistency Review: PASS / FAIL,检查语义一致性而非仅检查格式。QA 构建 HTML,并实际检查首页、导航、中文、关键页面和 SVG。Reviewer 或 QA finding 导致新 commit 后,受影响步骤必须重跑。
自动检查与人工判断的边界
tools/validate_docs.py 检查目录完整性、相对资源、图表格式与配对、禁用内容、状态栏和不可提交的构建产物。CI 运行同一校验器、测试和 mdBook 构建。
当前 caasxyz 组织私有仓库已启用 Protect main ruleset,但尚未把 docs 配置为 required status check。现阶段仍由用户依据 PR 上的成功检查与最终 SHA 审查证据执行合并门禁;只有独立 Issue 完成配置和真实验收后,才能声称该门禁由平台强制。
中文表达质量、架构语义、图形布局和实现一致性不能可靠地用简单规则判断,继续由 Reviewer 与 QA 人工验收;不得增加脆弱的中文字符比例或自动语义评分门禁。
文档站运行手册
状态:已实现
最后复核:2026-08-16
长期讨论:GitHub Discussions
当前边界
Issue #5 已建立本地 HTML 与 CI 构建。Issue #6 已把真实 mdBook 文档部署到 Cloudflare Pages 并绑定自定义域名。doc.trading-engine.caas.xyz 已通过未登录 302 验证由 Access 保护,但 pages.dev production/hash 入口仍可公开读取,因此整个站点不是私有站点。
Cloudflare Pages 项目初始化
初始化器只读取 1Password Vault hft-mm-engine-dev 中 Item cloudflare-pages-deploy 的三个初始字段:
api_token:仅限目标 Account 的Cloudflare Pages / Edit。account_id:Cloudflare Account ID。project_name:Pages 项目名。
本地运行固定使用 1Password CLI 2.34.1;版本不一致时初始化器在读取配置前失败关闭。
用户不需要填写 pages_project_id、pages_hostname、production_branch、pages_domains 或 initialized_at。初始化器从 Cloudflare canonical project 自动取得这些非秘密元数据,并只回填上述字段。
默认命令只生成只读计划:
python3 tools/cloudflare_pages_init.py plan
确认计划中的 Account ID、Project Name 和动作后,显式执行:
python3 tools/cloudflare_pages_init.py apply
行为约束:
- 查询到现有项目时复用,不重复创建。
- 只有 Cloudflare 明确返回 Project not found 时,
apply才创建项目;权限、网络、限流或未知错误全部失败关闭。 - 创建前先确认 1Password 不含陈旧项目元数据;写回后重新读取并核对 Cloudflare canonical project 与全部归属字段。
- HTTP 客户端拒绝所有重定向,避免把 Authorization header 转发给其他 origin。
- 核心执行入口只接受精确的
plan或apply,任何拼写错误都不能触发副作用。 - 已回填值与 Cloudflare 不一致时报告 drift 并停止,不静默覆盖。
- 再次执行相同
apply必须得到no-op。 - 输出只包含非秘密项目元数据和动作,不输出 API Token、Authorization header 或完整 1Password Item。
- 初始化执行阶段的成功和失败均输出带已知非秘密上下文、时间、耗时、动作及错误分类的单行脱敏 JSON,作为可保存的审计记录。
- 初始化器不绑定域名、不修改 DNS/Access、不轮换 Token,也不部署文档。
2026-08-16 初始化验收
plan确认目标项目不存在,计划动作为create。apply创建 Pages 项目trading-engine,Cloudflare canonical hostname 为trading-engine-4wl.pages.dev。- 初始化器将非秘密项目元数据回填至既有 1Password Item。
- 紧接着再次运行
plan与apply,两者均返回no-op,没有重复创建或写入。 - 使用固定 Wrangler
4.123.0向 production branchmain部署了无敏感内容占位页;deployment hash 为edcbe490。 - 未登录探针确认 production 与该 hash deployment 均可直接返回占位正文,说明现有 Access 配置尚未实际覆盖这些入口;真实文档因此没有上传。
- 用户选定自定义域名
doc.trading-engine.caas.xyz,并已定向写入 1Password 的custom_hostname字段;Pages association、DNS 与 TLS 已生效。 - 一次本地 operator 探针的异常输出暴露了旧 Cloudflare API Token;用户已撤销并轮换,初始化器对新 Token 的只读
plan返回no-op。 - 自定义域名未登录请求返回 Cloudflare Access 登录跳转;
trading-engine-4wl.pages.dev与 hash deployment 仍直接返回 HTTP 200,占位正文可公开读取。 - Access bootstrap Token 可读取计划,但创建 Application 返回
403 / 1010;没有通过该 Token 创建或修改任何 Access 对象。 - 用户于 2026-08-16 明确授权跳过剩余
pages.devAccess 权限问题并公开部署真实文档。该决定使pages.dev成为已知公开旁路;noindex等响应头不是访问控制。
2026-08-16 真实文档部署验收
- 使用固定 Wrangler
4.123.0从提交e2e01cb2e75f89307c7a7c77f99521a999728096的book/部署 53 个静态文件。 - 首次真实文档 deployment hash 为
56332f8e。 - production 与 hash URL 均返回 HTTP 200,并包含文档首页标记;它们不经过 Access。
- 自定义域名
doc.trading-engine.caas.xyz的未登录请求返回 Cloudflare Access 登录跳转,正文未泄露给该请求。 - production 与 hash URL 均返回
X-Robots-Tag: noindex, noarchive、Cache-Control: no-store、X-Content-Type-Options: nosniff和X-Frame-Options: DENY。 - 尚未执行授权用户登录后的首页、导航、搜索和 SVG 外部验收;用户通过自定义域名完成人工 review。
本地阅读
仓库固定使用 mdBook v0.5.4 官方预编译二进制,不通过升级项目 Rust 工具链安装 mdBook。当前 Apple Silicon Mac 的最小安装方式:
mkdir -p .tools
curl --fail --location --output .tools/mdbook-v0.5.4.tar.gz \
https://github.com/rust-lang/mdBook/releases/download/v0.5.4/mdbook-v0.5.4-aarch64-apple-darwin.tar.gz
echo "03e8a6d8b13a2971e0b3280affd03b388373c1485e26f73407c3a76b0b1838df .tools/mdbook-v0.5.4.tar.gz" \
| shasum -a 256 --check
tar -xzf .tools/mdbook-v0.5.4.tar.gz -C .tools
构建或启动本地阅读服务:
python3 tools/validate_docs.py
.tools/mdbook build
node tests/test_cjk_search.mjs
.tools/mdbook serve --open
静态入口是 book/index.html。book/ 和 .tools/ 均为本地生成内容,不提交 Git。
cjk-search.js 只补充 mdBook 内置 elasticlunr 的中文单字/双字 token,不引入搜索服务、第三方依赖或自定义主题。回归检查使用 mdBook 实际生成的索引格式验证“文档治理”“治理”“文档”和英文查询。
CI 产物
PR 上的 docs job 使用固定版本并校验 SHA256 后构建文档,上传保留 7 天的私有 GitHub Actions artifact。它只用于渲染检查,不是发布地址;当前 main 构建也不会自动部署 Cloudflare。
人工审阅
- 阅读者在 mdBook 中检查导航、搜索、中文、代码块、表格和 SVG。
- 审查者回到对应 GitHub PR 逐行评论并提交 Review。
- 跨版本问题从仓库 Discussions 根入口发起;当前沿用 GitHub 自动创建的默认分类,采纳结论必须经 Issue/PR 回写文档。
- Cloudflare Access 只控制其覆盖入口的文档站阅读权。GitHub 私有仓库权限单独控制 PR、编辑和 Discussion;两者不会自动同步。
恢复全私有部署的前置条件
私有部署的原始验收标准仍要求所有 Pages host 在未登录环境无法读取正文;noindex 不能替代 Access。当前用户已经显式接受公开 pages.dev 旁路并授权部署,因此本次发布只能声明为“自定义域名受 Access 保护、Pages 原生入口公开”,不得描述为全私有站点。若以后恢复私有目标,必须保护 production/hash/wildcard 三类 pages.dev 入口并重新执行未登录验收。
如长期讨论数量增长,可在 Issue #6 开始前由仓库管理员把默认开放分类重命名为“文档讨论”;这只是可选的信息架构调整,不阻塞当前文档门禁,也不得删除仍在使用的分类。