Skip to content

fix(release): require canonical lowercase source SHA - #443

Merged
seonghobae merged 18 commits into
mainfrom
fix/release-evidence-lowercase-sha
Aug 21, 2026
Merged

fix(release): require canonical lowercase source SHA#443
seonghobae merged 18 commits into
mainfrom
fix/release-evidence-lowercase-sha

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Scope

Tighten buyer-verifiable release/deployment evidence so commit and digest identities are accepted only in their canonical byte/string representation rather than being case-folded or whitespace-normalized before persistence.

Test-first repairs

Release source SHA

  • RED 5f4c34dc93abf56244e604e5459014d9875e1359: uppercase 40-hex SHA with a matching archive name reaches the real release-evidence entrypoint and must fail closed.
  • Candidate f95d748821948b51de27314cb6b3772f1f1dd509: require lowercase 40-hex.
  • RED 98dcf9739a1293b0a467daf8c1e2a9651e0ef23f: whitespace-wrapped environment SHA with a canonical archive filename demonstrates that requireString() can otherwise normalize authority before validation.
  • Candidate 1bd0e36b29a923d86e41caf5cfadda76d42d2d87: compare the validated SHA with its original environment value and reject normalization.

Deployment source SHA and evidence digests

  • RED 45f13ba31387983749f408244dd70728a600378c: uppercase deployment/release-evidence SHA pair must fail rather than be accepted and lowercased in the buyer receipt.
  • Candidate a9a4377b0c3aeb7ec7ca2a360111c03ec808a4a1: require lowercase deployment SHA.
  • RED 56357923bcf11d446de22e73ffe9633073037b8e: uppercase external SHA-256 evidence digest must fail rather than be silently lowercased.
  • Candidate 5d0802ecead4071acfbbbf9534c0fcd5f4aae414: require lowercase digest and stop case-folding it.
  • RED 2a2a21381a85250358ceb1792556d7d1fc363d30: whitespace-wrapped deployment SHA or release-evidence digest must fail rather than be trimmed into authority.
  • Current candidate 141d48b831c353aa99f0736f81945c6f35d801db: require exact original-string equality for deployment SHA and SHA-256 digest; persist the already-canonical SHA without normalization.

Existing SBOM, stable-file, timestamp, tag/ref, immutable-release, smoke/KPI, deployment-target and attestation contracts are unchanged.

Current identity and fresh evidence

  • protected base: 80925420bb14c673510e0ed206257befa55da7a9
  • exact head: 141d48b831c353aa99f0736f81945c6f35d801db
  • changed paths: scripts/release-evidence.mjs, test/release-evidence.test.ts, scripts/deployment-evidence.mjs, test/deployment-evidence.test.ts
  • application CI 32501920201: queued
  • reviewer-ci 32501920200: queued
  • central Security Scan 32501920295: queued

Merge boundary

Draft. Do not merge until application CI, reviewer-ci and the eligible central Security Scan are terminal-success on this unchanged exact head, review/thread state is freshly clean, and protected base plus current central scanner authority are revalidated. Pending/predecessor evidence is non-passing.

Summary by CodeRabbit

  • 버그 수정

    • 배포 및 릴리스 증거 검증이 소문자 형식의 SHA와 다이제스트만 허용하도록 강화되었습니다.
    • 공백이 포함되거나 대소문자가 다른 식별자, 잘못된 날짜와 타임스탬프가 올바르게 거부됩니다.
    • 검증된 커밋 SHA가 원래의 정확한 형식으로 출력됩니다.
  • 테스트

    • 잘못된 SHA, 다이제스트, 날짜 및 타임스탬프에 대한 검증 사례가 추가되었습니다.

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b67092f1-2703-4ec8-8bae-2650f9a3f938

📥 Commits

Reviewing files that changed from the base of the PR and between 469d4a6 and dcc7d55.

📒 Files selected for processing (6)
  • scripts/deployment-evidence.mjs
  • scripts/lib/acquisition-deployment-evidence.mjs
  • scripts/release-evidence.mjs
  • test/acquisition-deployment-evidence.test.ts
  • test/deployment-evidence.test.ts
  • test/release-evidence.test.ts

📝 Walkthrough

Walkthrough

배포 및 릴리스 증거 검증이 소문자 canonical SHA와 digest를 요구하도록 변경되었습니다. 입력의 공백과 대문자를 더 이상 정규화하지 않습니다. timestamp 검증은 ISO 형식과 실제 달력 날짜를 확인합니다. 관련 실패 테스트가 추가되었습니다.

Changes

Canonical 증거 검증

Layer / File(s) Summary
배포 증거 형식 및 날짜 검증
scripts/deployment-evidence.mjs, test/deployment-evidence.test.ts
SHA와 digest는 소문자 hexadecimal 형식만 허용합니다. timestamp는 정규 ISO 형식, 유한한 파싱 결과, 윤년과 월별 날짜 범위를 검증합니다.
배포 증거 canonical 일치 검증
scripts/lib/acquisition-deployment-evidence.mjs, test/acquisition-deployment-evidence.test.ts
commit SHA와 digest를 trim 또는 소문자 변환 없이 검증합니다. 영수증 값과 배포 값은 canonical 원문이 정확히 일치해야 합니다.
릴리스 commit SHA 선택 및 검증
scripts/release-evidence.mjs, test/release-evidence.test.ts
NOEMA_RELEASE_COMMIT_SHA를 우선 사용하고, 없으면 GITHUB_SHA를 사용합니다. 선택된 원문 값은 40자리 소문자 hexadecimal 형식이어야 합니다. 대문자와 선행 공백 입력의 실패 동작을 테스트합니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

✨ 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/release-evidence-lowercase-sha

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.

@seonghobae
seonghobae marked this pull request as ready for review August 21, 2026 19:35
@seonghobae
seonghobae merged commit 046c104 into main Aug 21, 2026
15 of 17 checks passed
@seonghobae
seonghobae deleted the fix/release-evidence-lowercase-sha branch August 21, 2026 19:36

@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 1 potential issue.

Open in Devin Review

Comment on lines 47 to 63
function requireTimestamp(value, label) {
const timestamp = requireString(value, label);
if (Number.isNaN(Date.parse(timestamp))) {
fail(`${label} must be an ISO-compatible timestamp`);
const calendar = timestamp.match(isoCalendarPrefixPattern);
const timestampMilliseconds = Date.parse(timestamp);
if (timestamp !== value || !calendar || !Number.isFinite(timestampMilliseconds)) {
fail(`${label} must be a canonical ISO-compatible timestamp with a valid calendar date`);
}
const year = Number(calendar[1]);
const month = Number(calendar[2]);
const day = Number(calendar[3]);
const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
const daysPerMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (month < 1 || month > 12 || day < 1 || day > daysPerMonth[month - 1]) {
fail(`${label} must be a canonical ISO-compatible timestamp with a valid calendar date`);
}
return timestamp;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Timestamp validation broadened beyond commit-SHA scope

requireTimestamp (scripts/deployment-evidence.mjs:47-63) now rejects any timestamp lacking the YYYY-MM-DDT prefix, differing from its trimmed form, or naming an impossible calendar date. It runs on externally sourced values: the Wrangler deploy timestamp (scripts/deployment-evidence.mjs:237) and Cloudflare created_on (scripts/deployment-evidence.mjs:256). Both emit RFC3339/ISO today, so no regression is expected, but a space-separated or offset variant would now fail closed.

Open in Devin Review

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

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