fix(release): gate release identity, model/updater admission, and platform trust - #1126
seonghobae wants to merge 310 commits into
Conversation
📝 WalkthroughWalkthrough릴리스 정체성 검증 스크립트를 추가했습니다. Changes릴리스 정체성 검증
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant ReleaseIdentityJob
participant VerifyReleaseIdentity
participant ReleaseMetadata
participant BuildAndPublish
ReleaseIdentityJob->>VerifyReleaseIdentity: verify_release_identity.py 실행
VerifyReleaseIdentity->>ReleaseMetadata: VERSION 및 JSON 버전 읽기
ReleaseMetadata-->>VerifyReleaseIdentity: 버전 메타데이터 반환
VerifyReleaseIdentity-->>ReleaseIdentityJob: 검증 결과 반환
ReleaseIdentityJob->>BuildAndPublish: 검증 성공 후 빌드 및 게시 허용
Merge Risk: ⚪ Minimal · up to The release guard now stops builds and publication when version metadata or the release tag disagrees. No actionable merge-blocking risk remains after normal checks and review. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| "--expected-identity", | ||
| os.environ.get("BANDSCOPE_WINDOWS_PUBLISHER_SUBJECT", ""), |
There was a problem hiding this comment.
🔴 Tagged releases cannot produce artifacts
Tag builds pass an empty BANDSCOPE_WINDOWS_PUBLISHER_SUBJECT into verify_tag_platform_trust; no workflow job defines either required signer identity. Every platform packager fails before upload, so publication never runs.
Prompt for agents
The tag-triggered jobs in .github/workflows/build-baseline.yml invoke package_desktop_artifact.py without defining BANDSCOPE_WINDOWS_PUBLISHER_SUBJECT or BANDSCOPE_APPLE_TEAM_ID. They also contain no signing or notarization setup, so the newly mandatory platform trust verifier rejects every tagged build before artifact upload. Add the required release configuration and platform signing/notarization flow to the owning build jobs, expose the expected identities explicitly, and add workflow-level tests proving real tag jobs receive these values. Keep pull-request and branch builds unsigned if intended, while ensuring tagged builds can create verifiable artifacts.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Validated on current implementation head d33bb96ec1794c02492fea3e8cd5e36280709eae: this remains a real blocker. The verifier is correctly fail-closed, but the tag jobs do not yet possess an organization-approved Windows signing identity/certificate/timestamp authority or Apple Team ID/Developer ID/notarization authority. The PR title/body now state this explicitly and the thread remains unresolved; no signer identity, secret, timestamp service, or Apple authority will be fabricated in repository source. Once those external authorities are provisioned, the existing #960 owner must wire them into tag-only build steps and prove signed/notarized artifacts before upload.
There was a problem hiding this comment.
Revalidated on exact current head ae98559c83939b75ae02cadcbd05894883cc0a37 against protected develop@314ddeae7b775a4957594b599358c8255617eb2e. Current ordinary descendants retain the Windows/macOS platform-trust gate while adding a Distribution HTTP dependency-admission repair: root Cargo features can no longer re-enable reqwest features through reqwest/gzip, a renamed dependency such as distribution_http/brotli, or Cargo's weak dependency?/feature syntax outside the direct reviewed {rustls} declaration. Traceability explicitly limits that claim and still requires Cargo-owned resolved-feature evidence once the real HTTP graph exists. None of this supplies or alters native signer authority. The finding remains a real external prerequisite: repository source still has no organization-approved Windows publisher/certificate/private key/timestamp authority or Apple Team ID/Developer ID/notarization authority. #1126 remains Draft and this thread stays unresolved. No signer identity, credential, predecessor-head check, or review receipt is fabricated or transferred.
|
Exact-head verification update for
The upstream Demucs primary evidence was re-read directly: Antoine Défossez states that the model weights are not covered by the MIT license and are provided only for scientific purposes (facebookresearch/demucs#327 comment 1134828611). The checked-in |
|
Exact-head verification refresh for |
|
Exact-head verification refresh for |
|
@coderabbitai review Please review exact head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== checked out commit =='
git rev-parse HEAD
printf '%s\n' '== requested commit present =='
git cat-file -t b535013d9f381b91c9498ab469f374739192c081
printf '%s\n' '== diff name/status from parent =='
git diff --name-status b535013d9f381b91c9498ab469f374739192c081^ b535013d9f381b91c9498ab469f374739192c081
printf '%s\n' '== changed-file diff stat =='
git diff --stat b535013d9f381b91c9498ab469f374739192c081^ b535013d9f381b91c9498ab469f374739192c081
printf '%s\n' '== candidate updater-related files =='
fd -HI -t f . | rg -i '(^|/)(cargo\.toml|cargo\.lock|tauri\.conf(\.json)?|.*updat.*|.*release.*|.*admission.*|.*policy.*)$' | sort
printf '%s\n' '== relevant symbol references =='
rg -n -i -C 3 '(updater|tauri-plugin-updater|UpdaterExt|check\s*\(|download_and_install|install\s*\(|blocked)' \
-g 'Cargo.toml' -g 'Cargo.lock' -g '*.rs' -g '*.py' -g '*.sh' -g '*.yml' -g '*.yaml' -g '*.json' -g '*test*' . || trueLength of output: 79358 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== verifier outline =='
ast-grep outline scripts/checks/verify_release_updater_policy.py --items all --view expanded
printf '%s\n' '== runtime wiring test outline =='
ast-grep outline services/analysis-engine/tests/test_release_updater_runtime_wiring.py --items all --view expanded
printf '%s\n' '== updater policy test outline =='
ast-grep outline services/analysis-engine/tests/test_release_updater_policy.py --items all --view expanded
printf '%s\n' '== verifier: dependency, lock, lexical stripping, runtime, entrypoint =='
sed -n '217,490p' scripts/checks/verify_release_updater_policy.py
printf '%s\n' '== runtime wiring tests =='
cat -n services/analysis-engine/tests/test_release_updater_runtime_wiring.py
printf '%s\n' '== supporting updater policy tests =='
sed -n '25,280p' services/analysis-engine/tests/test_release_updater_policy.py
printf '%s\n' '== actual desktop manifest, lock entry, main entrypoint =='
cat -n apps/desktop/src-tauri/Cargo.toml
rg -n -A12 -B3 'name = "tauri-plugin-updater"' apps/desktop/src-tauri/Cargo.lock || true
cat -n apps/desktop/src-tauri/src/main.rs
printf '%s\n' '== PR commit sequence for related files =='
git log --oneline --reverse -- scripts/checks/verify_release_updater_policy.py services/analysis-engine/tests/test_release_updater_runtime_wiring.py services/analysis-engine/tests/test_release_updater_policy.py docs/traceability/updater-release-admission.md
printf '%s\n' '== PR range changes for related files =='
git diff --name-status 314ddeae7b775a4957594b599358c8255617eb2e..HEAD -- scripts/checks/verify_release_updater_policy.py services/analysis-engine/tests/test_release_updater_runtime_wiring.py services/analysis-engine/tests/test_release_updater_policy.py docs/traceability/updater-release-admission.md apps/desktop/src-tauri/Cargo.toml apps/desktop/src-tauri/Cargo.lock apps/desktop/src-tauri/src/main.rs release/updater-policy.json .github/workflows/release.ymlLength of output: 70853 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== numbered verifier sections =='
nl -ba scripts/checks/verify_release_updater_policy.py | sed -n '217,390p'
printf '%s\n' '== lock package dependency examples =='
rg -n -A18 -B2 '^name = "bandscope-desktop"$|^name = "tauri-plugin-updater"$' apps/desktop/src-tauri/Cargo.lock || true
printf '%s\n' '== all desktop package declarations in lockfile =='
rg -n -A25 -B2 'name = "bandscope-desktop"' apps/desktop/src-tauri/Cargo.lock || true
printf '%s\n' '== release workflow gate and artifact/publication dependencies =='
rg -n -C5 '(verify_release_identity|verify_release_updater_policy|release-identity|GITHUB_REF_TYPE|publish|package)' .github/workflows/release.yml .github/workflows/build-baseline.yml scripts/harness/quickcheck.sh scripts/release/build_tauri_bundle_with_retry.sh scripts/release/package_desktop_artifact.py scripts/release/select_release_assets.py || true
printf '%s\n' '== traceability document =='
cat -n docs/traceability/updater-release-admission.md
printf '%s\n' '== tests for lexical resistance and lock binding =='
rg -n -C3 '(comment|string|raw|cfg|unreachable|unused|orphan|lock.*depend|manifest.*version|package\s*=)' services/analysis-engine/tests/test_release_updater_policy.py services/analysis-engine/tests/test_release_updater_runtime_wiring.py scripts/checks/verify_release_updater_policy.py || trueLength of output: 61417
I found two admission-boundary defects. I treated the checked-in
I did not execute repository code or tests in the inspection sandbox. You are interacting with an AI system. |
Advances #960 and the Distribution/update portion of #1180 on the existing release owner. This Draft owns exact release identity, updater/model admission, native platform trust, release receipts/publication attestation, anti-replay/rollback policy, provisional updater metadata, transport/staging/recovery, and Distribution-owned highest-seen state. It consumes #1181 as a legal prerequisite and does not manufacture model rights, signer authority, updater signing authority, or remote-metadata authenticity.
Exact current identity
develop@314ddeae7b775a4957594b599358c8255617eb2e.fix/trusted-release-version-identity-960.528ba04cbaf2228bd819e3313f06f849ab027fac.develop; current semantic diff is 81 files.Single-writer boundary
#1116 remains Open / Draft and the canonical owner for
docs/product-technical-gap-baseline.md; #1126 does not write that file. Distribution-specific decisions stay in #1126-owned code,ARCHITECTURE.md,docs/traceability/*, and live #960/#1180 authority.Current hosted RED → repair
Fresh hosted evidence on predecessor
ae98559c83939b75ae02cadcbd05894883cc0a37exposed two repository-owned failures rather than runner noise.cifailed the Distribution download test job on Ubuntu, Windows, and macOS becausecargo +stable test --manifest-path apps/desktop/distribution-download/Cargo.toml --locked --all-targetsruns with-D missing-docs, while the three integration-test crates had no crate-level documentation.da5c690c70d2ba3ebde625a0e6d4eed43cb80998adds purpose-specific crate docs topath_replacement_cleanup.rs,sealed_reader.rs, andstaged_artifact.rswithout changing runtime or test behavior.sbomfailedverify_supply_chain.pybecausebuild-baseline.ymlgenerated and revalidatedrelease-artifacts.txt, then copied it into the publication list, while the protected supply-chain contract requires the canonicalrelease-assets.txtto be generated and revalidated directly.2cd906c8b1a868bb52d41744a5a92946163e87d7makes the strict selector producerelease-assets.txt, revalidates that same list before publication, separately rechecks deterministiclatest.json, and only then appendslatest.jsonbefore the exact mapfile/upload path. The supply-chain checker was not weakened.FileNotFoundErrorno-op in atomic updater-manifest cleanup.528ba04cbaf2228bd819e3313f06f849ab027facpreserves cleanup behavior and records why not-found is expected after successfulos.replaceconsumes the staging pathname; the finding thread is resolved.These repairs are ordinary descendants. Exact-current-head hosted results still govern; predecessor failures and successes do not transfer.
Retained reqwest feature-forwarding repair
The HTTP dependency gate requires the direct reqwest declaration to use
default-features = falseand exactly{rustls}. Cargo root features can otherwise reactivate dependency features throughdependency/featureanddependency?/featurebecause Cargo unifies enabled features.ed5be008b379f5f07c4325801f1bbba9676fcad1covers directreqwest/gzipand renameddistribution_http/brotliforwarding.bc56faad9bd2582cd6bae4f0b4df43dafc64d9a8discovers unconditional/target-scoped dependency keys resolving to packagereqwestand rejects root-feature forwarding through those keys.0f74972089c4240dbcb7e47d65a8e116bbf099cfcovers Cargo weakdistribution_http?/zstdforwarding.ae98559c83939b75ae02cadcbd05894883cc0a37records the decision and claim boundary indocs/traceability/distribution-http-feature-forwarding.md.This does not claim that a future transitive package cannot enable additional reqwest features. Once the production client exists, release acceptance must add Cargo-owned resolved-feature evidence such as the equivalent of
cargo tree -e features -i reqwestalongside a genuinely resolved standalone lock.Retained Distribution trust boundary
verify_release_identity.pypins repository release projections to bounded regular non-link descriptors, rejects duplicate/non-standard JSON semantics, requires stable double reads/final path-to-descriptor identity, and bounds stableMAJOR.MINOR.PATCHto Rustu64.distribution-runtimestrict-parses the bounded four-target updater document and returns only provisional release/URL/resource/signature-envelope evidence. It cannot mutate freshness state.distribution-transportowns direct-200/explicit-one-hop-302 admission, exact effective URL, full-candidate attempt identity, response content-coding rejection, bounded staging handoff, candidate/artifact evidence continuity through the exactSealedTransportArtifactdescriptor, and bounded diagnostic redaction. It still owns no socket/client/TLS implementation.distribution-downloadowns bounded chunk/content-length/size admission, exclusive staging/lease/restart cleanup, sync/seal, descriptor-bound reader input, Unix identity-checked unlink and Windows deferred stale-file reclamation. Staging remains unverified scratch.distribution-stateserializes cooperating-process highest-seen authority. Unix uses single-link append/sync semantics; Windows uses synchronized replacement snapshots so a pre-existing hard-link alias is not mutated in place on stable Rust.distribution-coreremains the deterministic post-authentication release/anti-replay/rollback decision owner.Trust order remains: bounded provisional metadata + explicit attempt-bound transport admission + same-object sealed evidence continuity → independently authenticated release identity → updater artifact cryptographic signature verification → exact sealed-descriptor digest/size binding → explicit verified-artifact promotion → anti-replay decision + durable highest-seen mutation.
The HTTP dependency gate remains fail closed. A future direct runtime reqwest declaration must stay in the reviewed stable 0.13.x line, use a canonical three-component manifest floor,
default-features = false, direct features exactly{rustls}, no root feature forwarding through its dependency key, and canonical crates.io provenance throughout the standalone external lock graph. Workspace inheritance, alternate sources, pre-release substitution, and unreviewed transport features remain rejected.Hosted evidence still required
Only exact
528ba04cbaf2228bd819e3313f06f849ab027facresults count now. #1220 remains Open until exact-current-head stable Windowsgate / ci / distribution-owned / windows-2025reaches terminal GREEN for the highest-seen hard-link snapshot contracts. A qualifying non-author current-head formal approval is also required before merge. No self-approval, protection bypass, gate weakening, or predecessor-evidence transfer.Release authority and external blockers
release/model-artifact-policy.jsonremains blocked pending commercial model rights (#1181/#770).release/updater-policy.jsonremains blocked because no organization-approved updater public key/production endpoint exists.The signer-authority review finding remains valid while tagged production packaging has no organization-approved Windows publisher/certificate/private-key/timestamp authority and no Apple Developer ID/Team ID/notarization authority. Repository source must not invent those identities or secrets. Keep Draft until provisioned authority and tag-only jobs prove real signed/notarized artifacts.
Remaining repository-owned scope
Next implement the production HTTP adapter only together with a genuinely Cargo-resolved BandScope-owned standalone lock graph that stays in the reviewed stable reqwest 0.13.x line, uses canonical external package provenance, selects unaffected rustls, and demonstrates the actual resolved reqwest feature set with Cargo-owned evidence. The client must explicitly select rustls, disable implicit redirects, transparent decoding and proxy inheritance, pass exact status/effective URL/Location/Content-Encoding into
distribution-transport, stream bounded chunks throughdistribution-download, and redact opaque redirect/signature values from ordinary diagnostics.Then continue: real DNS/TLS/network error, cancellation, disk-full and captive-portal evidence → canonical metadata authentication → cryptographic updater-signature/digest/authenticated-size verification over the exact
SealedTransportArtifactdescriptor → explicit verified-artifact promotion → only then highest-seen state wiring → packaged multi-process/process-kill/restart/power-loss and last-known-good rollback acceptance.Merge gate
Keep Draft and unmerged while exact-head hosted evidence is non-terminal/failing, qualifying independent current-head approval is absent, valid findings remain, or real signer/updater/model authority is unprovisioned. No force-push, destructive rebase, self-approval, bypass, gate weakening, fake authority, or predecessor-evidence transfer.