Add SHA-256 digest and hashlink helpers for portable media#935
Conversation
Implement SHA-256 digestMultibase and metadata-free hashlink helpers in vocab-runtime so FEP-ef61 media can be created and verified across supported runtimes. Validate canonical multibase and multihash encodings, and document the public API. Closes fedify-dev#831 Assisted-by: Codex:gpt-5.6-sol
✅ Deploy Preview for fedify-json-schema canceled.
|
|
@codex review |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdded SHA-256 ChangesDigest and hashlink helpers
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Application
participant computeDigestMultibase
participant WebCrypto
participant createHashlink
participant verifyHashlink
Application->>computeDigestMultibase: resource bytes
computeDigestMultibase->>WebCrypto: SHA-256 digest request
WebCrypto-->>computeDigestMultibase: raw digest bytes
computeDigestMultibase-->>Application: digestMultibase
Application->>createHashlink: digestMultibase
createHashlink-->>Application: hl: hashlink
Application->>verifyHashlink: resource bytes and hashlink
verifyHashlink-->>Application: verification result
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 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 |
There was a problem hiding this comment.
Code Review
This pull request introduces SHA-256 digestMultibase and simple hl: hashlink helpers in @fedify/vocab-runtime to support computing, parsing, creating, and verifying portable media resource digests as required by FEP-ef61. The feedback suggests optimizing memory usage in computeDigestMultibase and verifyDigestMultibase by avoiding unconditional bytes.slice() on the input Uint8Array unless the underlying buffer is a SharedArrayBuffer.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Codex Review: Didn't find any major issues. Chef's kiss. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Codecov Report❌ Patch coverage is
... and 1 file with indirect coverage changes 🚀 New features to boost your workflow:
|
Pass ArrayBuffer-backed views directly to WebCrypto so hashing large media does not allocate a full-size copy. Copy only SharedArrayBuffer- backed input, which WebCrypto cannot consume, and cover that fallback in both digest helper paths. fedify-dev#935 (comment) fedify-dev#935 (comment) Assisted-by: Codex:gpt-5.6-sol
|
/gemini review |
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request introduces SHA-256 digestMultibase and simple hl: hashlink helpers in @fedify/vocab-runtime to compute, parse, create, and verify portable media resource digests as required by FEP-ef61. The changes include implementation, tests, and documentation updates. Feedback is provided to improve the robustness of toWebCryptoBytes by addressing cross-realm compatibility and avoiding redundant instantiation when standard ArrayBuffers are used.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Codex Review: Didn't find any major issues. Can't wait for the next one! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
ArrayBuffer instanceof checks depend on the current JavaScript realm and could make ordinary media input incur a full copy. Detect only shared storage by its intrinsic tag so regular Uint8Array views pass through unchanged while SharedArrayBuffer input remains Web Crypto-compatible. fedify-dev#935 (comment) Assisted-by: Codex:gpt-5.6-sol
|
/gemini review |
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request introduces SHA-256 digestMultibase and simple hl: hashlink helpers to @fedify/vocab-runtime for computing, parsing, creating, and verifying portable media resource digests as required by FEP-ef61. It also adds comprehensive unit tests and documentation updates. The review feedback suggests two optimizations: simplifying the constant-time comparison loop in verifyDigestMultibase since digest lengths are guaranteed to be equal, and refactoring verifyHashlink to avoid redundant parsing of the digest multibase.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/vocab-runtime/src/digest.ts`:
- Around line 28-31: Replace the `Object.prototype.toString` check and
conditional `bytes.slice()` with an unconditional copy into a fresh `Uint8Array`
before `crypto.subtle.digest`; use the existing digest input handling in
`digest.ts` to ensure subclasses and shared-backed buffers cannot pass through
unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ff0432dc-fc83-4710-95d1-56862fb1e111
📒 Files selected for processing (1)
packages/vocab-runtime/src/digest.ts
String tags and typed-array slice methods can be overridden, so neither reliably identifies or copies shared storage. Use the native ArrayBuffer byte-length getter as a realm-independent brand check and copy shared input through the base Uint8Array constructor. fedify-dev#935 (comment) Assisted-by: Codex:gpt-5.6-sol
SHA-256 parsing and hashing guarantee equal 32-byte digests, so the constant-time comparison does not need fallback indexing. Separate hashlink syntax extraction from digest validation so verification performs the relatively expensive multibase parsing only once. fedify-dev#935 (comment) fedify-dev#935 (comment) Assisted-by: Codex:gpt-5.6-sol
|
/gemini review |
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request introduces SHA-256 digestMultibase and simple hl: hashlink helpers to compute, parse, create, and verify portable media resource digests as required by FEP-ef61. Feedback focuses on improving the robustness and simplicity of the SharedArrayBuffer handling in packages/vocab-runtime/src/digest.ts. Specifically, it is recommended to remove the module-level descriptor lookup to prevent potential runtime crashes, and to simplify toWebCryptoBytes using instanceof SharedArrayBuffer while safely copying the buffer with .slice() for Web Crypto API compatibility.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f3640b6041
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Some JavaScript hosts may not expose the standard ArrayBuffer byte-length getter as expected. Treat a missing getter as an unknown buffer brand and take the safe copy path instead of failing while loading the module. fedify-dev#935 (comment) Assisted-by: Codex:gpt-5.6-sol
JavaScript's end anchor can match before a final line terminator, which allowed non-URI hashlink strings to reach digest validation without the suffix. Exclude every ECMAScript line terminator and require the match to consume the entire input. fedify-dev#935 (comment) Assisted-by: Codex:gpt-5.6-sol
|
/gemini review |
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request introduces SHA-256 digestMultibase and simple hl: hashlink helpers in @fedify/vocab-runtime to support portable media resource digests as required by FEP-ef61. It includes implementation, comprehensive unit tests, and updated documentation. Feedback on the implementation suggests adding a safety check for encodingFromBaseData returning null/undefined to prevent generic errors, removing a redundant regex match length check, and using a more robust cross-realm check for URL objects instead of instanceof.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
URL instanceof checks depend on the current JavaScript realm. Distinguish the string union member directly so URL objects from another realm still provide their href while strict whole-input hashlink validation remains. fedify-dev#935 (comment) Assisted-by: Codex:gpt-5.6-sol
|
/gemini review |
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request introduces SHA-256 digestMultibase and simple hl: hashlink helpers to compute, parse, create, and verify portable media resource digests as required by FEP-ef61. It includes the implementation in packages/vocab-runtime/src/digest.ts, exports in mod.ts, comprehensive unit tests in digest.test.ts, updated documentation in docs/manual/vocab.md, and changelog updates in CHANGES.md. There are no review comments, and I have no additional feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
A supported SHA-256 multihash is exactly 34 bytes, and base2 produces its longest supported representation at 273 characters including the prefix. Reject longer input before decoding so malformed values cannot consume resources disproportionate to any valid digest. fedify-dev#935 (comment) Assisted-by: Codex:gpt-5.6-sol
|
/gemini review |
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request introduces SHA-256 digestMultibase and simple hl: hashlink helpers in @fedify/vocab-runtime to support FEP-ef61, along with corresponding documentation and unit tests. The review feedback points out a redundant length check in extractDigestMultibase since the regular expression is already anchored with ^ and $, which can be simplified.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
FEP-ef61 allows portable objects and their media to be available through more than one gateway. A media URL alone cannot establish that two gateways returned the same resource, or that a resource has remained unchanged after an object was signed. The FEP therefore requires external resources to carry a SHA-256
digestMultibasevalue and recommends hashlinks for their identifiers.Fedify already exposes
digestMultibasein its vocabulary types, but applications had no matching runtime support for producing or checking those values. Each application would otherwise need to assemble multihashes by hand, choose a multibase representation, parsehl:URIs, and reproduce the same validation rules. Besides duplicating subtle binary encoding code, that would make portable media behave differently across Deno, Node.js, Bun, and browser-like WebCrypto environments.This PR puts that boundary in
@fedify/vocab-runtime. The helpers use Web Crypto API for SHA-256 and build on Fedify's existing multibase and multicodec code, so they do not add a second encoding stack or a runtime dependency ondigitalbazaar/hashlink. The Hashlink Internet-Draft is expired and describes more than FEP-ef61 needs, so the API deliberately supports only metadata-freehl:URIs. Metadata-bearing hashlinks and legacy?hl=parameters are rejected instead of becoming accidental compatibility commitments.Parsing is intentionally strict. A digest must contain a canonical multibase encoding of a canonical SHA-256 multihash with a 32-byte payload. Unsupported algorithms, overlong varints, incorrect padding, malformed lengths, and noncanonical encodings are rejected. This keeps equivalent digests from acquiring multiple accepted spellings and ensures that values created, parsed, serialized, and verified by different Fedify components agree exactly. Verification returns
falsefor valid digests that do not match the supplied bytes, while malformed inputs remain programmer-visibleTypeErrors.The implementation and its public exports live in packages/vocab-runtime/src/digest.ts and packages/vocab-runtime/src/mod.ts. The regression coverage in packages/vocab-runtime/src/digest.test.ts includes the Hashlink draft's
Hello World!vector, valid non-base58 multibase input, canonical padding, malformed multihashes, unsupported algorithms, metadata rejection, and matching and non-matching byte sequences. The portable-object section of docs/manual/vocab.md now shows how the digest and hashlink helpers fit the existing vocabulary properties, and CHANGES.md records the new API.Closes #831.