Skip to content

fix(release): gate release identity, model/updater admission, and platform trust - #1126

Draft
seonghobae wants to merge 87 commits into
developfrom
fix/trusted-release-version-identity-960
Draft

fix(release): gate release identity, model/updater admission, and platform trust#1126
seonghobae wants to merge 87 commits into
developfrom
fix/trusted-release-version-identity-960

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Advances #960 and the Distribution/update portion of #1180 on the existing release owner. This PR owns exact release identity, commercial model-artifact admission/evidence/inventory binding, native platform trust, exact package/updater receipts, fail-closed updater admission, static updater-manifest publication, hosted release re-verification, GitHub immutable-release attestation, updater security metadata, and the Rust-first anti-replay/rollback decision core. It consumes #1181 as a legal prerequisite; it does not decide or manufacture model rights or signing authority.

Exact current identity

  • Protected target: develop@314ddeae7b775a4957594b599358c8255617eb2e.
  • Branch: fix/trusted-release-version-identity-960.
  • Exact current head: 9df9e61592c006f7bfb94008c94427ef40a1bc0c.
  • Fresh protected-base comparison: ahead 87 / behind 0; merge base is exact protected develop.
  • Current semantic diff is 35 files. The earlier stale-tree restack defect was repaired non-force at 788e8bd82285e5380f498cf8ec425ab1d64e26d6; protected workflow/security delta is not being rolled back.
  • Current-head checks/reviews must be re-fetched after every movement. Predecessor GREEN/review evidence never transfers.

Release/update authority already implemented

verify_release_identity.py composes version, model and updater policy gates. Tag packaging runs that preflight before release artifact creation. Windows/macOS tag packaging additionally requires native signature/notarization trust evidence; unsigned PR/develop builds remain validation evidence only.

release/model-artifact-policy.json remains blocked for upstream demucs/htdemucs / 955717e8-8726e21a.th because commercial pretrained-weight rights are not established. Future admission requires exact model bytes/full SHA-256, rights/provenance/loader-policy evidence bytes and one matching supplemental-inventory entry. #1181 owns the legal decision and #770 owns rights-cleared real-audio scientific acceptance.

release/updater-policy.json also remains blocked: no organization-approved updater public key or production endpoint exists in repository authority. Future admission must agree across bounded policy JSON, Tauri config, locked Cargo dependency graph and executable updater initialization. No placeholder key, endpoint or signing secret is fabricated.

Tagged packaging emits target-qualified release receipts binding version/tag, full source commit, platform/architecture/triple, installer checksums and exact Tauri updater bundle/signature bytes. select_release_assets.py re-admits the four target graphs after Actions artifact transfer. build_updater_manifest.py builds deterministic exact-tag static updater JSON; hosted draft and published assets are downloaded again and byte-compared, followed by gh release verify and gh release verify-asset against GitHub immutable-release attestation.

Updater security metadata

Fresh review against #960 found that the Tauri static manifest carried exact URL/signature content but did not itself identify the receipt-authorized updater bundle digest or minimumSupportedVersion. Tauri exposes the original response through Update.raw_json, so future replay/compatibility decisions need exact authenticated evidence in that response.

  • RED 57ced89e61529a984010c8b351fef54cac543b6f requires exact full source commit, policy version floor and per-target updater bundle size/full SHA-256.
  • Fix 21ee4ff52789659cbf70db33c24d9e925fb8d4f1 adds deterministic top-level bandscope metadata derived only from admitted receipts and fixed release/updater-policy.json.
  • 209f58e7e647df836be50fa31c90a751829cca38 documents the Tauri/TUF claim boundary.
  • 857e1e9324e29f896d5bad6216631bd723fd1f65 rejects duplicate policy authority and non-canonical version floors.

This metadata is not a second signing mechanism: Tauri .sig remains artifact authenticity authority, while GitHub immutable-release attestation remains hosted publication evidence.

Rust anti-replay / rollback core

The next repository-owned #960 gap was that replay/rollback policy existed only as a requirement. RED 4467a9e80b3fa7e7e7a95cb1ff7606749606b3d0 requires repository CI to execute a standalone locked Rust Distribution suite. 1339cfd44aef17743a770449651ee9a233baf4e5 and 0fbb2e8a5396e5b5b123704537e0c4b9719a92e3 establish the dependency-free apps/desktop/distribution-core; causal fix 42fdeed9a1ddf57d807889e61dee864b931b62a2 implements the decision contract. d80a4775f5be719b39eab85a1e78094b8f43c160 makes compiler warnings and missing public rustdoc hard failures.

The core now fails closed on malformed stable versions, malformed source/digest identity, invalid or mismatched targets, clients below the automatic-update compatibility floor, candidate rollback, metadata older than locally highest-seen authenticated evidence, and same-version source/digest equivocation. A previously authenticated highest-seen release can be reoffered without being treated as newly fresh. Known-good rollback is allowed only when the target is actually older and can read the current on-disk project schema.

The core is intentionally network/filesystem/Tauri/installer independent. Highest-seen state belongs to Distribution and must be persisted after authenticated metadata admission even when installation is deferred; Project Persistence remains owner only of project bytes/schema truth. Positive production runtime wiring still waits for real updater authority rather than manufacturing a key/endpoint.

cd25fab5f40f6379f5b2c25017510f4b6f3378cf doctors updater traceability around this boundary, a0a9eecc977375cf540a3bc04cce82292c6a583c registers the bounded context in ARCHITECTURE.md, and 9df9e61592c006f7bfb94008c94427ef40a1bc0c establishes the previously missing docs/product-technical-gap-baseline.md with buyer-visible release/audio/UI gaps.

Current verification

Exact current-head hosted workflows exist for 9df9e61592c006f7bfb94008c94427ef40a1bc0c; build-baseline, ci, sbom, Security Scan, SAST Semgrep, and CodeQL PR are non-terminal at the latest read. Predecessor results are not transferred and no exact-head GREEN is claimed.

Fresh formal review inventory has no qualifying non-author APPROVED. The remaining unresolved signer-authority finding is still valid: repository source cannot supply organization-approved Windows publisher/certificate/private-key/timestamp authority, Apple Developer ID/Team ID/notarization credentials, or the approved updater signing/public-key + production endpoint authority. Keep Draft; do not fabricate these values or self-approve.

Remaining scope

This PR does not claim #960, #1180 or #1181 complete. Repository-owned runtime work still includes authenticated Update.raw_json admission into the Rust core, crash-safe highest-seen Distribution state/reload, offline-safe update checks, truncated/partial/disk-full/cancel/first-launch recovery, last-known-good installer retention and packaged wrong-key/signature/digest/replay/target acceptance on Windows/macOS. Positive production signature acceptance needs external approved updater authority.

Security Notes

  • Attack surface: release/update metadata, policy/config/runtime wiring, model/evidence/inventory bytes, installer/updater bytes and signatures, signing/notarization, artifact transfer, immutable publication, locally persisted freshness state and recovery decisions.
  • Trust boundary: Distribution owns commercial release/update admission/freshness/publication evidence; Active Player, MIR and Project Persistence do not duplicate release authority.
  • Policy/evidence inputs are fixed-path and bounded; artifact bytes are stable-descriptor hashed and fail closed on missing, linked, malformed, drifting or digest-mismatched state.
  • The Rust decision core accepts only already-authenticated release identity and performs no network/install/project writes.
  • Current model and updater authority remain blocked. No source statement claims legal rights, signer provisioning, production updater-key validity, TUF-equivalent metadata security or packaged rollback acceptance.

Merge gate

Keep Draft and unmerged while exact-head hosted evidence is non-terminal, qualifying independent current-head approval is absent, valid findings remain, or actual release prerequisites are unprovisioned. Never self-approve, bypass protection, weaken a gate, fabricate rights/signing/updater authority, or transfer predecessor GREEN.

devin-ai-integration[bot]

This comment was marked as resolved.

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

릴리스 정체성 검증 스크립트를 추가했습니다. VERSION, package.json, tauri.conf.json, 릴리스 태그의 일치를 확인합니다. 검증 작업을 빌드와 게시 작업의 선행 조건으로 연결하고, quickcheck 및 테스트에 검증 단계를 추가했습니다.

Changes

릴리스 정체성 검증

Layer / File(s) Summary
릴리스 정체성 검증기
scripts/checks/verify_release_identity.py
VERSION을 기준으로 JSON 버전과 선택적 릴리스 태그를 검증합니다. 오류 발생 시 실패 코드를 반환합니다.
빌드 및 게시 게이트 연결
.github/workflows/build-baseline.yml, scripts/harness/quickcheck.sh
release-identity 작업을 추가했습니다. Windows 및 macOS 빌드와 immutable release 게시 작업이 검증 완료 후 실행되도록 설정했습니다. quickcheck에도 검증 명령을 추가했습니다.
검증 테스트 및 픽스처
services/analysis-engine/tests/test_release_version_identity.py
정상 버전, 메타데이터 불일치, 잘못된 태그, 다중 줄 VERSION, 워크플로 의존성을 검증합니다.

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: 검증 성공 후 빌드 및 게시 허용
Loading

Merge Risk: ⚪ Minimal · up to b0d5e

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)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 13 functions across 3 files. (1 skipped: 1…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 릴리스 정체성 검증 게이트라는 주요 변경 사항을 정확히 나타냅니다. 다만 model/updater admissionplatform trust는 변경 요약에 명확히 포함되지 않습니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/trusted-release-version-identity-960

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

coderabbitai[bot]

This comment was marked as resolved.

@seonghobae seonghobae added documentation Improvements or additions to documentation priority: high High-priority or P1 work status: needs-review Open pull request requiring current-head review or checks type: bug Defect or incorrect behavior labels Sep 2, 2026 — with ChatGPT Codex Connector
devin-ai-integration[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

Devin Review

Comment on lines +128 to +129
"--expected-identity",
os.environ.get("BANDSCOPE_WINDOWS_PUBLISHER_SUBJECT", ""),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 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.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revalidated after the non-force protected-base restack. Exact current head is b0bfbd2333f8f0a8eb2f8058f74cf985331aaebe, with develop@889d782e88b4df28dcbb4ae3cfd6d99ef85d9844 as an ancestor and behind_by=0; the seven release-owned files are unchanged. This finding remains valid for the same external prerequisite: no repository-owned source can supply an approved Windows publisher/certificate/timestamp authority or Apple Team ID/Developer ID/notarization credential. The PR is Draft and this thread stays unresolved. No predecessor-head check/review receipt transfers.

Comment thread scripts/checks/verify_release_platform_trust.py
@seonghobae seonghobae changed the title fix(release): fail closed on version identity drift fix(release): gate release identity and platform trust Sep 2, 2026
@seonghobae
seonghobae marked this pull request as draft September 4, 2026 04:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation priority: high High-priority or P1 work status: draft Draft pull request type: bug Defect or incorrect behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant