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
21 changes: 21 additions & 0 deletions .github/workflows/deploy-strategy-switch-console.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,19 @@ jobs:
target.write_text(text, encoding="utf-8")
PY

- name: Verify M0 research-ledger ingress token
env:
# Only the Worker deployment receives this copy. The M0 publisher
# reads the same value from its separate main-only Environment,
# never the Cloudflare deployment credentials.
M0_RESEARCH_SYNC_TOKEN: ${{ secrets.M0_RESEARCH_SYNC_TOKEN }}
run: |
set -euo pipefail
if [ -z "${M0_RESEARCH_SYNC_TOKEN:-}" ]; then
echo "M0_RESEARCH_SYNC_TOKEN is required so a deployment cannot retain a stale M0 ingress credential." >&2
exit 2
fi

- name: Deploy Worker
working-directory: web/strategy-switch-console
run: npx wrangler@4.106.0 deploy --config wrangler.toml
Expand Down Expand Up @@ -152,6 +165,14 @@ jobs:
set -euo pipefail
printf '%s' "$EXECUTION_EVIDENCE_SYNC_TOKEN" | npx wrangler@4.106.0 secret put EXECUTION_EVIDENCE_SYNC_TOKEN --config wrangler.toml

- name: Sync M0 research-ledger ingress token
env:
M0_RESEARCH_SYNC_TOKEN: ${{ secrets.M0_RESEARCH_SYNC_TOKEN }}
working-directory: web/strategy-switch-console
run: |
set -euo pipefail
printf '%s' "$M0_RESEARCH_SYNC_TOKEN" | npx wrangler@4.106.0 secret put M0_RESEARCH_SYNC_TOKEN --config wrangler.toml

- name: Sync bundled strategy profiles to KV
if: github.event_name != 'workflow_dispatch' || inputs.sync_strategy_profiles
run: |
Expand Down
9 changes: 9 additions & 0 deletions docs/m0_research_publisher_envelope_contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ run ID 和 artifact ID 都作为 `source_artifact` metadata 显式传给构建
必须是不同的值和不同的最小权限用途:前者只能读取固定 QAR repository 的 Actions run/artifact,
后者只能向 M0 接收端发布封套;不得复用、互相授予或写入运行时/平台配置。

同一个 `M0_RESEARCH_SYNC_TOKEN` 还必须以**同名、同值的独立 secret**配置到已有的
`runtime-strategy-switch` Environment。它只会在控制台 Worker 的部署 workflow 中被写入
Cloudflare 的 `M0_RESEARCH_SYNC_TOKEN` secret binding;该部署 workflow 不读取 QAR artifact token,
而 M0 发布 workflow 也不读取 Cloudflare 凭据。不要在 repository-level 放置这个名字,避免未受
Environment 保护的 fallback。控制台部署会在部署前验证该 secret;缺失时直接失败,不能静默
保留 Cloudflare Worker 中的旧值。轮换时,先只更新 `runtime-strategy-switch` 中的副本,从 `main`
部署并确认 Worker secret 写入成功;再把同一个新值写入 `m0-research-publisher`,最后手动发布
一份已验证的 M0 ledger。

URL、发布 token 和 QAR 读取 token 不会写进封套、`GITHUB_STEP_SUMMARY` 或 workflow 输出。该
workflow 不读取运行时、平台、selector、策略或券商配置;其唯一网络写入是构建器在
`--publish` 明确指定时,对上述研究接收地址发送经过校验的 no-order 封套。
5 changes: 5 additions & 0 deletions python/tests/test_runtime_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,11 @@ def test_strategy_switch_console_deploy_workflow_syncs_bundled_profiles(self):
self.assertIn("secret put STRATEGY_HEALTH_SYNC_TOKEN", workflow)
self.assertIn("RESEARCH_TASK_SYNC_TOKEN", workflow)
self.assertIn("secret put RESEARCH_TASK_SYNC_TOKEN", workflow)
self.assertIn("M0_RESEARCH_SYNC_TOKEN", workflow)
self.assertIn("secret put M0_RESEARCH_SYNC_TOKEN", workflow)
self.assertIn("Verify M0 research-ledger ingress token", workflow)
self.assertIn("M0_RESEARCH_SYNC_TOKEN is required", workflow)
self.assertNotIn("if: env.M0_RESEARCH_SYNC_TOKEN != ''", workflow)
self.assertIn("CLOUDFLARE_WRANGLER_CONFIG_TOML", workflow)
self.assertIn("STRATEGY_SWITCH_CONFIG_KV_NAMESPACE_ID", workflow)
self.assertIn("python/scripts/sync_strategy_switch_page_asset.py", workflow)
Expand Down
3 changes: 2 additions & 1 deletion web/strategy-switch-console/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ wrangler secret put GITHUB_CLIENT_SECRET
wrangler secret put SESSION_SECRET
wrangler secret put RUNTIME_SETTINGS_DISPATCH_TOKEN
wrangler secret put STRATEGY_SWITCH_SYNC_TOKEN # optional; defaults to RUNTIME_SETTINGS_DISPATCH_TOKEN
wrangler secret put M0_RESEARCH_SYNC_TOKEN
wrangler secret put ALLOWED_GITHUB_LOGINS
wrangler secret put ALLOWED_GITHUB_ORGS
wrangler secret put STRATEGY_SWITCH_ADMIN_LOGINS
Expand All @@ -210,7 +211,7 @@ wrangler kv namespace create STRATEGY_SWITCH_CONFIG

Add the returned namespace id to `wrangler.toml`.

For GitHub Actions auto-deploy, configure `STRATEGY_SWITCH_CONFIG_KV_NAMESPACE_ID`, `STRATEGY_SWITCH_CONSOLE_URL`, `STRATEGY_SWITCH_SYNC_TOKEN`, and either `CLOUDFLARE_API_TOKEN` or `CLOUDFLARE_WRANGLER_CONFIG_TOML` in the `runtime-strategy-switch` environment (or reuse `RUNTIME_SETTINGS_GH_TOKEN` only if it matches the Worker sync secret). `CLOUDFLARE_ACCOUNT_ID` is optional when Wrangler can infer it from the token. The workflow deploys the Worker and then syncs the bundled strategy profile catalog into KV so the website is not left with stale profile/plugin metadata.
For GitHub Actions auto-deploy, configure `STRATEGY_SWITCH_CONFIG_KV_NAMESPACE_ID`, `STRATEGY_SWITCH_CONSOLE_URL`, `STRATEGY_SWITCH_SYNC_TOKEN`, `M0_RESEARCH_SYNC_TOKEN`, and either `CLOUDFLARE_API_TOKEN` or `CLOUDFLARE_WRANGLER_CONFIG_TOML` in the `runtime-strategy-switch` environment (or reuse `RUNTIME_SETTINGS_GH_TOKEN` only if it matches the Worker sync secret). `CLOUDFLARE_ACCOUNT_ID` is optional when Wrangler can infer it from the token. `M0_RESEARCH_SYNC_TOKEN` must match the separately protected `m0-research-publisher` environment secret; it is only copied to the Worker binding. A missing M0 token fails the deployment before it can retain a stale Worker secret. The workflow deploys the Worker and then syncs the bundled strategy profile catalog into KV so the website is not left with stale profile/plugin metadata.

Deploy:

Expand Down
3 changes: 2 additions & 1 deletion web/strategy-switch-console/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ wrangler secret put RUNTIME_SETTINGS_DISPATCH_TOKEN
wrangler secret put STRATEGY_SWITCH_SYNC_TOKEN # 可选;默认复用 RUNTIME_SETTINGS_DISPATCH_TOKEN
wrangler secret put STRATEGY_HEALTH_SYNC_TOKEN
wrangler secret put CONTROL_PLANE_SYNC_TOKEN
wrangler secret put M0_RESEARCH_SYNC_TOKEN
wrangler secret put ALLOWED_GITHUB_LOGINS
wrangler secret put ALLOWED_GITHUB_ORGS
wrangler secret put STRATEGY_SWITCH_ADMIN_LOGINS
Expand All @@ -347,7 +348,7 @@ wrangler kv namespace create STRATEGY_SWITCH_CONFIG

然后把返回的 namespace id 加到 `wrangler.toml`。

GitHub Actions 自动部署需要在 `runtime-strategy-switch` environment 配置 `STRATEGY_SWITCH_CONFIG_KV_NAMESPACE_ID`、`STRATEGY_SWITCH_CONSOLE_URL`、`STRATEGY_SWITCH_SYNC_TOKEN`,以及 `CLOUDFLARE_API_TOKEN` 或 `CLOUDFLARE_WRANGLER_CONFIG_TOML` 二选一(只有当 `RUNTIME_SETTINGS_GH_TOKEN` 与 Worker 同步密钥相同时才复用它)。如果 Wrangler 能从 token 推断账号,`CLOUDFLARE_ACCOUNT_ID` 可不配。workflow 会先部署 Worker,再把内置策略 profile 目录同步到 KV,避免网站继续使用旧的 profile/plugin 元数据。
GitHub Actions 自动部署需要在 `runtime-strategy-switch` environment 配置 `STRATEGY_SWITCH_CONFIG_KV_NAMESPACE_ID`、`STRATEGY_SWITCH_CONSOLE_URL`、`STRATEGY_SWITCH_SYNC_TOKEN`、`M0_RESEARCH_SYNC_TOKEN`,以及 `CLOUDFLARE_API_TOKEN` 或 `CLOUDFLARE_WRANGLER_CONFIG_TOML` 二选一(只有当 `RUNTIME_SETTINGS_GH_TOKEN` 与 Worker 同步密钥相同时才复用它)。如果 Wrangler 能从 token 推断账号,`CLOUDFLARE_ACCOUNT_ID` 可不配。`M0_RESEARCH_SYNC_TOKEN` 必须与另一个受保护的 `m0-research-publisher` Environment 中的同名 secret 一致;它只会被复制到 Worker binding。缺少该值时,workflow 会在部署前失败,不能静默保留 Worker 的旧密钥。workflow 会先部署 Worker,再把内置策略 profile 目录同步到 KV,避免网站继续使用旧的 profile/plugin 元数据。

部署:

Expand Down
1 change: 1 addition & 0 deletions web/strategy-switch-console/wrangler.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ workers_dev = true
# - STRATEGY_HEALTH_SYNC_TOKEN # dedicated outbound health snapshot token; never reuse dispatch token
# - CONTROL_PLANE_SYNC_TOKEN # dedicated global dashboard snapshot token; never reuse dispatch token
# - RESEARCH_TASK_SYNC_TOKEN # dedicated immutable research-task source token; never reuse another token
# - M0_RESEARCH_SYNC_TOKEN # dedicated read-only M0 research-ledger ingress token; never reuse another token
# - ALLOWED_GITHUB_LOGINS
# - ALLOWED_GITHUB_ORGS
# - STRATEGY_SWITCH_ADMIN_LOGINS
Expand Down