Skip to content

Verify FEP-044f quote authorization stamps#33

Merged
dahlia merged 9 commits into
fedify-dev:mainfrom
dahlia:fep-044f/verify
Jul 7, 2026
Merged

Verify FEP-044f quote authorization stamps#33
dahlia merged 9 commits into
fedify-dev:mainfrom
dahlia:fep-044f/verify

Conversation

@dahlia

@dahlia dahlia commented Jul 6, 2026

Copy link
Copy Markdown
Member

Closes #30.

Why this shape

FEP-044f approval has to be checked at the point where a received message is materialized, not only when the activity first arrives. A stamp can disappear or change after the quote was stored, so packages/botkit/src/message-impl.ts dereferences and validates the stamp each time it computes Message.quoteApproved. The helper in packages/botkit/src/quote-authorization.ts keeps the validation rules shared between materialization and incoming approval handling, so the origin, attribution, quote object, and target object checks cannot drift apart.

Self-quotes are treated as approved because they do not need a remote authorization stamp. Everything else is conservative: a missing stamp, a failed fetch, a mismatched interactingObject, a mismatched interactionTarget, a mismatched attributedTo, or a stamp from the wrong origin becomes false rather than an exception. That gives event handlers a clear signal without making timeline ingestion brittle.

How revocation is routed

A deleted quote authorization stamp may be delivered to the shared inbox without addressing the local bot that used it. Routing only through to and cc would miss that Delete, especially for dynamic bot groups. packages/botkit/src/instance-impl.ts therefore asks the repository for every bot identifier that references the deleted stamp URI and resolves those identifiers through the normal instance routing path.

Once a bot receives the Delete, packages/botkit/src/bot-impl.ts validates the revoker by origin instead of by exact actor URI. That matches how servers often send administrative Deletes from a same-origin service actor. The original Delete is forwarded before the local quote is stripped, preserving the remote revocation activity for followers first; the local message is then updated without the quote target, and Bot.onQuoteRevoked fires after the Update has been sent.

How storage supports routing

The received-stamp reference index is intentionally repository-level rather than actor-scoped. Shared-inbox routing starts before the instance knows which bot should handle the Delete, so the lookup has to answer “which identifiers reference this stamp?” rather than “which message does this one bot reference?”

packages/botkit/src/repository.ts adds that reverse lookup for the KV, memory, and memory-cached repositories. packages/botkit-sqlite/src/mod.ts and packages/botkit-postgres/src/mod.ts add database indexes on the authorization URI so the same query stays cheap for persistent repositories. The existing actor-scoped reference methods still handle per-bot message lookup and cleanup after the route has been resolved.

Validation

The tests exercise the failure modes that matter for federation rather than only the happy path: invalid stamps, legacy quotes without stamps, failed stamp fetches, same-origin service revocations, wrong-origin Deletes, unaddressed shared-inbox Deletes, and dynamic bot group routing. The repository tests cover the new reverse lookup across the in-memory, KV, SQLite, and PostgreSQL implementations.

I ran mise run test and mise run docs:build. The commit hook also ran deno check, deno lint, deno fmt --check, hongdown --check, and deno publish --dry-run.

Summary by CodeRabbit

  • New Features
    • Added Message.quoteApproved to report whether an incoming quote target is approved (or not applicable).
    • Added onQuoteRevoked so bots can react when a quote authorization is revoked.
    • Added repository support for reverse-lookup of which bot identifiers depend on a received quote authorization.
  • Bug Fixes
    • Improved revoked-quote handling: quote targets are stripped and update activities are sent.
    • Fixed delete routing for revoked quote authorizations, including dynamic bot setups.
  • Documentation
    • Updated quote/quoting event and message documentation for accepted/rejected/revoked behavior.
  • Tests
    • Expanded coverage for quote approval/revocation and quote-authorization reference indexing.

Add validation for FEP-044f quote authorization stamps when
materializing received messages, exposing the result through
Message.quoteApproved.

Route quote authorization Delete activities through the received stamp
reference index, strip revoked quotes after forwarding the Delete, and
fire Bot.onQuoteRevoked after the Update is sent.

Add reverse lookup support across the in-memory, KV, SQLite, and
PostgreSQL repositories, plus tests and documentation for the new
behavior.

Fixes fedify-dev#30
Refs fedify-dev#27

Assisted-by: Codex:gpt-5.5
@dahlia dahlia self-assigned this Jul 6, 2026
@dahlia dahlia added the enhancement New feature or request label Jul 6, 2026
@dahlia

dahlia commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@codex review

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@dahlia, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e46f28bd-0b94-4698-9818-156daddc3afc

📥 Commits

Reviewing files that changed from the base of the PR and between 6000a26 and af4f38b.

📒 Files selected for processing (4)
  • packages/botkit/src/bot-impl.test.ts
  • packages/botkit/src/bot-impl.ts
  • packages/botkit/src/message-impl.test.ts
  • packages/botkit/src/message-impl.ts
📝 Walkthrough

Walkthrough

This PR adds quote approval verification, reverse-index lookup for quote authorization references, quote revocation handling, and documentation updates. It computes Message.quoteApproved, wires onQuoteRevoked, routes quote-authorization Delete activities by reference index, and updates tests and docs accordingly.

Changes

Quote Approval and Revocation

Layer / File(s) Summary
Quote approval validation
packages/botkit/src/quote-authorization.ts, packages/botkit/src/quote-authorization.test.ts, packages/botkit/src/message-impl.ts, packages/botkit/src/message-impl.test.ts, packages/botkit/src/bot-impl.ts, packages/botkit/src/bot-impl.test.ts, packages/botkit/src/message.ts
Adds validateQuoteAuthorization(), computes quoteApproved during message creation, and covers approved, rejected, abort, and legacy quote cases.
Quote authorization reverse index
packages/botkit/src/repository.ts, packages/botkit/src/repository.test.ts, packages/botkit-sqlite/src/mod.ts, packages/botkit-sqlite/src/mod.test.ts, packages/botkit-postgres/src/mod.ts, packages/botkit-postgres/src/mod.test.ts, packages/botkit/src/helpers.ts
Adds findQuoteAuthorizationReferenceIdentifiers() across repository implementations, plus supporting indexes, migration handling, and tests for lookup, removal, and missing-method handling.
Quote revocation handling
packages/botkit/src/events.ts, packages/botkit/src/bot.ts, packages/botkit/src/bot-impl.ts, packages/botkit/src/bot.test.ts, packages/botkit/src/instance-impl.ts, packages/botkit/src/instance-routing.test.ts, packages/botkit/src/bot-impl.test.ts
Adds onQuoteRevoked, forwards revocation Delete activities, strips revoked quotes, routes delete events by reverse index, and expands revocation coverage in tests.
Documentation and changelog
CHANGES.md, docs/concepts/events.md, docs/concepts/message.md
Documents quote approval, revocation, and the new quoteApproved property and handler behavior.

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

Possibly related issues

Possibly related PRs

  • fedify-dev/botkit#32: Shares the same quote-authorization storage and Delete-handling path that this PR extends with onQuoteRevoked and reverse-lookup identifiers.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: verifying FEP-044f quote authorization stamps.
Linked Issues check ✅ Passed The PR appears to implement the FEP-044f approval, revocation, indexing, eventing, tests, docs, and changelog work requested by #30.
Out of Scope Changes check ✅ Passed The changes stay focused on quote approval and revocation support, with no obvious unrelated scope additions.
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.

@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

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

Files with missing lines Patch % Lines
packages/botkit/src/repository.ts 75.00% 22 Missing and 10 partials ⚠️
packages/botkit/src/bot-impl.ts 94.70% 5 Missing and 5 partials ⚠️
Files with missing lines Coverage Δ
packages/botkit-postgres/src/mod.ts 89.31% <100.00%> (+0.19%) ⬆️
packages/botkit-sqlite/src/mod.ts 74.56% <100.00%> (+0.34%) ⬆️
packages/botkit/src/bot.ts 100.00% <ø> (ø)
packages/botkit/src/helpers.ts 100.00% <100.00%> (ø)
packages/botkit/src/instance-impl.ts 77.49% <100.00%> (+0.30%) ⬆️
packages/botkit/src/message-impl.ts 88.69% <100.00%> (+0.95%) ⬆️
packages/botkit/src/message.ts 100.00% <ø> (ø)
packages/botkit/src/quote-authorization.ts 100.00% <100.00%> (ø)
packages/botkit/src/bot-impl.ts 87.02% <94.70%> (+1.89%) ⬆️
packages/botkit/src/repository.ts 88.25% <75.00%> (-0.05%) ⬇️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@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: b21b1f11ab

ℹ️ 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/botkit/src/bot-impl.ts
Comment thread packages/botkit/src/bot-impl.ts Outdated

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces support for verifying and revoking FEP-044f quote authorization stamps. It adds a new onQuoteRevoked event handler, introduces the Message.quoteApproved property, and implements the findQuoteAuthorizationReferenceIdentifiers method across database repositories to trace which bots reference a given stamp. The review feedback highlights a critical bug where the BotImpl instance is incorrectly passed to ctx.forwardActivity instead of the Delete activity, potential runtime TypeError crashes due to missing null checks on actor.id and targetActorId, and a redundant call to #hasValidQuoteAuthorization that can be safely removed.

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/botkit/src/bot-impl.ts Outdated
Comment thread packages/botkit/src/bot-impl.ts
Comment thread packages/botkit/src/bot-impl.ts Outdated
Comment thread packages/botkit/src/quote-authorization.ts

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/botkit/src/repository.ts (1)

1017-1101: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

migrate() doesn't rebuild the new quote-authorization reference index for legacy data.

migrate() special-cases only the "followees" category to rebuild its reverse index via #addToFolloweeIndex (lines 1084-1098), but "quoteAuthorizationRefs" (included in categories at line 1063) is copied as raw KV entries without a corresponding call to #addToQuoteAuthorizationReferenceIndex. Since findQuoteAuthorizationReferenceIdentifiers only reads from this materialized index (unlike the Postgres/SQLite backends, which query the table directly), legacy-migrated quote-authorization references become permanently invisible to reverse lookup, breaking Delete-triggered quote revocation for bots that adopted BotKit 0.4 data.

🛠️ Proposed fix
         if (category === "followees" && rest.length === 1) {
           let followeeId: URL;
           try {
             followeeId = new URL(rest[0]);
           } catch (error) {
             logger.warn(
               "Skipping the malformed legacy followee key {followeeId}.",
               { followeeId: rest[0], error },
             );
             continue;
           }
           await this.#addToFolloweeIndex(identifier, followeeId);
         }
+        if (category === "quoteAuthorizationRefs" && rest.length === 1) {
+          let authorizationUrl: URL;
+          try {
+            authorizationUrl = new URL(rest[0]);
+          } catch (error) {
+            logger.warn(
+              "Skipping the malformed legacy quote authorization reference key {authorization}.",
+              { authorization: rest[0], error },
+            );
+            continue;
+          }
+          await this.#addToQuoteAuthorizationReferenceIndex(
+            identifier,
+            authorizationUrl,
+          );
+        }
🤖 Prompt for 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.

In `@packages/botkit/src/repository.ts` around lines 1017 - 1101, migrate() is
copying legacy quote-authorization reference rows but never rebuilds the reverse
lookup index used by findQuoteAuthorizationReferenceIdentifiers. Update the
migration loop in KvRepository.migrate to mirror the followees special case for
the "quoteAuthorizationRefs" category by parsing each legacy reference key and
calling `#addToQuoteAuthorizationReferenceIndex` after copying the raw entry,
while preserving the existing retry/no-op behavior and letting malformed keys or
storage errors behave consistently with the followees handling.
🧹 Nitpick comments (4)
packages/botkit/src/message-impl.test.ts (1)

271-283: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Add a test for a fetched authorization whose id doesn't match the requested quoteAuthorizationId.

validateQuoteAuthorization separately checks authorization.id.href === options.authorizationId.href (distinct from the cross-origin check already tested), guarding against a server returning a different authorization object than the one referenced. This path isn't currently exercised.

🧪 Proposed additional test
+  await t.test("mismatched authorization id", async () => {
+    const message = await materialize({
+      quote: targetId,
+      quoteAuthorization: authorizationId,
+      authorization: new QuoteAuthorization({
+        id: new URL("https://author.example/stamps/other"),
+        attribution: author.id,
+        interactingObject: quoteId,
+        interactionTarget: targetId,
+      }),
+    });
+    assert.deepStrictEqual(message.quoteApproved, false);
+  });
🤖 Prompt for 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.

In `@packages/botkit/src/message-impl.test.ts` around lines 271 - 283, Add a test
in message-impl.test.ts that exercises validateQuoteAuthorization with a fetched
QuoteAuthorization whose id does not match the requested quoteAuthorizationId.
Reuse the existing materialize/setup pattern from the valid stamp test, but make
the returned authorization object have a different id than the one passed in
quoteAuthorization, and assert the failure/false result that proves
validateQuoteAuthorization checks authorization.id.href against
options.authorizationId.href in addition to the cross-origin validation.
packages/botkit/src/message-impl.ts (1)

984-992: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Reuse the already-computed documentLoader instead of recreating it.

createMessage already builds documentLoader at line 793 for use throughout the function, but verifyQuoteApproval independently calls session.context.getDocumentLoader(session.bot) again, duplicating that work on every quote verification.

♻️ Proposed fix: pass the existing loader down
 async function verifyQuoteApproval<TContextData>(
   raw: MessageClass,
   quoteTarget: Message<MessageClass, TContextData>,
   session: SessionImpl<TContextData>,
+  documentLoader: DocumentLoader,
 ): Promise<boolean> {
   ...
       : await session.context.lookupObject(
         raw.quoteAuthorizationId,
         {
           contextLoader: session.context.contextLoader,
-          documentLoader: await session.context.getDocumentLoader(
-            session.bot,
-          ),
+          documentLoader,
         },
       );

And update the call site to pass the existing documentLoader variable from createMessage.

🤖 Prompt for 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.

In `@packages/botkit/src/message-impl.ts` around lines 984 - 992, In
createMessage, verifyQuoteApproval is redundantly calling
session.context.getDocumentLoader(session.bot) instead of using the
already-built documentLoader from earlier in the function. Update the
verifyQuoteApproval call site to pass the existing documentLoader variable
through, and adjust verifyQuoteApproval’s parameter usage so it reuses that
loader rather than recreating it.
packages/botkit/src/bot-impl.test.ts (2)

4590-4646: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Same boolean-assertion anti-pattern here.

revoked is a plain boolean flag; Line 4640's assert.deepStrictEqual(revoked, false) should be assert.ok(!revoked).

As per coding guidelines: "avoid assert.equal(..., true) or assert.equal(..., false) in favor of assert.ok(...) / assert.ok(!...)."

♻️ Proposed fix
-  assert.deepStrictEqual(revoked, false);
+  assert.ok(!revoked);
🤖 Prompt for 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.

In `@packages/botkit/src/bot-impl.test.ts` around lines 4590 - 4646, The test in
BotImpl.onDeleted() is using a boolean anti-pattern for the revoked flag. Update
the assertion after the Delete handling to use assert.ok(!revoked) instead of a
deep-equality false check, keeping the rest of the quote revocation behavior
verification in this test unchanged.

Source: Coding guidelines


4437-4496: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use assert.ok(!...) for the boolean flag instead of deepStrictEqual.

rejectedCalled is a plain boolean, so assert.deepStrictEqual(rejectedCalled, false) at Line 4490 is the same anti-pattern the guideline calls out for assert.equal(..., false).

As per coding guidelines: "avoid assert.equal(..., true) or assert.equal(..., false) in favor of assert.ok(...) / assert.ok(!...)."

♻️ Proposed fix
-  assert.deepStrictEqual(rejectedCalled, false);
+  assert.ok(!rejectedCalled);
🤖 Prompt for 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.

In `@packages/botkit/src/bot-impl.test.ts` around lines 4437 - 4496, The test in
BotImpl.onDeleted() is asserting a plain boolean with deepStrictEqual, which
should follow the boolean assertion guideline instead. Update the rejectedCalled
check near the quote revocation assertions to use assert.ok(!rejectedCalled)
rather than comparing it to false, keeping the surrounding revocation checks for
revoked and revoker unchanged.

Source: Coding guidelines

🤖 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/botkit/src/message-impl.ts`:
- Around line 960-1003: verifyQuoteApproval currently performs
session.context.lookupObject without any cancellation, so a slow quote
authorization fetch can hang message processing. Thread an AbortSignal from
createMessage through verifyQuoteApproval and into the lookupObject call (or add
a timeout wrapper there), keeping the existing repository path and validation
flow intact.

In `@packages/botkit/src/quote-authorization.ts`:
- Around line 18-37: Add JSDoc to the exported API in quote-authorization.ts:
document QuoteAuthorizationValidationOptions and validateQuoteAuthorization with
a short purpose summary, parameter descriptions, and the return type/meaning for
the type guard. Include a `@since` tag with the appropriate version number for
both exported symbols, and keep the comments attached to the identifiers so they
remain discoverable even if code moves.

---

Outside diff comments:
In `@packages/botkit/src/repository.ts`:
- Around line 1017-1101: migrate() is copying legacy quote-authorization
reference rows but never rebuilds the reverse lookup index used by
findQuoteAuthorizationReferenceIdentifiers. Update the migration loop in
KvRepository.migrate to mirror the followees special case for the
"quoteAuthorizationRefs" category by parsing each legacy reference key and
calling `#addToQuoteAuthorizationReferenceIndex` after copying the raw entry,
while preserving the existing retry/no-op behavior and letting malformed keys or
storage errors behave consistently with the followees handling.

---

Nitpick comments:
In `@packages/botkit/src/bot-impl.test.ts`:
- Around line 4590-4646: The test in BotImpl.onDeleted() is using a boolean
anti-pattern for the revoked flag. Update the assertion after the Delete
handling to use assert.ok(!revoked) instead of a deep-equality false check,
keeping the rest of the quote revocation behavior verification in this test
unchanged.
- Around line 4437-4496: The test in BotImpl.onDeleted() is asserting a plain
boolean with deepStrictEqual, which should follow the boolean assertion
guideline instead. Update the rejectedCalled check near the quote revocation
assertions to use assert.ok(!rejectedCalled) rather than comparing it to false,
keeping the surrounding revocation checks for revoked and revoker unchanged.

In `@packages/botkit/src/message-impl.test.ts`:
- Around line 271-283: Add a test in message-impl.test.ts that exercises
validateQuoteAuthorization with a fetched QuoteAuthorization whose id does not
match the requested quoteAuthorizationId. Reuse the existing materialize/setup
pattern from the valid stamp test, but make the returned authorization object
have a different id than the one passed in quoteAuthorization, and assert the
failure/false result that proves validateQuoteAuthorization checks
authorization.id.href against options.authorizationId.href in addition to the
cross-origin validation.

In `@packages/botkit/src/message-impl.ts`:
- Around line 984-992: In createMessage, verifyQuoteApproval is redundantly
calling session.context.getDocumentLoader(session.bot) instead of using the
already-built documentLoader from earlier in the function. Update the
verifyQuoteApproval call site to pass the existing documentLoader variable
through, and adjust verifyQuoteApproval’s parameter usage so it reuses that
loader rather than recreating it.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4feb207-6c24-4774-bc63-c4f14a131e7f

📥 Commits

Reviewing files that changed from the base of the PR and between c9aae4c and b21b1f1.

📒 Files selected for processing (20)
  • CHANGES.md
  • docs/concepts/events.md
  • docs/concepts/message.md
  • packages/botkit-postgres/src/mod.test.ts
  • packages/botkit-postgres/src/mod.ts
  • packages/botkit-sqlite/src/mod.test.ts
  • packages/botkit-sqlite/src/mod.ts
  • packages/botkit/src/bot-impl.test.ts
  • packages/botkit/src/bot-impl.ts
  • packages/botkit/src/bot.test.ts
  • packages/botkit/src/bot.ts
  • packages/botkit/src/events.ts
  • packages/botkit/src/instance-impl.ts
  • packages/botkit/src/instance-routing.test.ts
  • packages/botkit/src/message-impl.test.ts
  • packages/botkit/src/message-impl.ts
  • packages/botkit/src/message.ts
  • packages/botkit/src/quote-authorization.ts
  • packages/botkit/src/repository.test.ts
  • packages/botkit/src/repository.ts

Comment thread packages/botkit/src/message-impl.ts
Comment thread packages/botkit/src/quote-authorization.ts
dahlia added 2 commits July 7, 2026 05:26
Legacy quote authorization reference rows were copied into the
scoped key space, but their reverse lookup index also has to be
rebuilt while the adopting bot owns the migration.  Rebuilding it in
the same pass keeps lookup behavior consistent after migration.

Malformed legacy keys are skipped like malformed followees, while
storage failures still leave the done marker unwritten so a later
migration attempt can retry the index write.

Addresses review feedback from:
fedify-dev#33 (review)

Assisted-by: Codex:gpt-5.5
Quote authorization revocations now require the recorded attribution
instead of trusting every actor on the stamp origin.  Remote Delete
forwarding is limited to quotes whose audience is already shared with
followers, which avoids exposing private quote stamps to unrelated
followers.

Remote quote authorization lookups now receive the createMessage abort
signal, and the validation helper documents its exported API while
rejecting missing target actors explicitly.

fedify-dev#33 (comment)
fedify-dev#33 (comment)
fedify-dev#33 (comment)
fedify-dev#33 (comment)
fedify-dev#33 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@dahlia

dahlia commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@codex review

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces support for FEP-044f quote authorization stamp revocations and verification of quote approvals on received third-party quote posts. It adds the onQuoteRevoked event handler, the Message.quoteApproved property, and new repository methods to find bot actors referencing a stamp. However, a critical security issue was identified in bot-impl.ts where the return value of this.#hasValidQuoteAuthorization is ignored, bypassing the authorization requirement. Additionally, several potential runtime crashes were found where calling new repository methods on custom repositories could throw a TypeError if they are not implemented; defensive checks should be added to ensure backward 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.

Comment thread packages/botkit/src/bot-impl.ts Outdated
Comment thread packages/botkit/src/instance-impl.ts Outdated
Comment thread packages/botkit/src/bot-impl.ts
Comment thread packages/botkit/src/repository.ts
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: 3c7f830f87

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

Local FEP-044f quote handling now stops before user handlers when
the stored authorization is missing, invalid, or revoked during the
audience check.  The cleanup path still runs first so widened local
quote stamps are revoked before the activity is dropped.

Older custom repository implementations may not yet expose the new
quote authorization reverse-index methods.  Treat those methods as
optional at runtime and fall back to empty routing or missing
attribution instead of crashing.

fedify-dev#33 (comment)
fedify-dev#33 (comment)
fedify-dev#33 (comment)
fedify-dev#33 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@dahlia

dahlia commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces support for verifying FEP-044f quote authorization stamps on received third-party quote posts and handling their revocation. It adds the Message.quoteApproved property to check for valid FEP-044f approval, introduces the QuoteRevokedEventHandler type and Bot.onQuoteRevoked event handler, and implements the findQuoteAuthorizationReferenceIdentifiers method across Postgres, SQLite, KV, and Memory repositories to track which bots depend on a given authorization stamp. When an authorization stamp is deleted, BotKit now forwards the Delete activity, strips the quote, and triggers the onQuoteRevoked event. As there are no review comments, no additional feedback is provided.

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.

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/botkit/src/bot-impl.ts (2)

2456-2482: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Silent fail-closed for repositories without the new reverse-index methods.

When the underlying repository doesn't implement findQuoteAuthorizationReferenceAttribution, this delegate returns undefined with no logging. Downstream, #validateQuoteAuthorizationDeletion() (Line 1033) treats undefined attribution as a mismatch and always returns undefined — meaning any repository that hasn't been upgraded with this optional method will silently and permanently ignore every incoming quote-authorization revocation, with no signal to the operator that the feature is inert. The same applies to findQuoteAuthorizationReferenceIdentifiers (Lines 2460-2463), used by migration/cleanup.

Since this is a deliberate compatibility fallback (per the PR's commit notes) rather than a bug, the main gap is observability: operators running a custom/legacy Repository implementation have no way to discover that revocation handling is silently disabled.

📝 Suggested fix: log once when the fallback is hit
   async findQuoteAuthorizationReferenceAttribution(
     identifier: string,
     authorization: URL,
   ): Promise<URL | undefined> {
     await this.#migration;
     if (
       typeof this.#repository.findQuoteAuthorizationReferenceAttribution !==
         "function"
-    ) return undefined;
+    ) {
+      logger.warn(
+        "The repository does not implement " +
+          "findQuoteAuthorizationReferenceAttribution(); quote " +
+          "authorization revocations will be silently ignored until it " +
+          "is upgraded.",
+      );
+      return undefined;
+    }
     return await this.#repository.findQuoteAuthorizationReferenceAttribution(
       identifier,
       authorization,
     );
   }
🤖 Prompt for 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.

In `@packages/botkit/src/bot-impl.ts` around lines 2456 - 2482, The fallback in
bot-impl.ts silently returns when the repository lacks the new reverse-index
methods, so add a one-time warning for observability in both
findQuoteAuthorizationReferenceAttribution and
findQuoteAuthorizationReferenceIdentifiers. Use the existing BotImpl methods and
the `#repository` capability checks to log once when these optional methods are
missing, making it clear that quote-authorization revocation/cleanup is disabled
for this repository implementation. Keep the compatibility behavior unchanged,
but ensure the operator can detect the fallback through the logger.

882-887: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Guard against stripping a newer quote authorization. onDeleted() uses a stale object snapshot, but #stripRejectedQuote() only checks quoteId. If the message is re-authorized with a new quoteAuthorizationId for the same target before updateMessage() runs, the old delete can still strip the newer authorization. Compare existingObject.quoteAuthorizationId?.href with the authorization being revoked before updating.

Proposed fix
         if (
           !isMessageObject(existingObject) || existingObject.id == null ||
-          (quoteId != null && existingObject.quoteId?.href !== quoteId.href)
+          (quoteId != null && existingObject.quoteId?.href !== quoteId.href) ||
+          existingObject.quoteAuthorizationId?.href !==
+            object.quoteAuthorizationId?.href
         ) {
           return;
         }
🤖 Prompt for 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.

In `@packages/botkit/src/bot-impl.ts` around lines 882 - 887, Guard the quote
revocation path in onDeleted()/#stripRejectedQuote so it does not strip a newer
authorization when the stale object snapshot is older than the current message
state. Update `#stripRejectedQuote` to load or compare the latest
existingObject.quoteAuthorizationId?.href against the quote authorization being
revoked before calling updateMessage, and only strip when they match. Use the
existing `#stripRejectedQuote` and onDeleted flow to locate the fix and ensure the
deletion handler ignores outdated quoteId-only matches.
🧹 Nitpick comments (3)
packages/botkit/src/quote-authorization.test.ts (1)

21-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Thin coverage: only the null-targetActorId short-circuit is tested.

The test only exercises the branch where options.targetActorId == null, which short-circuits validateQuoteAuthorization() before any of the URL/origin comparisons run. Given this function is the core FEP-044f gate (blocking unapproved quotes, gating revocations), it would be valuable to also cover: the accepted/true path, an attributionId mismatch, an interactingObjectId/interactionTargetId mismatch, an authorizationId mismatch, and a non-QuoteAuthorization input.

✅ Example additional cases
test("validateQuoteAuthorization() accepts a matching stamp", () => {
  const targetActorId = new URL("https://example.com/users/alice");
  const authorization = new QuoteAuthorization({
    id: new URL("https://example.com/stamps/1"),
    attribution: targetActorId,
    interactingObject: new URL("https://quote.example/notes/1"),
    interactionTarget: new URL("https://example.com/notes/1"),
  });
  assert.ok(
    validateQuoteAuthorization(authorization, {
      quoteId: new URL("https://quote.example/notes/1"),
      targetId: new URL("https://example.com/notes/1"),
      targetActorId,
    }),
  );
});
🤖 Prompt for 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.

In `@packages/botkit/src/quote-authorization.test.ts` around lines 21 - 37, The
current quote authorization test only covers the null targetActorId
short-circuit in validateQuoteAuthorization(), so add coverage for the full
decision path using QuoteAuthorization. Extend quote-authorization.test.ts with
cases for a valid matching authorization that returns true, mismatches on
attributionId, interactingObjectId/interactionTargetId, and authorizationId that
return false, plus a non-QuoteAuthorization input case. Use the existing
validateQuoteAuthorization() helper and QuoteAuthorization constructor to keep
the tests anchored to the same symbols.
packages/botkit/src/bot-impl.test.ts (1)

2865-2879: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing coverage for the findQuoteAuthorizationReferenceAttribution fallback.

This test only covers MigrationGatedRepository tolerating a missing findQuoteAuthorizationReferenceIdentifiers. It doesn't cover the sibling fallback for findQuoteAuthorizationReferenceAttribution, which is the one that actually gates whether onDeleted() can validate/process a revocation (see the related comment in bot-impl.ts). A regression test asserting it returns undefined when the underlying method is absent would help lock in that fail-closed behavior.

🤖 Prompt for 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.

In `@packages/botkit/src/bot-impl.test.ts` around lines 2865 - 2879, Add missing
coverage for the sibling fallback in MigrationGatedRepository: the current test
only verifies findQuoteAuthorizationReferenceIdentifiers is tolerated when
absent, but it should also exercise findQuoteAuthorizationReferenceAttribution
on the same wrapped repository. Update bot-impl.test.ts by extending the
existing MigrationGatedRepository test (or adding a parallel one) to hide
findQuoteAuthorizationReferenceAttribution on the underlying MemoryRepository
and assert the repository returns undefined for a quote stamp URL. Use the
MigrationGatedRepository and onDeleted-related fallback behavior as the target
symbols to keep the regression anchored.
packages/botkit/src/repository.test.ts (1)

60-72: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate hideRepositoryMethods helper across test files.

The same implementation of hideRepositoryMethods is defined in packages/botkit/src/bot-impl.test.ts and packages/botkit/src/instance-routing.test.ts. Since this helper directly encodes the "missing reverse-index method" contract used to test critical fallback behavior (revocation-related), keeping three independent copies risks silent drift if the detection semantics ever need to change.

♻️ Suggested consolidation
-function hideRepositoryMethods(
-  repository: Repository,
-  hiddenMethods: readonly PropertyKey[],
-): Repository {
-  return new Proxy(repository, {
-    get(target, prop, receiver) {
-      if (hiddenMethods.includes(prop)) return undefined;
-      const value = Reflect.get(target, prop, receiver);
-      return typeof value === "function" ? value.bind(target) : value;
-    },
-  });
-}
+import { hideRepositoryMethods } from "./test-utils.ts"; // shared helper
🤖 Prompt for 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.

In `@packages/botkit/src/repository.test.ts` around lines 60 - 72, The
`hideRepositoryMethods` helper is duplicated across the botkit test files, so
consolidate it into a shared test utility and import it from
`repository.test.ts`, `bot-impl.test.ts`, and `instance-routing.test.ts`. Keep
the existing `Proxy`/`get` behavior and `PropertyKey[]` contract unchanged, and
update the affected tests to use the single shared helper so the reverse-index
fallback semantics stay in sync.
🤖 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.

Outside diff comments:
In `@packages/botkit/src/bot-impl.ts`:
- Around line 2456-2482: The fallback in bot-impl.ts silently returns when the
repository lacks the new reverse-index methods, so add a one-time warning for
observability in both findQuoteAuthorizationReferenceAttribution and
findQuoteAuthorizationReferenceIdentifiers. Use the existing BotImpl methods and
the `#repository` capability checks to log once when these optional methods are
missing, making it clear that quote-authorization revocation/cleanup is disabled
for this repository implementation. Keep the compatibility behavior unchanged,
but ensure the operator can detect the fallback through the logger.
- Around line 882-887: Guard the quote revocation path in
onDeleted()/#stripRejectedQuote so it does not strip a newer authorization when
the stale object snapshot is older than the current message state. Update
`#stripRejectedQuote` to load or compare the latest
existingObject.quoteAuthorizationId?.href against the quote authorization being
revoked before calling updateMessage, and only strip when they match. Use the
existing `#stripRejectedQuote` and onDeleted flow to locate the fix and ensure the
deletion handler ignores outdated quoteId-only matches.

---

Nitpick comments:
In `@packages/botkit/src/bot-impl.test.ts`:
- Around line 2865-2879: Add missing coverage for the sibling fallback in
MigrationGatedRepository: the current test only verifies
findQuoteAuthorizationReferenceIdentifiers is tolerated when absent, but it
should also exercise findQuoteAuthorizationReferenceAttribution on the same
wrapped repository. Update bot-impl.test.ts by extending the existing
MigrationGatedRepository test (or adding a parallel one) to hide
findQuoteAuthorizationReferenceAttribution on the underlying MemoryRepository
and assert the repository returns undefined for a quote stamp URL. Use the
MigrationGatedRepository and onDeleted-related fallback behavior as the target
symbols to keep the regression anchored.

In `@packages/botkit/src/quote-authorization.test.ts`:
- Around line 21-37: The current quote authorization test only covers the null
targetActorId short-circuit in validateQuoteAuthorization(), so add coverage for
the full decision path using QuoteAuthorization. Extend
quote-authorization.test.ts with cases for a valid matching authorization that
returns true, mismatches on attributionId,
interactingObjectId/interactionTargetId, and authorizationId that return false,
plus a non-QuoteAuthorization input case. Use the existing
validateQuoteAuthorization() helper and QuoteAuthorization constructor to keep
the tests anchored to the same symbols.

In `@packages/botkit/src/repository.test.ts`:
- Around line 60-72: The `hideRepositoryMethods` helper is duplicated across the
botkit test files, so consolidate it into a shared test utility and import it
from `repository.test.ts`, `bot-impl.test.ts`, and `instance-routing.test.ts`.
Keep the existing `Proxy`/`get` behavior and `PropertyKey[]` contract unchanged,
and update the affected tests to use the single shared helper so the
reverse-index fallback semantics stay in sync.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 381efd78-c38f-407f-820f-aa6eeeebfa2c

📥 Commits

Reviewing files that changed from the base of the PR and between b21b1f1 and 8ecb6aa.

📒 Files selected for processing (10)
  • packages/botkit/src/bot-impl.test.ts
  • packages/botkit/src/bot-impl.ts
  • packages/botkit/src/instance-impl.ts
  • packages/botkit/src/instance-routing.test.ts
  • packages/botkit/src/message-impl.test.ts
  • packages/botkit/src/message-impl.ts
  • packages/botkit/src/quote-authorization.test.ts
  • packages/botkit/src/quote-authorization.ts
  • packages/botkit/src/repository.test.ts
  • packages/botkit/src/repository.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/botkit/src/instance-impl.ts
  • packages/botkit/src/quote-authorization.ts
  • packages/botkit/src/message-impl.test.ts
  • packages/botkit/src/instance-routing.test.ts
  • packages/botkit/src/message-impl.ts
  • packages/botkit/src/repository.ts

@dahlia

dahlia commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@codex review

@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: 8ecb6aa95d

ℹ️ 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/botkit/src/bot-impl.ts Outdated
Comment thread packages/botkit/src/message-impl.ts Outdated
dahlia added 3 commits July 7, 2026 08:12
Stale quote authorization deletes can arrive after a message has already
recorded a newer stamp.  Compare the current stored authorization before
stripping quote metadata so an old delete only removes the old reference.

The migration-gated repository now warns once when a custom repository
omits the optional quote reference index methods, preserving compatibility
while making disabled cleanup visible.

The tests cover the sibling fallback path, the full quote authorization
validator decision table, and the stale delete race.  The shared repository
method-hiding helper keeps the fallback tests aligned.

fedify-dev#33 (review)

Assisted-by: Codex:gpt-5.5
The revoked stamp Delete used to go only to followers, so direct quotes
and mention-expanded audiences could miss the revocation even though they
received the quoted message.

The forwarding path now rebuilds concrete recipients from the stored
message audience and mention tags, while keeping followers as a shared
inbox fan-out when the original audience included them.

fedify-dev#33 (comment)

Assisted-by: Codex:gpt-5.5
Remote quote stamp lookups can reject because the caller aborted the
message materialization. Treating that as an ordinary failed stamp lookup
lets cancelled work continue with a false approval result.

The verification path now rethrows abort failures while still suppressing
ordinary lookup and validation failures as an unapproved quote.

fedify-dev#33 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@dahlia

dahlia commented Jul 6, 2026

Copy link
Copy Markdown
Member Author

@codex review

@coderabbitai coderabbitai 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.

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/botkit/src/quote-authorization.test.ts`:
- Around line 53-98: Add a test case in validateQuoteAuthorization() that
specifically exercises the origin guard in validateQuoteAuthorization by keeping
all other bindings valid but giving the authorization.id a different origin than
targetActorId. Use the existing createAuthorization helper and the
validateQuoteAuthorization test table in quote-authorization.test.ts to forge a
cross-origin stamp, then assert the function returns false for that case.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6cff2a86-b2a0-4abf-b82f-35623d1a9e19

📥 Commits

Reviewing files that changed from the base of the PR and between 8ecb6aa and 9b45faf.

⛔ Files ignored due to path filters (1)
  • deno.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • packages/botkit/src/bot-impl.test.ts
  • packages/botkit/src/bot-impl.ts
  • packages/botkit/src/helpers.ts
  • packages/botkit/src/instance-routing.test.ts
  • packages/botkit/src/message-impl.test.ts
  • packages/botkit/src/message-impl.ts
  • packages/botkit/src/quote-authorization.test.ts
  • packages/botkit/src/repository.test.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/botkit/src/helpers.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/botkit/src/message-impl.test.ts
  • packages/botkit/src/repository.test.ts
  • packages/botkit/src/message-impl.ts
  • packages/botkit/src/bot-impl.test.ts
  • packages/botkit/src/bot-impl.ts

Comment thread packages/botkit/src/quote-authorization.test.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: 9b45faf7cd

ℹ️ 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/botkit/src/bot-impl.ts

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces support for verifying FEP-044f quote authorization stamps on received third-party quote posts and handling revoked quote authorizations, adding the onQuoteRevoked event handler and the Message.quoteApproved property. It also updates Postgres, SQLite, and KV repositories to track quote authorization references. The review feedback suggests guarding against a null or undefined fepQuoteUrl when validating quote authorizations to prevent runtime errors, and optimizing sequential network lookups of mentioned actors in a loop by executing them in parallel using Promise.all.

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/botkit/src/bot-impl.ts
Comment thread packages/botkit/src/bot-impl.ts Outdated
The revocation forwarder now resolves message addressees in parallel,
keeps the original recipient order, and includes the reply target actor
before the quoted actor. That matches the audience used for quote updates
so every server that saw the quote can also see the stamp Delete.

The validation tests also cover cross-origin stamp IDs directly, which
locks down the origin binding separately from the authorization ID match.

fedify-dev#33 (comment)
fedify-dev#33 (comment)
fedify-dev#33 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

@codex review

@dahlia

dahlia commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request implements support for verifying FEP-044f quote authorization stamps on received third-party quote posts and handling revoked stamps. It introduces the onQuoteRevoked event handler, the Message.quoteApproved property, and new repository methods to track and query quote authorization references across bot instances. When a quote authorization is deleted, BotKit now forwards the deletion to the quote's audience and strips the quote target. Feedback on the changes suggests simplifying the abortion check in verifyQuoteApproval to robustly propagate any error when signal?.aborted is true, rather than checking for specific error types.

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/botkit/src/message-impl.ts Outdated

@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: 6000a26c62

ℹ️ 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/botkit/src/bot-impl.ts
Abort handling should not depend on the exact error type thrown by the
remote lookup path. Once the caller's signal is aborted, quote stamp
verification now propagates the error instead of treating it as an
ordinary failed validation.

Quote rejection and revocation also no longer materialize the stripped
message unless a handler is registered. The stored message is still
updated and the audience update is still sent, but handler-only lookup
work is skipped when there is no callback to consume it.

fedify-dev#33 (comment)
fedify-dev#33 (comment)

Assisted-by: Codex:gpt-5.5
@dahlia

dahlia commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@dahlia

dahlia commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

@codex review

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request implements support for verifying and revoking quote authorization stamps under FEP-044f. It introduces the Bot.onQuoteRevoked event handler, the Message.quoteApproved property, and updates the Postgres, SQLite, and KV repositories with reverse indexing methods to track quote authorization references. When a quote authorization is deleted, BotKit now forwards the deletion activity and strips the quote from the bot's post. The review feedback highlights two critical issues in packages/botkit/src/bot-impl.ts where missing null checks on fepQuoteUrl and actor.id could lead to TypeScript compilation errors or runtime TypeErrors.

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/botkit/src/bot-impl.ts
Comment thread packages/botkit/src/bot-impl.ts
@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: af4f38b3fc

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

@dahlia dahlia merged commit 1a0cd9c into fedify-dev:main Jul 7, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Verify third-party quote approvals and handle revocation (FEP-044f)

1 participant