Skip to content

Make the outbox delivery lint rule path-aware #900

Description

@dahlia

Why

The existing outbox listener rule in packages/lint/src/rules/outbox-listener-delivery-required.ts catches a useful class of delivery mistakes, but it currently decides success by finding a ctx.sendActivity() or ctx.forwardActivity()-style call somewhere in the listener source. That keeps the first implementation simple, but it can treat unreachable or unrelated calls as proof that every posted activity is delivered.

This matters because a local outbox handler that accepts a post without actually delivering it creates a confusing ActivityPub failure: the object exists locally, but followers never receive it.

Current code

The rule already handles direct calls, aliases, destructuring, bracket notation, template literals, and named listener callbacks. The related tests live in packages/lint/src/tests/outbox-listener-delivery-required.test.ts.

The next step is not to rewrite the rule from scratch. It is to make the delivery check understand enough control flow to avoid obvious false negatives.

Scope

Please update the rule so that it does not count delivery calls that are clearly outside the listener delivery path. Good starting cases are:

  • ctx.sendActivity() inside a nested helper function that is declared but never called.
  • ctx.forwardActivity() behind if (false) or after an unconditional return.
  • A delivery call that only exists in a callback passed to an unrelated API, such as array.map(() => ctx.sendActivity(...)), when the callback is not awaited or returned.

The implementation can be conservative. It is fine to keep reporting when the rule cannot prove that delivery happens.

Non-goals

Do not try to build a full TypeScript control-flow analyzer. Do not require type information. This rule should keep working in both the Deno lint plugin and the ESLint plugin surfaces.

Suggested checks

Add focused tests in packages/lint/src/tests/outbox-listener-delivery-required.test.ts. Existing positive cases should keep passing, especially the alias and named-listener cases.

Metadata

Metadata

Assignees

No one assigned

    Priority

    Low

    Effort

    High

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions