Skip to content

feat(soup): impl notification filters for foreign entities, github pr's in signal#4059

Open
synoet wants to merge 3 commits into
mainfrom
synoet/macro-1822-featsoup-notificationdone-filter-to-foreign-entities-github-prs-in-soup
Open

feat(soup): impl notification filters for foreign entities, github pr's in signal#4059
synoet wants to merge 3 commits into
mainfrom
synoet/macro-1822-featsoup-notificationdone-filter-to-foreign-entities-github-prs-in-soup

Conversation

@synoet

@synoet synoet commented Jun 15, 2026

Copy link
Copy Markdown
Contributor
  • feat(soup): add notification filters to foreign entity (GitHub PR) queries
  • feat(soup): surface GitHub PR notifications in the inbox Signal tab

claude added 2 commits June 14, 2026 17:08
…eries

Foreign entities (GitHub PRs) fetched from soup can now be filtered by the
requesting user's notification state, matching the done/seen filters already
available for documents, chats, emails, projects, and channels.

- Add `notification_filters` to `ForeignEntityFilters` and expand it into
  `nd`/`ns` AST literals.
- In the foreign entity repo, hoist the notification literals (alongside
  `includes_me`) out of the metadata jsonpath and apply them as `EXISTS`
  predicates against `notification`/`user_notification`, scoped to the
  requesting user and the `foreign_entity` event type. A notification filter
  with no requesting user matches nothing.
- Regenerate the storage/search OpenAPI + TypeScript clients and the sqlx cache.

https://claude.ai/code/session_01V3PQwKGcmnjAdhQDhkG1De
Foreign entities (GitHub PRs) now appear in the inbox Signal tab, gated on
the user's not-done notifications like the other notification-backed types.

- Add `foreignEntityDone`/`foreignEntitySeen` filter-store fields mapping to
  the `fef` target (`nd`/`ns`), backed by the notification filters added to
  `ForeignEntityFilters`.
- Reference `foreignEntityDone: false` in the inbox signal query so foreign
  entities are fetched (and opted past defineQueryFilters' exclusion of
  unreferenced entity types) and gated on not-done notifications.
- Classify foreign entities as signal client-side (`signalFilter`).

Rendering stays gated on the existing supported-foreign-entities flag.

https://claude.ai/code/session_01V3PQwKGcmnjAdhQDhkG1De
@macro-application

Copy link
Copy Markdown

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ac0e10b2-9429-45d1-934a-6d47efdc1f89

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds notification-state filtering (done/seen) for foreign entities across the full stack. On the Rust side, ForeignEntityLiteral gains NotificationDone and NotificationSeen variants; ForeignEntityFilters gains a notification_filters field that is propagated through expand_ast. The Postgres repository introduces a hoisting mechanism to extract these literals from the filter tree into dedicated SQL parameters, and adds per-user EXISTS subqueries over notification/user_notification tables. On the TypeScript side, ScalarFieldFilters is extended with the two new fields, FIELD_CONFIG maps them to backend field names, the inbox filter preset includes foreignEntityDone: false, and signalFilter now classifies foreign entities as signal rather than non-signal.

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title exceeds the 72-character limit at 81 characters and doesn't properly follow conventional commits format. Shorten the title to under 72 characters while maintaining the conventional commits format, e.g., 'feat(soup): add notification filters for foreign entities' or 'feat(soup): surface GitHub PRs in inbox signal'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly relates to the changeset, detailing notification filtering for foreign entities and their integration into the Signal tab.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
js/app/packages/app/component/next-soup/filters/inbox-filters.ts (1)

105-135: Use match from ts-pattern instead of a native exhaustive switch in signalFilter.

The switch statement covers all cases of entity.type (channel, chat, document, email, project, channel_message, call, crm_company, crm_contact, automation, foreign). Per project convention, this exhaustive branching should be expressed with match(...).exhaustive() for consistency and compile-time exhaustiveness guarantees.

🤖 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 `@js/app/packages/app/component/next-soup/filters/inbox-filters.ts` around
lines 105 - 135, Replace the exhaustive switch statement in the signalFilter
function with a match expression from the ts-pattern library. Convert each case
into a pattern entry using the match function, maintaining the same return
values for each entity type (channel, chat, document, email, project,
channel_message, call, crm_company, crm_contact, automation, and foreign), and
append .exhaustive() to the match chain to ensure compile-time exhaustiveness
checking per project convention.

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 `@rust/cloud-storage/foreign_entity/src/outbound/pg_foreign_entity_repo.rs`:
- Around line 61-70: The and method incorrectly merges conflicting
notification_done and notification_seen predicates by using Option::or, which
drops one side when both are Some. Instead of using or, check if both
notification_done values are Some and have conflicting boolean values (one true,
one false), and similarly for notification_seen; when conflicts are detected,
the filter should be marked as unsatisfiable. After fixing the and method to
properly detect unsatisfiable conditions, update the
get_foreign_entities_for_user method to return Ok(Vec::new()) when the resulting
filter is unsatisfiable.

---

Nitpick comments:
In `@js/app/packages/app/component/next-soup/filters/inbox-filters.ts`:
- Around line 105-135: Replace the exhaustive switch statement in the
signalFilter function with a match expression from the ts-pattern library.
Convert each case into a pattern entry using the match function, maintaining the
same return values for each entity type (channel, chat, document, email,
project, channel_message, call, crm_company, crm_contact, automation, and
foreign), and append .exhaustive() to the match chain to ensure compile-time
exhaustiveness checking per project convention.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f4271965-c238-4f89-b803-81202c42f2d5

📥 Commits

Reviewing files that changed from the base of the PR and between c955d44 and b14984d.

⛔ Files ignored due to path filters (4)
  • js/app/packages/service-clients/service-search/generated/models/foreignEntityFilters.ts is excluded by !**/generated/**
  • js/app/packages/service-clients/service-storage/generated/schemas/foreignEntityFilters.ts is excluded by !**/generated/**
  • js/app/packages/service-clients/service-storage/generated/zod.ts is excluded by !**/generated/**
  • rust/cloud-storage/.sqlx/query-d45423d79a30cd22b475c082ccb2f2d433780b1d32441dcddc6350501de54260.json is excluded by !**/.sqlx/**
📒 Files selected for processing (13)
  • js/app/packages/app/component/app-sidebar/soup-filter-presets.ts
  • js/app/packages/app/component/next-soup/filters/configs/general.ts
  • js/app/packages/app/component/next-soup/filters/filter-store/compile.ts
  • js/app/packages/app/component/next-soup/filters/filter-store/types.ts
  • js/app/packages/app/component/next-soup/filters/inbox-filters.ts
  • js/app/packages/service-clients/service-search/openapi.json
  • js/app/packages/service-clients/service-storage/openapi.json
  • rust/cloud-storage/foreign_entity/src/outbound/pg_foreign_entity_repo.rs
  • rust/cloud-storage/foreign_entity/src/outbound/pg_foreign_entity_repo/tests.rs
  • rust/cloud-storage/item_filters/src/ast/foreign_entity.rs
  • rust/cloud-storage/item_filters/src/ast/tests.rs
  • rust/cloud-storage/item_filters/src/lib.rs
  • rust/cloud-storage/soup/src/domain/service/tests.rs

… unsatisfiable

Combining hoisted notification predicates with `Option::or` silently dropped
one side, so a contradictory AST like `NotificationDone(true) AND
NotificationDone(false)` collapsed to a single-sided `done = true` predicate
instead of matching nothing. Detect conflicting done/seen predicates while
folding the AND spine and short-circuit to an empty result.

Only reachable via a hand-crafted AST (the typed ForeignEntityFilters emits at
most one done/seen literal each), but the silent collapse was misleading.

https://claude.ai/code/session_01V3PQwKGcmnjAdhQDhkG1De
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants