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
41 changes: 34 additions & 7 deletions .github/workflows/deploy-strategy-switch-console.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,23 @@ jobs:
if [ "$(git rev-parse HEAD)" != "$RELEASE_SOURCE_SHA" ] || [ "$(git rev-parse 'HEAD^{tree}')" != "$expected_tree" ]; then exit 2; fi
exit 0
fi
# Reviewed merged main release: keep all receiver checks and live configuration.
if [ "$RELEASE_SOURCE_SHA" = "c1b737d6e721eb9fe71a12c613fbb49d3fa51563" ]; then
[ "$GITHUB_REF" = "refs/heads/main" ] && [ "$frontend_mode" = true ] \
&& [ "$SYNC_SECRETS" = false ] && [ "$SYNC_STRATEGY_PROFILES" = false ] \
&& [ "$SKIP_BINANCE_RECEIVER_CHECKS" = false ] || exit 2
Comment thread
Pigbibi marked this conversation as resolved.
Resolved
control_sha="$(git rev-parse HEAD)"
[ "$control_sha" = "$GITHUB_SHA" ] || exit 2
git cat-file -e "${RELEASE_SOURCE_SHA}^{commit}"
git merge-base --is-ancestor "$RELEASE_SOURCE_SHA" "$control_sha"
expected_tree="5dcdab977ec72e32f99cd3ef4956cebff90ba107"
[ "$(git rev-parse "${RELEASE_SOURCE_SHA}^{tree}")" = "$expected_tree" ] || exit 2
[ "$(git rev-parse "${RELEASE_SOURCE_SHA}:web/strategy-switch-console/v2_asset_map.js")" = "b4ef57a6830011f78d0aa0270729e17d05a4d230" ] || exit 2
git -c advice.detachedHead=false checkout --detach "$RELEASE_SOURCE_SHA"
[ "$(git rev-parse HEAD)" = "$RELEASE_SOURCE_SHA" ] \
&& [ "$(git rev-parse 'HEAD^{tree}')" = "$expected_tree" ] || exit 2
exit 0
fi
if [ "$frontend_mode" = "true" ]; then
if [ "$GITHUB_REF" != "refs/heads/main" ] || [ "$RELEASE_SOURCE_SHA" != "9722414a99298cd7079a88eb8e3e703d50e986de" ] \
|| [ "$SYNC_SECRETS" != "false" ] || [ "$SYNC_STRATEGY_PROFILES" != "false" ] \
Expand Down Expand Up @@ -1127,6 +1144,15 @@ jobs:
if: inputs.release_frontend_assets && inputs.source_sha != '20dad166be317dd0d57e492ed06e56dfb82b7aef' && !inputs.render_and_compare_only
run: |
set -euo pipefail
reviewed_main="c1b737d6e721eb9fe71a12c613fbb49d3fa51563"
if [ "$(git rev-parse HEAD)" = "$reviewed_main" ]; then
[ "$GITHUB_REF" = "refs/heads/main" ] \
&& [ "$(git rev-parse 'HEAD^{tree}')" = "5dcdab977ec72e32f99cd3ef4956cebff90ba107" ] || exit 2
[ "$(git hash-object web/strategy-switch-console/v2_asset_map.js)" = "b4ef57a6830011f78d0aa0270729e17d05a4d230" ] || exit 2
[ -z "$(git diff --name-only "$reviewed_main")" ] \
&& [ -z "$(git ls-files --others --exclude-standard)" ] || exit 2
exit 0
fi
integrated="0dd2c0b3e73e890bc2c39ab0bae0eeb48c58470a"
cpu_candidate="974354b98ebe0cd55931baa03034d887d4fac560"
status_candidate="68e3d4b69e706e2100f860c473ec657e9baf05ba"
Expand Down Expand Up @@ -1603,7 +1629,8 @@ jobs:
const statusCandidate = process.env.RELEASE_SOURCE_SHA === '68e3d4b69e706e2100f860c473ec657e9baf05ba';
const cpuCandidate = process.env.RELEASE_SOURCE_SHA === '974354b98ebe0cd55931baa03034d887d4fac560';
const integrated = controlRuntimeCandidate || controlAdminCandidate || historyCandidate || declarationCandidate || returnsCandidate || settingsCandidate || dailyCandidate || statusCandidate || cpuCandidate || process.env.RELEASE_SOURCE_SHA === '0dd2c0b3e73e890bc2c39ab0bae0eeb48c58470a';
const betaRelease = ibkrDaily || integrated;
const reviewedMain = process.env.RELEASE_SOURCE_SHA === 'c1b737d6e721eb9fe71a12c613fbb49d3fa51563';
const betaRelease = ibkrDaily || integrated || reviewedMain;
const flowMode = process.env.EXTERNAL_FLOW_ENABLE === 'true';
if (flowMode && process.env.RELEASE_SOURCE_SHA !== '1174db8e143f2a3689ca8e86cd547dc08461ff29') fail('external_flow_source_invalid');
const resume = process.env.IBKR_CANDIDATE_RESUME ?? 'off';
Expand Down Expand Up @@ -1810,7 +1837,7 @@ jobs:
// version; the older script-version API only supports latest.
const metadata = { main_module: 'worker.js', bindings: old.bindings.map(b => ({ type: 'inherit', name: b.name, ...(betaRelease ? {version_id: prior} : {}) })),
compatibility_date: old.script_runtime.compatibility_date, usage_model: old.script_runtime.usage_model,
annotations: { 'workers/message': controlRuntimeCandidate ? 'Reviewed runtime control candidate; retained configuration' : controlAdminCandidate ? 'Reviewed runtime control admin candidate 5db5153e; retained configuration' : historyCandidate ? 'Reviewed history return candidate 21829dda; retained configuration' : declarationCandidate ? 'Reviewed account declaration candidate 411356d3; retained configuration' : returnsCandidate ? 'Reviewed account returns candidate b051154d; retained configuration' : settingsCandidate ? 'Reviewed settings candidate 3782a3e8; retained configuration' : dailyCandidate ? 'Reviewed daily candidate 4b6cbedc; retained configuration' : statusCandidate ? 'Reviewed status candidate 68e3d4b6; retained configuration' : cpuCandidate ? 'Reviewed CPU candidate 974354b9; retained configuration' : integrated ? 'Reviewed integrated candidate 0dd2c0b3; retained configuration' : pr764 ? 'Reviewed PR764 20dad166 full source; retained configuration' : ibkrDaily ? 'Reviewed IBKR daily candidate aaa46a81; retained configuration' : 'Reviewed website backend 9722414a with fixed frontend 96363633; retained bindings' } };
annotations: { 'workers/message': reviewedMain ? 'Reviewed merged main frontend; retained configuration' : controlRuntimeCandidate ? 'Reviewed runtime control candidate; retained configuration' : controlAdminCandidate ? 'Reviewed runtime control admin candidate 5db5153e; retained configuration' : historyCandidate ? 'Reviewed history return candidate 21829dda; retained configuration' : declarationCandidate ? 'Reviewed account declaration candidate 411356d3; retained configuration' : returnsCandidate ? 'Reviewed account returns candidate b051154d; retained configuration' : settingsCandidate ? 'Reviewed settings candidate 3782a3e8; retained configuration' : dailyCandidate ? 'Reviewed daily candidate 4b6cbedc; retained configuration' : statusCandidate ? 'Reviewed status candidate 68e3d4b6; retained configuration' : cpuCandidate ? 'Reviewed CPU candidate 974354b9; retained configuration' : integrated ? 'Reviewed integrated candidate 0dd2c0b3; retained configuration' : pr764 ? 'Reviewed PR764 20dad166 full source; retained configuration' : ibkrDaily ? 'Reviewed IBKR daily candidate aaa46a81; retained configuration' : 'Reviewed website backend 9722414a with fixed frontend 96363633; retained bindings' } };
if (flowMode) {
metadata.bindings = metadata.bindings.filter(binding => binding.name !== 'CONSOLE_EXTERNAL_FLOW_ENABLED');
metadata.bindings.push({ name: 'CONSOLE_EXTERNAL_FLOW_ENABLED', type: 'plain_text', text: 'true' });
Expand All @@ -1835,7 +1862,7 @@ jobs:
} else {
uploaded = '2b097d2e-ffb5-4f08-af3b-9cc1d4b9e9ee';
}
if (resume !== 'off' || integrated) {
if (resume !== 'off' || integrated || reviewedMain) {
stage = 'candidate_module';
const candidate = await request(`/versions/${uploaded}?include=modules`, 'GET', undefined, true);
if (candidate?.id !== uploaded) fail('candidate_id_mismatch');
Expand All @@ -1862,7 +1889,7 @@ jobs:
desired.bindings.push({ name: 'CONSOLE_EXTERNAL_FLOW_ENABLED', type: 'plain_text', text: 'true' });
}
const configBefore = configHash(desired), configUploaded = configHash(next);
if (resume !== 'off' || integrated) {
if (resume !== 'off' || integrated || reviewedMain) {
const oldTag = old.script_runtime.migration_tag, newTag = next.script_runtime.migration_tag;
if (typeof oldTag !== 'string' || !oldTag || (newTag !== undefined && newTag !== oldTag)) fail('migration_tag_mismatch');
const normalized = structuredClone(next); normalized.script_runtime.migration_tag = oldTag;
Expand Down Expand Up @@ -1891,7 +1918,7 @@ jobs:
} else {
stage = 'activate'; deployAttempted = true;
const deployment = await request('/deployments?force=false', 'POST', JSON.stringify({ strategy: 'percentage',
versions: [{ version_id: uploaded, percentage: 100 }], annotations: { 'workers/message': controlRuntimeCandidate ? 'Reviewed runtime control candidate; retained configuration' : controlAdminCandidate ? 'Reviewed runtime control admin candidate 5db5153e; retained configuration' : historyCandidate ? 'Reviewed history return candidate 21829dda; retained configuration' : declarationCandidate ? 'Reviewed account declaration candidate 411356d3; retained configuration' : returnsCandidate ? 'Reviewed account returns candidate b051154d; retained configuration' : settingsCandidate ? 'Reviewed settings candidate 3782a3e8; retained configuration' : dailyCandidate ? 'Reviewed daily candidate 4b6cbedc; retained configuration' : statusCandidate ? 'Reviewed status candidate 68e3d4b6; retained configuration' : cpuCandidate ? 'Reviewed CPU candidate 974354b9; retained configuration' : integrated ? 'Reviewed integrated candidate 0dd2c0b3; retained configuration' : pr764 ? 'Reviewed PR764 full source; retained configuration' : ibkrDaily ? 'Reviewed IBKR daily candidate aaa46a81; retained configuration' : 'Reviewed website backend 9722414a and frontend 96363633; retained configuration' } }));
versions: [{ version_id: uploaded, percentage: 100 }], annotations: { 'workers/message': reviewedMain ? 'Reviewed merged main frontend; retained configuration' : controlRuntimeCandidate ? 'Reviewed runtime control candidate; retained configuration' : controlAdminCandidate ? 'Reviewed runtime control admin candidate 5db5153e; retained configuration' : historyCandidate ? 'Reviewed history return candidate 21829dda; retained configuration' : declarationCandidate ? 'Reviewed account declaration candidate 411356d3; retained configuration' : returnsCandidate ? 'Reviewed account returns candidate b051154d; retained configuration' : settingsCandidate ? 'Reviewed settings candidate 3782a3e8; retained configuration' : dailyCandidate ? 'Reviewed daily candidate 4b6cbedc; retained configuration' : statusCandidate ? 'Reviewed status candidate 68e3d4b6; retained configuration' : cpuCandidate ? 'Reviewed CPU candidate 974354b9; retained configuration' : integrated ? 'Reviewed integrated candidate 0dd2c0b3; retained configuration' : pr764 ? 'Reviewed PR764 full source; retained configuration' : ibkrDaily ? 'Reviewed IBKR daily candidate aaa46a81; retained configuration' : 'Reviewed website backend 9722414a and frontend 96363633; retained configuration' } }));
if (!object(deployment) || !Object.hasOwn(deployment, 'id')) fail('missing_id');
if (!isUuid(deployment.id)) fail('invalid_id');
const deploymentId = deployment.id;
Expand All @@ -1906,14 +1933,14 @@ jobs:
if (deployment.versions[0]?.percentage !== 100) fail('percentage_mismatch');
}
stage = 'readback'; await active(deploymentId, uploaded);
if (pr764 || integrated || resume !== 'off') {
if (pr764 || integrated || reviewedMain || resume !== 'off') {
stage = 'post_release_configuration';
const configAfter = configHash(resources(await request(`/versions/${uploaded}`), uploaded));
if (configAfter !== configBefore) fail('post_release_configuration_hash_mismatch');
// Version metadata hides secret values. Hash all comparable bindings/runtime/
// handlers/placement, never code etag or provider bookkeeping. No KV writes.
if (controlRuntimeCandidate) console.log(JSON.stringify({ status: 'integrated_configuration_verified', bindings_equal: true, runtime_equal: true, secret_values_read: false }));
else console.log(JSON.stringify({ status: integrated ? 'integrated_configuration_verified' : resume !== 'off' ? 'ibkr_candidate_configuration_verified' : 'pr764_configuration_verified', config_before_sha256: configBefore,
else console.log(JSON.stringify({ status: reviewedMain ? 'reviewed_main_configuration_verified' : integrated ? 'integrated_configuration_verified' : resume !== 'off' ? 'ibkr_candidate_configuration_verified' : 'pr764_configuration_verified', config_before_sha256: configBefore,
config_uploaded_sha256: configUploaded, config_after_sha256: configAfter, secret_values_read: false }));
}
if (controlRuntimeCandidate) console.log(JSON.stringify({ status: 'frontend_release_verified', matched: true,
Expand Down
19 changes: 19 additions & 0 deletions docs/console-execution-evidence.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,22 @@ The account and overview cards display the reason for unknown, broker environmen
页面展示未知原因、券商环境、配置来源与检查时间。确认配置仅表示已读到明确配置,不能证明当前生效、真实运行或成交。此变更不授予执行权限。

未获准的会话读取 `/api/config`,可能得到 HTTP 200 和 `accountOptions=null`;这是账户资料不可见,不能当作账户目录为空。

## Reviewed main frontend release source

The manual console deployment entry accepts the pinned, reviewed merged main
frontend release with receiver checks retained. The selector verifies the exact
commit, its ancestry in the workflow control revision, its tree and its embedded
asset map before checking out the source. The build must reproduce that map and
leave no tracked or untracked changes; the legacy frontend overlay is not applied.

Publication uses version-pinned inheritance from the active Worker version for
every binding, including secrets. Latest-version lineage checks reject concurrent
uploads; module and configuration readbacks must match before activation.

This mode requires `release_frontend_assets=true`, `sync_secrets=false`,
`sync_strategy_profiles=false`, `skip_binance_receiver_checks=false`,
`external_flow_enable=false` and `ibkr_candidate_resume=off`. Existing job gates
exclude backend-only, rollback, private-release and read-only modes. An arbitrary
main commit is not an accepted release source. Deployment still requires separate
scoped authorization; accepting a source does not grant deployment authority.
Loading
Loading