FEP-ef61 portable object vocabulary#928
Conversation
Expose FEP-ef61 gateways on actor classes and digestMultibase on links and document-like media objects. Preload the FEP-ef61 and Data Integrity v2 contexts so these terms compact and expand without remote context fetches. Update the vocabulary manual with a dedicated portable objects section and record the change for the planned PR. fedify-dev#830 fedify-dev#928 Assisted-by: Codex:gpt-5.5
✅ Deploy Preview for fedify-json-schema canceled.
|
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request adds support for FEP-ef61 portable ActivityPub objects, introducing the gateways property to actor classes and digestMultibase to link and document/media classes, along with updating documentation, fixtures, and tests. The review feedback correctly points out that while the https://w3id.org/security/data-integrity/v2 context is declared as preloaded and used in several vocabulary files, it is missing its actual import and registration in the preloaded contexts registry, which would cause offline expansion and compaction to fail.
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.
|
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:
📝 WalkthroughWalkthroughThis PR adds FEP-ef61 support for portable ActivityPub objects by introducing a preloaded JSON-LD context, updating vocab schemas and defaults, expanding fixtures and tests, and documenting portable object handling and related security-model wording. ChangesFEP-ef61 Vocabulary and Runtime Context Support
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related issues
Possibly related PRs
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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 612ca3d2cb
ℹ️ 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".
Codecov Report❌ Patch coverage is
🚀 New features to boost your workflow:
|
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 `@docs/manual/vocab.md`:
- Around line 212-216: The example in the vocabulary docs uses an unencoded DID
authority that is not a valid copy/paste URI literal. Update the portable
ActivityPub IRI example in the relevant docs section to use the percent-encoded
authority form, keeping the surrounding explanation in sync with the accepted
`ap:` and `ap+ef61:` forms and the canonical serialization behavior described
there.
🪄 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: e00da8bc-eb1f-4a6e-bfd7-5136c2bf1b76
⛔ Files ignored due to path filters (4)
packages/vocab-tools/src/__snapshots__/class.test.ts.deno.snapis excluded by!**/*.snappackages/vocab-tools/src/__snapshots__/class.test.ts.node.snapis excluded by!**/*.snappackages/vocab-tools/src/__snapshots__/class.test.ts.snapis excluded by!**/*.snappackages/vocab/src/__snapshots__/vocab.test.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (21)
CHANGES.mddocs/manual/vocab.mdpackages/fedify/src/federation/handler.test.tspackages/fixture/src/fixtures/w3id.org/fep/ef61.jsonpackages/fixture/src/fixtures/w3id.org/security/data-integrity/v2.jsonpackages/vocab-runtime/src/contexts.tspackages/vocab-runtime/src/contexts/fep-ef61.jsonpackages/vocab-runtime/src/docloader.tspackages/vocab-tools/src/type.tspackages/vocab/src/application.yamlpackages/vocab/src/audio.yamlpackages/vocab/src/document.yamlpackages/vocab/src/group.yamlpackages/vocab/src/image.yamlpackages/vocab/src/link.yamlpackages/vocab/src/organization.yamlpackages/vocab/src/page.yamlpackages/vocab/src/person.yamlpackages/vocab/src/service.yamlpackages/vocab/src/video.yamlpackages/vocab/src/vocab.test.ts
Keep the vendored Data Integrity v1 context from redefining the digestMultibase term that FEP-ef61 uses for credentials v2 digests. Also carry digestMultibase through Link-to-Image normalization and fix the portable URI example to use an encoded DID authority. fedify-dev#928 (comment) fedify-dev#928 (comment) fedify-dev#928 (comment) Assisted-by: Codex:gpt-5.5
|
@codex review |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request implements support for FEP-ef61 portable ActivityPub objects. It introduces the gateways property for actor classes (Application, Group, Organization, Person, Service) and the digestMultibase property for Link and document/media classes (Audio, Document, Image, Video, Page). Additionally, it updates the preloaded JSON-LD contexts, document loader, and property preprocessors to support these terms, and adds comprehensive tests. A review comment correctly points out an incorrect example in the documentation where a percent-encoded DID authority is labeled as decoded.
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: cd8abc8bf6
ℹ️ 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".
Treat actor gateways as their own URL scalar so generated constructors and JSON-LD decoding both enforce the FEP-ef61 gateway shape. Gateways now have to be HTTP(S) base URIs, which keeps portable actor data from serializing values that downstream dereferencing code should reject. The manual now avoids calling percent-encoded DID authorities decoded input, and documents the gateway base URI requirement next to the actor example. fedify-dev#928 (comment) fedify-dev#928 (comment) Assisted-by: Codex:gpt-5.5
|
@codex review |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces support for FEP-ef61 portable ActivityPub objects, adding the gateways list to actor classes and digestMultibase to link and media classes, along with preloaded JSON-LD contexts and validation helpers. The review feedback highlights a potential runtime crash in dataCheck when handling null values, advises against modifying standard vendored context files (such as security-data-integrity-v1.json) to resolve term conflicts, and suggests strengthening gateway URL validation to explicitly reject URLs containing user credentials.
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.
I am having trouble creating individual review comments. Click here to see my feedback.
packages/vocab-tools/src/type.ts (340-344)
In JavaScript/TypeScript, typeof null evaluates to "object". If ${v} is null, the check typeof ${v} === "object" will pass, and the subsequent "@value" in ${v} expression will throw a TypeError: Cannot use 'in' operator to search for '@value' in null. Adding a null check (${v} !== null) prevents this runtime crash when parsing properties with null values.
dataCheck(v) {
return "${v} !== null && typeof ${v} === \"object\" && \"@value\" in ${v}\n && typeof ${v}[\"@value\"] === \"string\"\n && ${v}[\"@value\"] !== \"\" && ${v}[\"@value\"] !== \"/\"";
},packages/vocab-runtime/src/contexts/security-data-integrity-v1.json (6-9)
Modifying standard, third-party vendored context files (like security-data-integrity-v1.json) to resolve term conflicts is highly discouraged. It breaks offline-online parity and interoperability for other documents that use the standard security-data-integrity-v1 context and expect digestMultibase to resolve to https://w3id.org/security#digestMultibase.
Instead, term overriding should be handled by context ordering (e.g., placing the FEP-ef61 context after the Data Integrity v1 context in the document's @context array) or via custom document loader mapping if necessary.
packages/vocab-runtime/src/url.ts (329-332)
A gateway URL should not contain user credentials (username and password) to prevent potential credential leakage or malformed URLs. Checking url.username === "" and url.password === "" ensures that only clean base URIs are accepted.
export function isGatewayUrl(url: URL): boolean {
return (url.protocol === "http:" || url.protocol === "https:") &&
url.pathname === "/" && url.search === "" && url.hash === "" &&
url.username === "" && url.password === "";
}
packages/vocab-runtime/src/url.test.ts (649-656)
Add a test case to verify that gateway URLs with credentials (e.g., https://user:pass@server.example/) are correctly rejected.
for (
const url of [
"ftp://server.example/",
"https://server.example/path",
"https://server.example/?x=1",
"https://server.example/#fragment",
"https://user:pass@server.example/",
]
) {
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8e1601861c
ℹ️ 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".
FEP-ef61 gateways are dereferenceable URI references, so generated JSON-LD should emit them as @id entries instead of value literals. The decoder still accepts the existing literal form because the bundled FEP context can produce it, but @id typed contexts now round-trip through the same base URI validation. fedify-dev#928 (comment) Assisted-by: Codex:gpt-5.5
|
@codex review |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request implements support for FEP-ef61 portable ActivityPub objects, introducing gateways lists for actor classes and digestMultibase for links and media/document classes. It also adds preloaded JSON-LD contexts and utility functions (isGatewayUrl, parseGatewayUrl) to validate gateway URLs as HTTP(S) base URIs. Feedback from the review suggests strengthening the gateway URL validation in isGatewayUrl to explicitly reject URLs containing userinfo (username and password) to prevent potential credential leakage, along with adding corresponding test cases.
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-tools/src/type.ts`:
- Around line 340-348: The dataCheck and decoder logic in the type definition
are out of sync: dataCheck only accepts the `@id` branch when `@id` is a non-empty
string, but decoder still chooses `@id` based on presence alone. Update decoder to
use the same type-guarding rules as dataCheck in this type.ts definition, likely
by checking that `@id` is a string before passing it to parseGatewayUrl and
otherwise falling back to `@value`, so malformed objects cannot crash decoding.
🪄 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: efd1917c-9a2a-4d8b-8e81-11669539059a
⛔ Files ignored due to path filters (3)
packages/vocab-tools/src/__snapshots__/class.test.ts.deno.snapis excluded by!**/*.snappackages/vocab-tools/src/__snapshots__/class.test.ts.node.snapis excluded by!**/*.snappackages/vocab-tools/src/__snapshots__/class.test.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (2)
packages/vocab-tools/src/type.tspackages/vocab/src/vocab.test.ts
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1840cf4398
ℹ️ 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".
Gateway URLs cannot carry credentials, so reject userinfo at the shared runtime predicate before those values can be accepted by generated vocab constructors or JSON-LD input. The generated decoder now mirrors the scalar data guard before choosing between @id and legacy @value input. The FEP-ef61 context also types gateways as IRI references so compact and expanded forms agree. fedify-dev#928 (comment) fedify-dev#928 (comment) fedify-dev#928 (comment) fedify-dev#928 (comment) fedify-dev#928 (comment) Assisted-by: Codex:gpt-5.5
|
/gemini review |
|
@codex review |
There was a problem hiding this comment.
Code Review
This pull request implements support for FEP-ef61 portable ActivityPub objects. It adds the gateways property to actor classes and the digestMultibase property to Link and document/media classes, preloads the FEP-ef61 JSON-LD context, and introduces helper functions to parse and validate gateway base URIs. The review feedback highlights a mismatch in the @type definition for gateways in the fixture context compared to the runtime context, suggesting it be updated to @id to ensure consistent JSON-LD compaction and expansion behavior.
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: c6adeadbda
ℹ️ 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".
Media documents now define only the credentials v2 digestMultibase term inline when they also include the Data Integrity v2 context. This keeps compact output stable without publishing two contexts that define the same protected term differently. The FEP-ef61 fixture context also mirrors the runtime gateway mapping so fixture-based expansion treats gateways as IRI references. fedify-dev#928 (comment) fedify-dev#928 (comment) Assisted-by: Codex:gpt-5.5
|
@codex review |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request implements support for FEP-ef61 portable ActivityPub objects, adding vocabulary terms such as gateways for actor classes and digestMultibase for links and media documents, along with corresponding JSON-LD contexts, validation helpers, and tests. The review feedback highlights a critical issue where modifying the vendored security-data-integrity-v1.json context file to remove digestMultibase will break signature verification. Additionally, it is recommended to make the digestMultibase property non-functional in both document.yaml and link.yaml to support multiple digests as specified by the W3C Verifiable Credential Data Integrity standard.
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.
I am having trouble creating individual review comments. Click here to see my feedback.
packages/vocab-runtime/src/contexts/security-data-integrity-v1.json (6-9)
Modifying the official, vendored https://w3id.org/security/data-integrity/v1 context file to remove digestMultibase is highly problematic and will break signature verification.
During JSON-LD signature verification (e.g., for Data Integrity Proofs), the document is expanded using the preloaded document loader. If the preloaded context differs from the official one by omitting digestMultibase, any incoming document using the v1 context that contains a digestMultibase property will have that property silently dropped during expansion. This will result in a different canonicalized RDF dataset than what the sender signed, causing signature verification to fail.
Instead of modifying the official context, we should keep it intact. If there is a URI conflict in the vocabulary, we should handle it in the vocabulary layer (e.g., by mapping both URIs or treating them as aliases) rather than diverging from the standard context.
packages/vocab/src/document.yaml (35-45)
According to the W3C Verifiable Credential Data Integrity specification (Section 2.3 Resource Integrity), the digestMultibase property can be either a single string value or a list of string values (to support multiple digests/algorithms, such as SHA-256 and SHA-512).
By setting functional: true, we restrict this property to a single string value, which will prevent parsing or serializing multiple digests. Consider making it non-functional by removing functional: true and defining it with a plural name and singular accessor. Note that if you make this change, you should also update normalizeLinkToImage in packages/vocab/src/preprocessors.ts to copy digestMultibases instead of digestMultibase.
- pluralName: digestMultibases
singularName: digestMultibase
singularAccessor: true
compactName: digestMultibase
uri: "https://www.w3.org/ns/credentials/v2#digestMultibase"
description: |
The multibase-encoded integrity digest of an external resource represented
by this document.
See [FEP-ef61](https://w3id.org/fep/ef61) for details.
range:
- "http://www.w3.org/2001/XMLSchema#string"packages/vocab/src/link.yaml (53-62)
According to the W3C Verifiable Credential Data Integrity specification (Section 2.3 Resource Integrity), the digestMultibase property can be either a single string value or a list of string values (to support multiple digests/algorithms, such as SHA-256 and SHA-512).
By setting functional: true, we restrict this property to a single string value, which will prevent parsing or serializing multiple digests. Consider making it non-functional by removing functional: true and defining it with a plural name and singular accessor. Note that if you make this change, you should also update normalizeLinkToImage in packages/vocab/src/preprocessors.ts to copy digestMultibases instead of digestMultibase.
- pluralName: digestMultibases
singularName: digestMultibase
singularAccessor: true
compactName: digestMultibase
uri: "https://www.w3.org/ns/credentials/v2#digestMultibase"
description: |
The multibase-encoded integrity digest of the linked resource.
See [FEP-ef61](https://w3id.org/fep/ef61) for details.
range:
- "http://www.w3.org/2001/XMLSchema#string"|
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". |
Why this belongs in the vocabulary layer
FEP-ef61 makes portable ActivityPub objects useful only if their supporting terms can move through the same typed JSON-LD path as the rest of Fedify's vocabulary. Treating
gatewaysanddigestMultibaseas ad hoc extension properties would leave users with raw JSON handling at exactly the point where portable objects need predictable parsing, ordering, and serialization.This PR adds those terms to the vocabulary schemas instead. Actor gateway ordering is represented as a JSON-LD list because the FEP gives that order meaning. Media integrity metadata is attached to links and document-like objects through the Data Integrity v2 term, so compacted and expanded JSON-LD use the same identifier that FEP-ef61 expects.
How the contexts are wired
The FEP-ef61 context is vendored into packages/vocab-runtime/src/contexts and registered with the preloaded document loader. Data Integrity v2 is also available through the existing context registry path. That keeps normal compaction and expansion offline for the new terms, which matters because these contexts are part of the library's core vocabulary behavior rather than application data that should require a network fetch.
The vocabulary generator's context heuristics were updated so
gatewaysis handled as an IRI-valued list anddigestMultibaseresolves to the credentials v2 term. The generated tests and snapshots then exercise the same code paths users get fromfromJsonLd()andtoJsonLd(), instead of only checking hand written helper behavior.Documentation shape
The manual now has a dedicated FEP-ef61 portable objects section in docs/manual/vocab.md. The previous portable ID notes were useful, but they were split across general instantiation and security-model text. Keeping portable IDs, gateway ordering, digest metadata, and origin comparison in one place should make the feature easier to find and harder to misunderstand.
Validation
I checked the focused FEP-ef61 vocabulary tests first, then regenerated the affected snapshots for Deno, Node.js, and Bun. After the handler expectation was updated for the new actor context, the full
mise testcommand completed successfully.