Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions config/hk_snapshot_verification.workflow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# One manual account snapshot verification on Google Cloud Workflows.
# Call logging stays disabled. Only the validated field counts leave the workflow.
main:
steps:
- configuration:
assign:
- origin: ${sys.get_env("HK_SNAPSHOT_ORIGIN")}
- expected_binding: ${sys.get_env("HK_SNAPSHOT_EXPECTED_BINDING")}
- requested_at: ${sys.now()}
- check_configuration:
switch:
- condition: '${not text.match_regex(origin, "^https://[a-z0-9-]+[.][a-z0-9-]+[.]run[.]app$") or not text.match_regex(expected_binding, "^[a-f0-9]{64}$")}'
raise: hk_snapshot_configuration_invalid
- read_snapshot:
try:
call: http.get
args:
url: ${origin + "/account-snapshot"}
timeout: 30
headers:
Accept: application/json
auth:
type: OIDC
audience: ${origin}
result: response
except:
as: error
steps:
- reject_http_error:
raise: hk_snapshot_request_failed
- select_snapshot:
assign:
- snapshot: ${response.body}
- now: ${sys.now()}
- check_binding_and_fields:
switch:
- condition: '${response.code != 200 or get_type(snapshot) != "map" or map.get(snapshot, "schema_version") != "longbridge_account_snapshot.v1" or map.get(snapshot, "status") != "partial" or map.get(snapshot, "account_scope") != "HK" or map.get(snapshot, "no_order") != true or map.get(snapshot, "live_authority_granted") != false or map.get(snapshot, "cash_complete") != true or map.get(snapshot, "positions_complete") != true}'
raise: hk_snapshot_contract_invalid
- condition: '${map.get(snapshot, ["source_binding", "kind"]) != "deployment_scope_token_version" or map.get(snapshot, ["source_binding", "status"]) != "bound" or map.get(snapshot, ["source_binding", "id"]) != expected_binding}'
raise: hk_snapshot_binding_invalid
- condition: '${get_type(map.get(snapshot, "broker_reported_balances")) != "list" or len(snapshot.broker_reported_balances) == 0 or get_type(map.get(snapshot, "positions")) != "list"}'
raise: hk_snapshot_fields_invalid
- verify_observation_time:
assign:
- started: ${time.parse(snapshot.observed_started_at)}
- finished: ${time.parse(snapshot.observed_finished_at)}
- check_freshness:
switch:
- condition: ${started < requested_at or started > finished or finished > now or now - started > 900}
raise: hk_snapshot_time_invalid
- receipt:
return:
account_scope: HK
source_binding_verified: true
read_only_snapshot_verified: true
observed_at: ${snapshot.observed_finished_at}
balance_count: ${len(snapshot.broker_reported_balances)}
position_count: ${len(snapshot.positions)}
2 changes: 2 additions & 0 deletions docs/read-only-account-observation.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

`independent_get` 适用于可由当前执行器访问的已鉴权 Cloud Run 服务。内部 ingress 返回固定原因 `internal_observer_required`,在调用券商或发送账户事实前停止;不得为采集开放 ingress。内部服务应复用受支持的内部执行入口,另行验证只读采集、私有归档与接收闭环。此文档不表示该内部闭环已经完成。

HK 内网连通性可用 `config/hk_snapshot_verification.workflow.yaml` 单独验证。它在同一 GCP 项目通过 OIDC 调用固定的 `GET /account-snapshot`,从受保护的部署配置读取服务地址和预期绑定。验证只返回时间、字段数量和绑定结果。Cloud Workflows 的调用日志须关闭,运行身份单独配置,调用者不能传入地址、方法或请求参数。验证入口无定时触发,首次真实读回后再接归档和日报。

单次操作最多一次快照 GET 和一次事实 POST,不自动重试未知结果。投影保留券商实际币种、金额、观察时间及来源;账户来源不匹配时拒收,不补零、不改旧数据时间。交易启停、风险预算和通知不由此观察器控制。

本次配置迁移只覆盖独立观察器与该心跳工作流。历史 Scheduler 观察器及其他部署流程尚有旧配置约定,不能据此宣称全仓已完成配置与隐私整改。
Loading