Skip to content

feat(release): verify an npm candidate before dispatching the publish - #359

Merged
ictechgy merged 1 commit into
mainfrom
feat/npm-candidate-verifier
Sep 1, 2026
Merged

feat(release): verify an npm candidate before dispatching the publish#359
ictechgy merged 1 commit into
mainfrom
feat/npm-candidate-verifier

Conversation

@ictechgy

@ictechgy ictechgy commented Sep 1, 2026

Copy link
Copy Markdown
Owner

npm-publish.yml 은 게시 직전에 후보를 검증하지만, 그 시점의 실패는 이미 워크플로를 한 번 태운 뒤다. 같은 증거를 더 이른 곳으로 옮긴다 — 실수 비용이 "재실행" 이지 "불변으로 게시된 버전" 이 아니게 된다.

무엇을 하나

scripts/verify_npm_candidate.py 는 내려받은 후보 하나(artifact) 또는 그것을 만든 Actions 실행(run)을 게시하려는 신원과 대조한다.

  • tarball 다이제스트를 다시 계산
  • 포장된 package.json 의 이름/버전 결속
  • 루트의 정확한 Receipt 의존을 옆에 실린 Receipt 자산과 대조
  • 후보 매니페스트가 정확한 커밋을 가리키는지 요구
  • run 모드는 성공한 main 후보 실행도 함께 요구

이번 세션의 0.11.0~0.12.3 배포에서 이 검증을 매번 손으로 했다 — 해시 재계산, Receipt 동일성 대조, 아티팩트 매니페스트 확인. 그 절차를 스크립트로 옮긴다.

실측한 검출력

0.12.3 의 실제 후보로 확인했다:

정상 입력:      npm candidate artifact verification: OK
틀린 해시:      candidate package binding mismatch
틀린 버전:      candidate package binding mismatch
틀린 커밋:      candidate manifest identity mismatch
틀린 Receipt:   candidate Receipt exact-asset binding mismatch

네 가지 오입력을 모두, 각각 다른 사유로 거부한다. 통과가 거짓 통과가 아니다.

승격 워크플로는 되살리지 않았다

이 스크립트는 미커밋 상태로 있던 npm 승격 묶음에서 왔지만, 검증기만 가져왔다.

runbook 은 npm-promote.yml 부재를 명시적 설계 결정으로 문서화한다:

There is no .github/workflows/npm-promote.yml, npm dist-tag add, or long-lived npm write token. The bypass-2FA granular-token deprecation therefore does not affect this publication path; OIDC authenticates each direct publish.

승격을 되살리면 2027-01 에 만료되는 bypass-2FA 토큰 의존이 돌아온다. 이 검증기는 승격과 무관하며(코드에 승격/release-state 참조가 없음) 현재의 OIDC 직접 게시 경로에 그대로 쓴다.

가져오지 않은 것: npm-promote.yml, release/release-state.json 과 스키마, verify_release_state.py, npm-publish.yml 재작성, test_workflows.py 의 승격 테스트.

증거

검증기 테스트 3건 · 보호 표면/인벤토리 게이트 14건 통과. 런북에 사용법과 거부 사유를 문서화했다. 새 파일 두 개를 provider-free 지원 경로로 선언했다.

npm-publish.yml 은 게시 직전에 후보를 검증하지만, 그 시점의 실패는 이미 워크플로를
한 번 태운 뒤다. 같은 증거를 더 이른 곳으로 옮긴다. 실수 비용이 "재실행" 이지
"불변으로 게시된 버전" 이 아니게 된다.

scripts/verify_npm_candidate.py 는 내려받은 후보 하나 또는 그것을 만든 Actions
실행을 게시하려는 신원과 대조한다. tarball 다이제스트를 다시 계산하고, 포장된
package.json 의 이름/버전을 결속하며, 루트의 정확한 Receipt 의존을 옆에 실린
Receipt 자산과 맞춰보고, 후보 매니페스트가 정확한 커밋을 가리키는지 요구한다.
run 모드는 성공한 main 후보 실행도 함께 요구한다.

이번 세션의 0.11.0~0.12.3 배포에서 이 검증을 매번 손으로 했다 - 해시 재계산,
Receipt 동일성 대조, 아티팩트 매니페스트 확인. 그 절차를 스크립트로 옮긴다.

실측으로 검출력을 확인했다. 0.12.3 의 실제 후보에 대해 통과하고, 네 가지 오입력을
각각 다른 사유로 거부한다: 틀린 해시와 틀린 버전은 package binding mismatch,
틀린 커밋은 manifest identity mismatch, 틀린 Receipt 버전은 Receipt exact-asset
binding mismatch.

승격 워크플로는 되살리지 않는다. runbook 이 npm-promote.yml 부재를 명시적 설계
결정으로 문서화하고 있고, 되살리면 2027-01 에 만료되는 bypass-2FA 토큰 의존이
돌아온다. 이 검증기는 승격과 무관하며 현재의 OIDC 직접 게시 경로에 그대로 쓴다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YZWGDQsVTLjsBogUSrmnzH
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 2d9cdc78-8556-4b7a-9d88-09e61131595f


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.

@ictechgy
ictechgy merged commit 911f74f into main Sep 1, 2026
6 checks passed
@ictechgy
ictechgy deleted the feat/npm-candidate-verifier branch September 1, 2026 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant