-
Notifications
You must be signed in to change notification settings - Fork 95
feat: Add X-Integrity HTTP header for unpkg files #833
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. |
Co-authored-by: fengmk2 <[email protected]>
Co-authored-by: fengmk2 <[email protected]>
Pull request summary
|
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughAdds multi-algorithm SRI (sha256/sha384/sha512) to integrity calculation, surfaces parsed SRI in controller responses and HTTP headers, stores combined SRI string in service, documents SRI support, and introduces comprehensive tests for calculation, controller behavior, and integration parsing/formatting. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant C as Caller
participant PU as PackageUtil.calculateIntegrity
participant FS as File/Data Source
rect #eef6ff
note over C,PU: Multi-algorithm integrity calculation
C->>PU: calculateIntegrity(contentOrFile)
alt input is file path
PU->>FS: Read file bytes
else input is Uint8Array
PU->>PU: Use provided bytes
end
PU->>PU: Hash bytes (sha256, sha384, sha512, sha1)
PU->>PU: Build sri.{sha256, sha384, sha512, combined}
PU-->>C: { integrity, shasum, sri }
end
sequenceDiagram
autonumber
participant Client
participant Ctl as PackageVersionFileController
participant Svc as PackageVersionFileService
participant Store as Storage
rect #f3fff0
note over Client,Ctl: Raw file fetch with SRI headers
Client->>Ctl: GET /raw/:pkg/:ver/:path
Ctl->>Svc: fetch file metadata and content
Svc->>Store: Read file
Store-->>Svc: Content + dist.integrity
Svc-->>Ctl: File + integrity (combined SRI stored)
Ctl->>Ctl: parseSRIFromIntegrity(integrity)
alt SRI present
Ctl-->>Client: 200 OK + Content<br/>Headers: X-SRI-SHA256/384/512, X-SRI-Integrity
else
Ctl-->>Client: 200 OK + Content (no SRI headers)
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Poem
Pre-merge checks❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
Note Free review on us!CodeRabbit is offering free reviews until Wed Oct 08 2025 to showcase some of the refinements we've made. Comment |
Co-authored-by: fengmk2 <[email protected]>
Co-authored-by: fengmk2 <[email protected]>
|
@copilot fix lint errors |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (3)
test/sri-integration.mjs (2)
4-201: Consider importing and testing the actual controller implementation.The current approach simulates the controller logic by duplicating the implementation within the test file. This creates maintenance burden and risks divergence between test and production code.
Consider refactoring to:
- Import
parseSRIFromIntegrityandformatFileItemfrom the actual controller file- Test the real implementations rather than simulated copies
- Integrate with the existing test framework (appears to be using a custom runner)
This would ensure tests remain synchronized with the actual implementation and catch regressions more reliably.
40-40: Use consistent assertion style.The test mixes
assert(condition)andassert.equal()calls, triggering theconsistent-assertlinting rule. Choose one style for consistency.Since you're already importing from
node:assert/strict, prefer using the more specific assertion methods (assert.equal,assert.notEqual, etc.) throughout for clearer failure messages:- assert(parsed !== null); + assert.notEqual(parsed, null);Also applies to: 50-50, 125-125, 143-143, 161-161, 177-178
app/port/controller/PackageVersionFileController.ts (1)
75-101: LGTM: Robust SRI parsing implementation.The
parseSRIFromIntegrityfunction correctly parses space-separated algorithm hashes and returns structured SRI data or null. The logic handles all three algorithms (sha256, sha384, sha512) appropriately.Optional refinement: Consider omitting empty algorithm fields rather than setting them to empty strings (lines 93-95). This would make the API more intuitive:
return { - sha256: sri.sha256 || '', - sha384: sri.sha384 || '', - sha512: sri.sha512 || '', + ...(sri.sha256 && { sha256: sri.sha256 }), + ...(sri.sha384 && { sha384: sri.sha384 }), + ...(sri.sha512 && { sha512: sri.sha512 }), combined: Object.values(sri).filter(Boolean).join(' '), };However, the current approach with empty strings is also valid if consumers expect consistent field presence.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
app/common/PackageUtil.ts(2 hunks)app/core/service/PackageVersionFileService.ts(1 hunks)app/port/controller/PackageVersionFileController.ts(3 hunks)docs/SRI_SUPPORT.md(1 hunks)test/common/PackageUtil/calculateIntegrity.test.ts(1 hunks)test/port/controller/PackageVersionFileController/raw.test.ts(1 hunks)test/sri-integration.mjs(1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Node.js CI
test/common/PackageUtil/calculateIntegrity.test.ts
[warning] 66-66: eslint(no-console): Unexpected console statement. Delete this console statement.
[warning] 89-89: eslint(no-console): Unexpected console statement. Delete this console statement.
[warning] 97-97: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 100-100: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 101-101: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 102-102: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 65-66: eslint(no-empty-function): Unexpected empty function. Consider removing this function or adding logic.
[warning] 89-90: eslint(no-empty-function): Unexpected empty function. Consider removing this function or adding logic.
[warning] 15-15: eslint(consistent-assert): Inconsistent assert usage. Prefer assert.ok(...) over assert(...)
[warning] 16-16: eslint(consistent-assert): Inconsistent assert usage. Prefer assert.ok(...) over assert(...)
[warning] 17-17: eslint(consistent-assert): Inconsistent assert usage. Prefer assert.ok(...) over assert(...)
[warning] 20-20: eslint(consistent-assert): Inconsistent assert usage. Prefer assert.ok(...) over assert(...)
[warning] 21-21: eslint(consistent-assert): Inconsistent assert usage. Prefer assert.ok(...) over assert(...)
[warning] 22-22: eslint(consistent-assert): Inconsistent assert usage. Prefer assert.ok(...) over assert(...)
[warning] 23-23: eslint(consistent-assert): Inconsistent assert usage. Prefer assert.ok(...) over assert(...)
[warning] 24-24: eslint(consistent-assert): Inconsistent assert usage. Prefer assert.ok(...) over assert(...)
[warning] 27-28: eslint(consistent-assert): Inconsistent assert usage. Prefer assert.ok(...) over assert(...)
[warning] 32-34: eslint(consistent-assert): Inconsistent assert usage. Prefer assert.ok(...) over assert(...)
test/port/controller/PackageVersionFileController/raw.test.ts
[warning] 817-817: eslint(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 818-818: eslint(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 819-819: eslint(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 860-860: eslint(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 862-862: eslint(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 863-863: eslint(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 823-825: eslint(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 823-825: eslint(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
test/sri-integration.mjs
[warning] 5-5: eslint(no-console): Unexpected console statement. Delete this console statement.
[warning] 63-63: eslint(no-console): Unexpected console statement. Delete this console statement.
[warning] 163-163: eslint(no-console): Unexpected console statement. Delete this console statement.
[warning] 188-188: eslint(no-console): Unexpected console statement. Delete this console statement.
[error] 199-199: eslint(no-process-exit): Don't use process.exit(). Throw an error instead.
[warning] 40-40: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 50-50: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 125-125: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 143-143: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 161-161: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 177-177: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[warning] 178-178: eslint-plugin-unicorn(consistent-assert): Inconsistent assert usage. Prefer using a single style for assertions.
[error] 199-199: eslint(no-process-exit): Don't use process.exit(). Throw an error instead.
🪛 markdownlint-cli2 (0.18.1)
docs/SRI_SUPPORT.md
41-41: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: copilot
🔇 Additional comments (2)
app/port/controller/PackageVersionFileController.ts (2)
34-73: LGTM: Clean SRI integration in FileItem and formatFileItem.The changes properly extend
FileItemwith optional SRI data and refactorformatFileItemto parse and include it. The type refinement ('file' as constat line 53) improves type safety, and the conditional SRI inclusion maintains backwards compatibility.
268-278: LGTM: SRI headers properly added to raw file responses.The implementation correctly parses SRI data and sets appropriate HTTP headers (X-SRI-SHA256, X-SRI-SHA384, X-SRI-SHA512, X-SRI-Integrity) for browser and tool integration. The conditional header setting ensures backwards compatibility with files lacking SRI data.
docs/SRI_SUPPORT.md
Outdated
| ``` | ||
| X-SRI-SHA256: sha256-3/1gIbsr1bCvZ2KQgJ7DpTGR3YHH9wpLKGiKNiGCmG8= | ||
| X-SRI-SHA384: sha384-VIXMmzNltDBd+06DN+ClmKV0+CQr8XKJ4N1sIKPNRKCJ3harSrMI9j5EsRcOtfUV | ||
| X-SRI-SHA512: sha512-N015SpXNz9izWZMYX++bo2jxYNja9DLQi6nx7R5avmzGkpHg+i/gAGpSVw7xjBne9OYXwzzlLvCm5fvjGMsDhw== | ||
| X-SRI-Integrity: sha256-3/1gIbsr1bCvZ2KQgJ7DpTGR3YHH9wpLKGiKNiGCmG8= sha384-VIXMmzNltDBd+06DN+ClmKV0+CQr8XKJ4N1sIKPNRKCJ3harSrMI9j5EsRcOtfUV sha512-N015SpXNz9izWZMYX++bo2jxYNja9DLQi6nx7R5avmzGkpHg+i/gAGpSVw7xjBne9OYXwzzlLvCm5fvjGMsDhw== | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a language hint to the fenced block.
markdownlint (MD040) is flagging this code fence because it has no language. Please annotate it (for example, ```text) so the docs lint passes.
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
41-41: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
In docs/SRI_SUPPORT.md around lines 41 to 46, the fenced code block lacks a
language hint and fails markdownlint MD040; update the opening fence to include
a language tag (for example use ```text) so the block becomes a
language-annotated fenced code block, keeping the same contents and closing
fence unchanged.
Co-authored-by: fengmk2 <[email protected]>
Fixed all lint errors in commit 10f8742: Changes made:
All oxlint checks now pass with 0 warnings and 0 errors. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #833 +/- ##
===========================================
- Coverage 95.16% 82.92% -12.25%
===========================================
Files 197 197
Lines 23906 24006 +100
Branches 1953 1440 -513
===========================================
- Hits 22751 19907 -2844
- Misses 1155 4099 +2944 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
docs/SRI_SUPPORT.md
Outdated
| "path": "/package.json", | ||
| "type": "file", | ||
| "contentType": "application/json", | ||
| "integrity": "sha512-N015SpXNz9izWZMYX++bo2jxYNja9DLQi6nx7R5avmzGkpHg+i/gAGpSVw7xjBne9OYXwzzlLvCm5fvjGMsDhw==", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot 我们只需要保持之前的 integrity 为 sha512 即可,只是新增一个 http response header,不需要额外新增其他算法。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplified the implementation as requested in commit fd4ec15:
Changes made:
- Reverted
calculateIntegrity()to only generate SHA-512 (removed SHA-256, SHA-384) - Removed
sriobject from file metadata responses - Simplified to single
X-Integrityheader containing SHA-512 hash - Removed multi-algorithm tests and documentation
- Kept only SHA-512 integrity field for backwards compatibility
The implementation now only adds a simple HTTP response header without changing the existing integrity calculation.
…A-512 Co-authored-by: fengmk2 <[email protected]>
Adds a simple
X-IntegrityHTTP response header containing the SHA-512 integrity hash when serving unpkg files. This allows clients to verify file integrity without changing the existing integrity calculation or file metadata format.Changes Made
X-Integrityheader to raw file responses containing the existing SHA-512 integrity value?meta) remain unchangedX-Integrityheader is correctly setImplementation Details
The implementation adds a single line to set the
X-Integrityheader inPackageVersionFileControllerwhen serving raw files:This provides a simple way for clients to access the integrity hash via HTTP headers without any changes to the existing integrity system or adding additional hash algorithms.
Testing
The changes are minimal and focused, adding only an HTTP header without altering any existing functionality or data structures.
Fixes #634.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.