Skip to content

Support FEP-fe34 cryptographic origins for portable objects#926

Merged
dahlia merged 3 commits into
fedify-dev:mainfrom
dahlia:feat/fep-ef61/ap-uri-crypto-origins
Jul 9, 2026
Merged

Support FEP-fe34 cryptographic origins for portable objects#926
dahlia merged 3 commits into
fedify-dev:mainfrom
dahlia:feat/fep-ef61/ap-uri-crypto-origins

Conversation

@dahlia

@dahlia dahlia commented Jul 8, 2026

Copy link
Copy Markdown
Member

Closes #829.

Why

Fedify already had two pieces of the portable-object story: FEP-ef61 URI parsing and local did:key verification method resolution for FEP-8b32 proofs. What was still missing was the policy layer between them. A portable object whose ID is ap://did:key:.../objects/1 should be able to carry an embedded did:key:...#... verification method or a matching portable actor without being treated as cross-origin just because the schemes differ.

This PR adds that bridge by comparing the FEP-fe34 origin of web URLs, portable ap:/ap+ef61: IDs, and DID URLs. HTTP(S) IDs keep the existing web-origin behavior. Portable IDs and DID URLs use their DID component as the cryptographic origin.

The proof path is intentionally narrower than the vocabulary lookup path. A proof can authenticate portable attributions by cryptographic origin only when the verification method ID is itself in the same cryptographic origin as the claimed controller. That keeps locally resolved did:key verification methods working while preventing an attacker-hosted HTTPS key document from claiming a victim DID controller and signing for that DID's portable objects.

How

  • packages/vocab-runtime/src/url.ts now exposes getFe34Origin() and haveSameFe34Origin(). They compare ordinary HTTP(S) origins and DID-based cryptographic origins through one helper.
  • packages/vocab-runtime/src/internal/jsonld-cache.ts and packages/vocab/src/lookup.ts use the new FE34 comparison as an addition to the existing IRI-origin comparison, not a replacement. This preserves existing same-authority behavior for non-FE34 schemes such as at://.
  • packages/fedify/src/sig/proof.ts uses FE34 origin matching when deciding whether a verified proof authenticates portable actors and attributions, but only after checking that the verification method ID is also in the matching cryptographic origin.
  • The manual pages under docs/manual/ now describe how Fedify treats cryptographic origins in lookup, vocabulary property accessors, and object proof verification.

Testing

The test coverage includes matching and mismatched portable DID origins, multiple same-origin portable attributions, same-authority non-FE34 IRIs, and the HTTPS-key spoofing case described above.

Verified with:

mise run test:deno -- packages/vocab-runtime/src/url.test.ts
mise run test:deno -- packages/vocab/src/lookup.test.ts --filter "FEP-fe34"
mise run test:deno -- packages/vocab/src/vocab.test.ts --filter "FEP-fe34"
mise run test:deno -- packages/fedify/src/sig/proof.test.ts --filter "verifyObject"
mise run check-each vocab-runtime vocab fedify
mise run test-each vocab-runtime vocab fedify
mise run check:md

Treat FEP-ef61 portable ActivityPub IDs and DID URLs as sharing an
FEP-fe34 cryptographic origin when their DID components match.  This lets
lookupObject(), generated vocabulary accessors, and did:key object proofs
handle portable objects without relaxing existing same-origin checks for
other IRI schemes.

Restrict proof-based portable attribution authentication to verification
methods that are themselves in the matching cryptographic origin, so a
remote HTTPS key cannot claim a victim DID controller and authenticate that
DID's portable objects.

fedify-dev#829
fedify-dev#926

Assisted-by: Codex:gpt-5.5
@dahlia dahlia added this to the Fedify 2.4 milestone Jul 8, 2026
@dahlia dahlia self-assigned this Jul 8, 2026
@dahlia dahlia added the component/vocab Activity Vocabulary related label Jul 8, 2026
@dahlia dahlia requested review from 2chanhaeng and sij411 as code owners July 8, 2026 11:37
@dahlia dahlia added component/federation Federation object related activitypub/compliance Specification compliance labels Jul 8, 2026
@netlify

netlify Bot commented Jul 8, 2026

Copy link
Copy Markdown

Deploy Preview for fedify-json-schema canceled.

Name Link
🔨 Latest commit 6d569d5
🔍 Latest deploy log https://app.netlify.com/projects/fedify-json-schema/deploys/6a4e461e41956e0008504b1f

@dahlia

dahlia commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@codex review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 95cf00bb-8ba7-4550-a23d-1c8417b43ffd

📥 Commits

Reviewing files that changed from the base of the PR and between a436473 and 6d569d5.

📒 Files selected for processing (2)
  • packages/vocab-runtime/src/url.test.ts
  • packages/vocab-runtime/src/url.ts

📝 Walkthrough

Walkthrough

This PR adds FEP-fe34 cryptographic-origin support for portable ap:/ap+ef61: identifiers and DID URLs. New URL helpers are used in lookup, proof verification, JSON-LD trust checks, and documentation, with tests covering matching, mismatch, and rejection cases.

Changes

FEP-fe34 origin support

Layer / File(s) Summary
Fe34 origin helper functions and tests
packages/vocab-runtime/src/url.ts, packages/vocab-runtime/src/mod.ts, packages/vocab-runtime/src/url.test.ts
Adds getFe34Origin() and haveSameFe34Origin(), updates portable DID normalization, re-exports the new helpers, and adds tests for web, portable, and DID origin cases.
jsonld-cache trust wiring
packages/vocab-runtime/src/internal/jsonld-cache.ts
isTrustedIriOrigin now accepts haveSameFe34Origin() alongside haveSameIriOrigin().
lookupObject cross-origin check and vocab embedded object trust
packages/vocab/src/lookup.ts, packages/vocab/src/lookup.test.ts, packages/vocab/src/vocab.test.ts
lookupObject() now treats FE34 origin mismatches as cross-origin, and the vocab tests cover portable object IDs, embedded object trust, and DID verification-method trust.
verifyObject attribution authentication
packages/fedify/src/sig/proof.ts, packages/fedify/src/sig/proof.test.ts
verifyObject() now uses FE34-aware attribution deletion helpers, with tests for matching and mismatching did:key-based portable attributions.
Documentation and changelog updates
docs/manual/context.md, docs/manual/context-advanced.md, docs/manual/send.md, docs/manual/vocab.md, CHANGES.md
Updates manual and release notes to describe the new cryptographic-origin rules and helper APIs.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

Possibly related PRs

  • fedify-dev/fedify#850: Shares the portable ap:/ap+ef61: parsing and canonicalization code updated by the new origin helpers.
  • fedify-dev/fedify#924: Intersects with the portable URI canonicalization changes in packages/vocab-runtime/src/url.ts.

Suggested labels: component/signatures, type/enhancement

Suggested reviewers: sij411, 2chanhaeng

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding FEP-fe34 cryptographic origin support for portable objects.
Description check ✅ Passed The description is detailed and directly matches the changeset, including origin helpers, call-site updates, and tests.
Linked Issues check ✅ Passed The PR implements the requested shared origin helpers, updates the listed FE34 call sites, and adds the expected regression tests.
Out of Scope Changes check ✅ Passed The changes stay within the origin-comparison and portable-object policy scope; no unrelated features are introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request implements FEP-fe34 cross-origin checks for FEP-ef61 portable ActivityPub IDs and DID URLs across the @fedify/fedify, @fedify/vocab, and @fedify/vocab-runtime packages. It introduces getFe34Origin() and haveSameFe34Origin() helpers to compute and compare cryptographic origins (using the DID component) alongside traditional web origins, and updates verifyObject() and lookupObject() to leverage these checks. The review feedback suggests improving DID normalization by ensuring that DID method names are consistently converted to lowercase to prevent case-sensitivity mismatches during origin comparisons, and recommends reusing this normalized logic when resolving portable cryptographic origins.

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.

Comment thread packages/vocab-runtime/src/url.ts
Comment thread packages/vocab-runtime/src/url.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 44441b5291

ℹ️ 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".

Comment thread packages/fedify/src/sig/proof.ts Outdated
@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.10345% with 6 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/vocab-runtime/src/url.ts 88.09% 3 Missing and 2 partials ⚠️
packages/fedify/src/sig/proof.ts 97.29% 0 Missing and 1 partial ⚠️
Files with missing lines Coverage Δ
...ackages/vocab-runtime/src/internal/jsonld-cache.ts 83.44% <100.00%> (+0.03%) ⬆️
packages/vocab-runtime/src/mod.ts 100.00% <100.00%> (ø)
packages/vocab/src/lookup.ts 96.49% <100.00%> (+0.03%) ⬆️
packages/fedify/src/sig/proof.ts 80.14% <97.29%> (+1.67%) ⬆️
packages/vocab-runtime/src/url.ts 90.11% <88.09%> (-0.04%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Normalize DID method names when deriving FE34 origins so portable
ActivityPub IDs and DID URLs compare according to DID Core casing
rules.  Reuse that validation path for portable authorities instead
of maintaining a separate normalization shortcut.

Keep exact DID attributions protected by the same verification-method
origin check used for portable attributions.  This prevents an
attacker-hosted HTTPS key document from claiming a DID controller and
authenticating objects attributed directly to that DID.

fedify-dev#926 (comment)
fedify-dev#926 (comment)
fedify-dev#926 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@dahlia

dahlia commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@codex review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request implements cross-origin checks for FEP-fe34 cryptographic origins, supporting FEP-ef61 portable ActivityPub IDs and DID URLs. It introduces the helper functions getFe34Origin() and haveSameFe34Origin() in the vocabulary runtime to resolve and compare web origins and cryptographic DID origins. These helpers are integrated into verifyObject(), lookupObject(), and property accessors to treat matching portable IDs and DID controllers as same-origin. Comprehensive tests and documentation updates have also been added. I have no feedback to provide as there are no review comments.

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.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a436473f37

ℹ️ 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".

Comment thread packages/vocab-runtime/src/url.ts Outdated
Apply the same percent-encoding normalization to FE34 DID origins that
portable URI canonicalization already uses.  This lets equivalent DID
authorities compare as the same cryptographic origin even when one form
uses percent escapes for unreserved characters.

fedify-dev#926 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@dahlia

dahlia commented Jul 8, 2026

Copy link
Copy Markdown
Member Author

@codex review
/gemini review

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 6d569d5c7d

ℹ️ 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".

@sij411 sij411 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I found hasCryptographicOrigin() does similar job to getFe34Origin() 's parsePortableIri() and DID_SCHEME_PATTERN.test(input) from @fedify/vocab-runtime but only a small part can be shared so I don't think it's a big deal.

@dahlia dahlia merged commit a974c7d into fedify-dev:main Jul 9, 2026
21 checks passed
@dahlia dahlia deleted the feat/fep-ef61/ap-uri-crypto-origins branch July 9, 2026 06:34
for await (const proof of object.getProofs(options)) {
const key = await verifyProof(jsonLd, proof, options);
if (key === null) return null;
if (proof.verificationMethodId == null) return null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

if (proof.verificationMethodId == null) return null; is not useful. Because if proof.verificationMethodId == null, then verifyProof() will return null and verifyObject() will return null, already.

}

function hasCryptographicOrigin(iri: string): boolean {
return /^did:/i.test(iri) || /^ap(?:\+ef61)?:\/\//i.test(iri);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This local RegExps are also defined in packages/vocab-runtime/src/url.ts. Import them and reuse for consistency and maintainability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

activitypub/compliance Specification compliance component/federation Federation object related component/vocab Activity Vocabulary related

Development

Successfully merging this pull request may close these issues.

Support cryptographic origins for ap:/ap+ef61: URIs

3 participants