diff --git a/.github/workflows/deploy-strategy-switch-console.yml b/.github/workflows/deploy-strategy-switch-console.yml index fd9371c7..14e0ec64 100644 --- a/.github/workflows/deploy-strategy-switch-console.yml +++ b/.github/workflows/deploy-strategy-switch-console.yml @@ -1040,7 +1040,25 @@ 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. + # Current reviewed merged main release: keep all receiver checks and live configuration. + # The earlier reviewed main remains an exact historical source in the next block. + if [ "$RELEASE_SOURCE_SHA" = "084ba4281cfff3304cf226ce511a2fc0a6b67b08" ]; then + [ "$GITHUB_REF" = "refs/heads/main" ] && [ "$frontend_mode" = true ] \ + && [ "$SYNC_SECRETS" = false ] && [ "$SYNC_STRATEGY_PROFILES" = false ] \ + && [ "$SKIP_BINANCE_RECEIVER_CHECKS" = false ] || exit 2 + 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="23f94567c2e8b631e8ef035bfea497acef795123" + [ "$(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")" = "5287f259185ed44f3784aa6374cb00412b3c6238" ] || 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 + # Historical reviewed merged main release: same receiver and configuration gates. if [ "$RELEASE_SOURCE_SHA" = "c1b737d6e721eb9fe71a12c613fbb49d3fa51563" ]; then [ "$GITHUB_REF" = "refs/heads/main" ] && [ "$frontend_mode" = true ] \ && [ "$SYNC_SECRETS" = false ] && [ "$SYNC_STRATEGY_PROFILES" = false ] \ @@ -1144,12 +1162,19 @@ 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")" ] \ + reviewed_main="084ba4281cfff3304cf226ce511a2fc0a6b67b08" + historical_reviewed_main="c1b737d6e721eb9fe71a12c613fbb49d3fa51563" + head_sha="$(git rev-parse HEAD)" + if [ "$head_sha" = "$reviewed_main" ] || [ "$head_sha" = "$historical_reviewed_main" ]; then + [ "$GITHUB_REF" = "refs/heads/main" ] || exit 2 + if [ "$head_sha" = "$reviewed_main" ]; then + [ "$(git rev-parse 'HEAD^{tree}')" = "23f94567c2e8b631e8ef035bfea497acef795123" ] || exit 2 + [ "$(git hash-object web/strategy-switch-console/v2_asset_map.js)" = "5287f259185ed44f3784aa6374cb00412b3c6238" ] || exit 2 + else + [ "$(git rev-parse 'HEAD^{tree}')" = "5dcdab977ec72e32f99cd3ef4956cebff90ba107" ] || exit 2 + [ "$(git hash-object web/strategy-switch-console/v2_asset_map.js)" = "b4ef57a6830011f78d0aa0270729e17d05a4d230" ] || exit 2 + fi + [ -z "$(git diff --name-only "$head_sha")" ] \ && [ -z "$(git ls-files --others --exclude-standard)" ] || exit 2 exit 0 fi @@ -1629,7 +1654,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 reviewedMain = process.env.RELEASE_SOURCE_SHA === 'c1b737d6e721eb9fe71a12c613fbb49d3fa51563'; + const reviewedMain = process.env.RELEASE_SOURCE_SHA === '084ba4281cfff3304cf226ce511a2fc0a6b67b08' + || 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'); diff --git a/docs/console-execution-evidence.md b/docs/console-execution-evidence.md index 19e2fed6..50ba93b9 100644 --- a/docs/console-execution-evidence.md +++ b/docs/console-execution-evidence.md @@ -29,10 +29,17 @@ The account and overview cards display the reason for unknown, broker environmen ## 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. +frontend release with receiver checks retained. The current pin is +`084ba4281cfff3304cf226ce511a2fc0a6b67b08` (parent +`395ddd561a16d38ae0d145e5a7e9bb7b60c44ae6`, tree +`23f94567c2e8b631e8ef035bfea497acef795123`, asset map +`5287f259185ed44f3784aa6374cb00412b3c6238`). The earlier reviewed main +`c1b737d6e721eb9fe71a12c613fbb49d3fa51563` remains an exact historical source +under the same gates. 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. This pin does +not enable strategy-profile synchronization or Meridian activation. Publication uses version-pinned inheritance from the active Worker version for every binding, including secrets. Latest-version lineage checks reject concurrent diff --git a/tests/console_deploy_safety_validation.mjs b/tests/console_deploy_safety_validation.mjs index 92edc128..0e04f689 100644 --- a/tests/console_deploy_safety_validation.mjs +++ b/tests/console_deploy_safety_validation.mjs @@ -245,17 +245,17 @@ const fakeGit = `git() { 'fetch --no-tags origin refs/heads/fix/runtime-daily-multi-release-20261030'|'fetch --no-tags origin refs/heads/fix/qrs-runtime-daily-serving-20261030'|'fetch --no-tags origin refs/heads/codex/website-account-settings-reviewed-20261029'|'fetch --no-tags origin refs/heads/codex/website-native-daily-fixed-clock-20261029'|'fetch --no-tags origin refs/heads/codex/website-integrated-candidate-20261029'|'fetch --no-tags origin refs/heads/codex/website-history-cpu-candidate-20261029'|'fetch --no-tags origin refs/heads/codex/website-incomplete-release-candidate-20261029') return 0 ;; 'rev-parse FETCH_HEAD') printf '%s' "$FAKE_FETCH_HEAD" ;; 'rev-parse HEAD') if [ -f "$SELECTED" ]; then printf '%s' "$FAKE_SELECTED_HEAD"; else printf '%s' "$FAKE_CONTROL_HEAD"; fi ;; - 'cat-file -e c1b737d6e721eb9fe71a12c613fbb49d3fa51563^{commit}'|'cat-file -e ${approved}^{commit}'|'cat-file -e ${pr764Source}^{commit}'|'cat-file -e ${ibkrSource}^{commit}') return "$FAKE_OBJECT_EXIT" ;; + 'cat-file -e 084ba4281cfff3304cf226ce511a2fc0a6b67b08^{commit}'|'cat-file -e c1b737d6e721eb9fe71a12c613fbb49d3fa51563^{commit}'|'cat-file -e ${approved}^{commit}'|'cat-file -e ${pr764Source}^{commit}'|'cat-file -e ${ibkrSource}^{commit}') return "$FAKE_OBJECT_EXIT" ;; 'cat-file -e ${frontend}^{commit}') return "$FAKE_FRONTEND_OBJECT_EXIT" ;; - 'merge-base --is-ancestor c1b737d6e721eb9fe71a12c613fbb49d3fa51563 ${control}'|'merge-base --is-ancestor ${approved} ${control}'|'merge-base --is-ancestor ${pr764Source} ${control}') return "$FAKE_ANCESTRY_EXIT" ;; + 'merge-base --is-ancestor 084ba4281cfff3304cf226ce511a2fc0a6b67b08 ${control}'|'merge-base --is-ancestor c1b737d6e721eb9fe71a12c613fbb49d3fa51563 ${control}'|'merge-base --is-ancestor ${approved} ${control}'|'merge-base --is-ancestor ${pr764Source} ${control}') return "$FAKE_ANCESTRY_EXIT" ;; 'merge-base --is-ancestor ${integratedSource} ${cpuSource}') return "$FAKE_ANCESTRY_EXIT" ;; 'merge-base --is-ancestor ${frontend} ${control}') return "$FAKE_FRONTEND_ANCESTRY_EXIT" ;; - 'rev-parse c1b737d6e721eb9fe71a12c613fbb49d3fa51563^{tree}'|'rev-parse ${runtimeDailyMultiSource}^{tree}'|'rev-parse ${runtimeDailySource}^{tree}'|'rev-parse ${approved}^{tree}'|'rev-parse ${pr764Source}^{tree}'|'rev-parse ${ibkrSource}^{tree}'|'rev-parse ${integratedSource}^{tree}'|'rev-parse ${cpuSource}^{tree}'|'rev-parse ${settingsSource}^{tree}'|'rev-parse ${dailySource}^{tree}'|'rev-parse ${statusSource}^{tree}'|'rev-parse HEAD^{tree}') printf '%s' "$FAKE_TREE" ;; + 'rev-parse 084ba4281cfff3304cf226ce511a2fc0a6b67b08^{tree}'|'rev-parse c1b737d6e721eb9fe71a12c613fbb49d3fa51563^{tree}'|'rev-parse ${runtimeDailyMultiSource}^{tree}'|'rev-parse ${runtimeDailySource}^{tree}'|'rev-parse ${approved}^{tree}'|'rev-parse ${pr764Source}^{tree}'|'rev-parse ${ibkrSource}^{tree}'|'rev-parse ${integratedSource}^{tree}'|'rev-parse ${cpuSource}^{tree}'|'rev-parse ${settingsSource}^{tree}'|'rev-parse ${dailySource}^{tree}'|'rev-parse ${statusSource}^{tree}'|'rev-parse HEAD^{tree}') printf '%s' "$FAKE_TREE" ;; 'rev-parse ${runtimeDailyMultiSource}^'|'rev-parse ${runtimeDailySource}^'|'rev-parse ${ibkrSource}^'|'rev-parse ${integratedSource}^'|'rev-parse ${settingsSource}^'|'rev-parse ${dailySource}^'|'rev-parse ${statusSource}^') printf '%s' "$FAKE_PARENT" ;; 'rev-parse ${frontend}^{tree}') printf '%s' "$FAKE_FRONTEND_TREE" ;; - 'rev-parse c1b737d6e721eb9fe71a12c613fbb49d3fa51563:${assetPath}'|'rev-parse ${runtimeDailyMultiSource}:${assetPath}'|'rev-parse ${runtimeDailySource}:${assetPath}'|'rev-parse ${pr764Source}:${assetPath}'|'rev-parse ${ibkrSource}:${assetPath}'|'rev-parse ${integratedSource}:${assetPath}'|'rev-parse ${cpuSource}:${assetPath}'|'rev-parse ${settingsSource}:${assetPath}'|'rev-parse ${dailySource}:${assetPath}'|'rev-parse ${statusSource}:${assetPath}') printf '%s' "$FAKE_PR764_BLOB" ;; + 'rev-parse 084ba4281cfff3304cf226ce511a2fc0a6b67b08:${assetPath}'|'rev-parse c1b737d6e721eb9fe71a12c613fbb49d3fa51563:${assetPath}'|'rev-parse ${runtimeDailyMultiSource}:${assetPath}'|'rev-parse ${runtimeDailySource}:${assetPath}'|'rev-parse ${pr764Source}:${assetPath}'|'rev-parse ${ibkrSource}:${assetPath}'|'rev-parse ${integratedSource}:${assetPath}'|'rev-parse ${cpuSource}:${assetPath}'|'rev-parse ${settingsSource}:${assetPath}'|'rev-parse ${dailySource}:${assetPath}'|'rev-parse ${statusSource}:${assetPath}') printf '%s' "$FAKE_PR764_BLOB" ;; 'rev-parse ${frontend}:${assetPath}') printf '%s' "$FAKE_FRONTEND_BLOB" ;; - '-c advice.detachedHead=false checkout --detach c1b737d6e721eb9fe71a12c613fbb49d3fa51563'|'-c advice.detachedHead=false checkout --detach ${runtimeDailyMultiSource}'|'-c advice.detachedHead=false checkout --detach ${runtimeDailySource}'|'-c advice.detachedHead=false checkout --detach ${approved}'|'-c advice.detachedHead=false checkout --detach ${pr764Source}'|'-c advice.detachedHead=false checkout --detach ${ibkrSource}'|'-c advice.detachedHead=false checkout --detach ${integratedSource}'|'-c advice.detachedHead=false checkout --detach ${cpuSource}'|'-c advice.detachedHead=false checkout --detach ${statusSource}'|'-c advice.detachedHead=false checkout --detach ${settingsSource}'|'-c advice.detachedHead=false checkout --detach ${dailySource}') touch "$SELECTED" ;; + '-c advice.detachedHead=false checkout --detach 084ba4281cfff3304cf226ce511a2fc0a6b67b08'|'-c advice.detachedHead=false checkout --detach c1b737d6e721eb9fe71a12c613fbb49d3fa51563'|'-c advice.detachedHead=false checkout --detach ${runtimeDailyMultiSource}'|'-c advice.detachedHead=false checkout --detach ${runtimeDailySource}'|'-c advice.detachedHead=false checkout --detach ${approved}'|'-c advice.detachedHead=false checkout --detach ${pr764Source}'|'-c advice.detachedHead=false checkout --detach ${ibkrSource}'|'-c advice.detachedHead=false checkout --detach ${integratedSource}'|'-c advice.detachedHead=false checkout --detach ${cpuSource}'|'-c advice.detachedHead=false checkout --detach ${statusSource}'|'-c advice.detachedHead=false checkout --detach ${settingsSource}'|'-c advice.detachedHead=false checkout --detach ${dailySource}') touch "$SELECTED" ;; *) return 91 ;; esac };\n`; @@ -296,6 +296,33 @@ for (const delta of [{FAKE_CONTROL_HEAD:"b".repeat(40)}, {FAKE_OBJECT_EXIT:"1"}, } assert.equal(sourceCase({...mergedEnv,FAKE_SELECTED_HEAD:"b".repeat(40)}, false).selected, true); +// The current reviewed main is the merged decision-inbox source. The previous pin stays valid. +const inboxSource = "084ba4281cfff3304cf226ce511a2fc0a6b67b08"; +const inboxParent = "395ddd561a16d38ae0d145e5a7e9bb7b60c44ae6"; +const inboxTree = "23f94567c2e8b631e8ef035bfea497acef795123"; +const inboxBlob = "5287f259185ed44f3784aa6374cb00412b3c6238"; +{ + const identity = spawnSync("git", ["rev-parse", `${inboxSource}^{commit}`, `${inboxSource}^`, `${inboxSource}^{tree}`, `${inboxSource}:${assetPath}`], {cwd: new URL("..", import.meta.url), encoding:"utf8"}); + assert.equal(identity.status, 0); + assert.deepEqual(identity.stdout.trim().split("\n"), [inboxSource, inboxParent, inboxTree, inboxBlob]); + const ancestry = spawnSync("git", ["merge-base", "--is-ancestor", inboxSource, "HEAD"], {cwd: new URL("..", import.meta.url)}); + assert.equal(ancestry.status, 0, "current reviewed main must be adopted in this checkout"); +} +const inboxEnv = { RELEASE_SOURCE_SHA: inboxSource, RELEASE_FRONTEND_ASSETS: "true", + SKIP_BINANCE_RECEIVER_CHECKS: "false", FAKE_SELECTED_HEAD: inboxSource, + FAKE_TREE: inboxTree, FAKE_PR764_BLOB: inboxBlob }; +assert.equal(sourceCase(inboxEnv, true).selected, true); +for (const delta of [{RELEASE_FRONTEND_ASSETS:"false"}, {SYNC_SECRETS:"true"}, + {SYNC_STRATEGY_PROFILES:"true"}, {SKIP_BINANCE_RECEIVER_CHECKS:"true"}, + {GITHUB_REF:"refs/heads/other"}, {IBKR_CANDIDATE_RESUME:"verify"}, {EXTERNAL_FLOW_ENABLE:"true"}]) { + assert.deepEqual(sourceCase({...inboxEnv,...delta}, false).calls, []); +} +for (const delta of [{FAKE_CONTROL_HEAD:"b".repeat(40)}, {FAKE_OBJECT_EXIT:"1"}, + {FAKE_ANCESTRY_EXIT:"1"}, {FAKE_TREE:"b".repeat(40)}, {FAKE_PR764_BLOB:"b".repeat(40)}]) { + assert.equal(sourceCase({...inboxEnv,...delta}, false).selected, false); +} +assert.equal(sourceCase({...inboxEnv,FAKE_SELECTED_HEAD:"b".repeat(40)}, false).selected, true); + const validSource = sourceCase({}, true); assert.equal(validSource.selected, true); assert.ok(validSource.calls.indexOf(`merge-base --is-ancestor ${approved} ${control}`) < validSource.calls.findIndex(line => line.includes("checkout --detach"))); @@ -451,7 +478,7 @@ const fakeOverlayGit = `git() { 'show ${ibkrSource}:${assetPath}') cat "$FROZEN_MAP" ;; hash-object*) command git "$@" ;; 'diff --name-only ${approved}') printf '%s' "$FAKE_DIFF" ;; - 'diff --name-only ${mergedSource}'|'diff --name-only ${ibkrSource}'|'diff --name-only ${cpuSource}'|'diff --name-only ${settingsSource}'|'diff --name-only ${dailySource}'|'diff --name-only ${statusSource}') printf '%s' "$FAKE_DIFF" ;; + 'diff --name-only ${inboxSource}'|'diff --name-only ${mergedSource}'|'diff --name-only ${ibkrSource}'|'diff --name-only ${cpuSource}'|'diff --name-only ${settingsSource}'|'diff --name-only ${dailySource}'|'diff --name-only ${statusSource}') printf '%s' "$FAKE_DIFF" ;; 'ls-files --others --exclude-standard') printf '%s' "$FAKE_UNTRACKED" ;; *) return 91 ;; esac @@ -494,6 +521,29 @@ function overlayCase(delta = {}, expected = true, bytes = reviewedMap) { assert.notEqual(spawnSync("bash", ["-c", fakeOverlayGit + overlayShell], {cwd:temp,env}).status, 0); } finally {rmSync(temp, {recursive:true,force:true});} } +// The current reviewed main must preserve its own map and reject tampering. +{ + const assetResult = spawnSync("git", ["show", `${inboxSource}:${assetPath}`], {maxBuffer:16*1024*1024}); + assert.equal(assetResult.status, 0); + const asset = assetResult.stdout; + assert.equal(spawnSync("git", ["hash-object", "--stdin"], {input:asset,encoding:"utf8",maxBuffer:16*1024*1024}).stdout.trim(), inboxBlob); + const temp = mkdtempSync(join(tmpdir(), "console-inbox-overlay-")); + try { + const dest = join(temp, assetPath); + mkdirSync(join(temp, "web/strategy-switch-console"), {recursive:true}); + const env = {PATH:process.env.PATH, GITHUB_REF:"refs/heads/main", FAKE_HEAD:inboxSource, + FAKE_TREE:inboxTree, FAKE_DIFF:"", FAKE_UNTRACKED:""}; + for (const delta of [{}, {FAKE_DIFF:"fake-file"}, {FAKE_UNTRACKED:"fake-file"}, + {FAKE_TREE:"a".repeat(40)}, {GITHUB_REF:"refs/heads/other"}]) { + writeFileSync(dest, asset); + const result = spawnSync("bash", ["-c", fakeOverlayGit + overlayShell], {cwd:temp,env:{...env,...delta}}); + assert.equal(result.status === 0, Object.keys(delta).length === 0); + assert.deepEqual(readFileSync(dest), asset, "never overlay an older asset"); + } + writeFileSync(dest, "fake modified asset"); + assert.notEqual(spawnSync("bash", ["-c", fakeOverlayGit + overlayShell], {cwd:temp,env}).status, 0); + } finally {rmSync(temp, {recursive:true,force:true});} +} // The CPU candidate carries its own exact generated map, never the older overlay. { const fixedAsset = spawnSync("git", ["show", `${cpuSource}:${assetPath}`], { cwd: new URL("..", import.meta.url) }); @@ -705,7 +755,7 @@ async function releaseCase({pr764=false,ibkrDaily=false,activeOverride=null,inhe releaseCases++;return {calls,stdout,stderr}; } // Exact integrated candidate: explicit inheritance, verified module, one non-forced activation. -async function integratedReleaseCase({ reviewedMain=false, lineage=null, settings=false, daily=false, statusCandidate=false, cpu=false, active=null, latest=null, moduleContent=syntheticBundle.toString("base64"), uploadedTag=undefined, postTag=runtime.migration_tag, flow=false, oldFlag=null, drift=false } = {}, expected=true) { +async function integratedReleaseCase({ reviewedMain=false, reviewedMainSource="c1b737d6e721eb9fe71a12c613fbb49d3fa51563", lineage=null, settings=false, daily=false, statusCandidate=false, cpu=false, active=null, latest=null, moduleContent=syntheticBundle.toString("base64"), uploadedTag=undefined, postTag=runtime.migration_tag, flow=false, oldFlag=null, drift=false } = {}, expected=true) { const calls=[], stdout=[], stderr=[], prior=settings?"7ffe9227-686a-48ad-baa9-72665969d918":daily?"14f0c9c2-09f9-40e9-bfbe-17165f499495":statusCandidate?"175ba768-484a-4fe6-9cea-e5a101bc1618":cpu?"90a0c8e9-b5ad-447a-998f-5d585ec28063":"600ec84d-a804-4ede-8d1d-0a34819ce46a"; active ??= prior; latest ??= active; const responses=responseSequence(false,active); @@ -726,7 +776,7 @@ async function integratedReleaseCase({ reviewedMain=false, lineage=null, setting else postResources.script_runtime.migration_tag=postTag; responses.push(wrap({id:newVersion,resources:postResources})); const process={env:{GITHUB_REF:"refs/heads/main",CLOUDFLARE_ACCOUNT_ID:"a".repeat(32),CLOUDFLARE_API_TOKEN:privateRelease, - RUNNER_TEMP:"/synthetic",WORKER_DIR:"web/strategy-switch-console",RELEASE_SOURCE_SHA:reviewedMain?"c1b737d6e721eb9fe71a12c613fbb49d3fa51563":flow?"1174db8e143f2a3689ca8e86cd547dc08461ff29":settings?settingsSource:daily?dailySource:statusCandidate?statusSource:cpu?cpuSource:integratedSource,...(flow?{EXTERNAL_FLOW_ENABLE:"true",PLATFORM_CONTROL_EXPECTED_VERSION:prior}:{})},exitCode:0}; + RUNNER_TEMP:"/synthetic",WORKER_DIR:"web/strategy-switch-console",RELEASE_SOURCE_SHA:reviewedMain?reviewedMainSource:flow?"1174db8e143f2a3689ca8e86cd547dc08461ff29":settings?settingsSource:daily?dailySource:statusCandidate?statusSource:cpu?cpuSource:integratedSource,...(flow?{EXTERNAL_FLOW_ENABLE:"true",PLATFORM_CONTROL_EXPECTED_VERSION:prior}:{})},exitCode:0}; await runRelease(process,async(url,options)=>{calls.push({url,options}); const response=responses[calls.length-1]; assert.ok(response,"no retry"); return response instanceof Response ? response : new Response(JSON.stringify(response),{headers:{"content-type":"application/json"}});}, {log:x=>stdout.push(x),error:x=>stderr.push(x)},async path=>path.endsWith("v2_asset_map.js")?syntheticAssetMap:syntheticBundle, @@ -747,6 +797,12 @@ await integratedReleaseCase({reviewedMain:true,lineage:priorVersion},false); await integratedReleaseCase({reviewedMain:true,moduleContent:Buffer.from("wrong").toString("base64")},false); await integratedReleaseCase({reviewedMain:true,uploadedTag:"wrong-tag"},false); await integratedReleaseCase({reviewedMain:true,postTag:null},false); +await integratedReleaseCase({reviewedMain:true,reviewedMainSource:inboxSource}); +await integratedReleaseCase({reviewedMain:true,reviewedMainSource:inboxSource,latest:priorVersion},false); +await integratedReleaseCase({reviewedMain:true,reviewedMainSource:inboxSource,lineage:priorVersion},false); +await integratedReleaseCase({reviewedMain:true,reviewedMainSource:inboxSource,moduleContent:Buffer.from("wrong").toString("base64")},false); +await integratedReleaseCase({reviewedMain:true,reviewedMainSource:inboxSource,uploadedTag:"wrong-tag"},false); +await integratedReleaseCase({reviewedMain:true,reviewedMainSource:inboxSource,postTag:null},false); await integratedReleaseCase(); await integratedReleaseCase({flow:true}); await integratedReleaseCase({flow:true,oldFlag:{name:"CONSOLE_EXTERNAL_FLOW_ENABLED",type:"plain_text",text:"false"}});