Skip to content

Take the content moderation rules from the SDK - #3503

Merged
feruzm merged 2 commits into
developmentfrom
bugfix/shared-moderation-rules
Aug 15, 2026
Merged

Take the content moderation rules from the SDK#3503
feruzm merged 2 commits into
developmentfrom
bugfix/shared-moderation-rules

Conversation

@feruzm

@feruzm feruzm commented Aug 15, 2026

Copy link
Copy Markdown
Member

Closes #3502. Consumer side of ecency/vision-web#1492.

Draft: blocked on the SDK publish. The code calls getContentModerationReason from @ecency/sdk, which does not exist in a published version yet. Once ecency/vision-web#1493 is labelled patch:sdk, merged and published, this needs one more commit bumping the dependency and yarn.lock. CI installs from the lockfile, so it stays red until then. Verified locally against a build of the web PR's SDK: 872 unit tests, yarn typecheck clean, lint clean.

The app carried its own copy of the rules and it had drifted from the website:

Case Mobile before Now (both clients)
Downvoted net_rshares < -7B and > 3 voters < -10B and >= 5 voters
Low reputation alone dimmed under reputation 25 not a signal
Low reputation + outbound link no such check dimmed under reputation 30
Precedence moderator, low reputation, downvotes moderator, downvotes, low trust

The old precedence was the worst of it: downvotes sink an author's reputation, so a heavily downvoted post read "Content from a low reputation account" here and "Downvoted by users" on the website.

Changes

  • parsePost and parseComment call getContentModerationReason; the local thresholds and getMutedReason are gone
  • MutedReason is now the SDK's ContentModerationReason re-exported under the same local name, so components keep reading one mobile-side symbol
  • new post.muted_low_trust string for the low-trust case
  • reasons written by older app versions live on in LegacyMutedReason, so posts already in the persisted query cache keep their copy instead of falling back to the generic message until the cache turns over
  • the feed's mute filter uses the shared isAuthorMuted. Behaviour is unchanged here, the website moves to match it
  • rule tests moved to the SDK next to the implementation; the parser tests keep covering how a parsed post carries the reason, including the cross-post cases

Worth knowing

Low-trust detection scans the post body for outbound links, which is new work in parsePost. For lists the body is raw markdown, for a single post it has already been through renderPostBody, and the check matches links in both.

Not verified on a device yet.

Summary by CodeRabbit

  • Bug Fixes
    • Improved muted-post messaging for low-trust content and legacy low-reputation moderation reasons.
    • Corrected mute filtering for regular and promoted posts.
    • Improved recognition of moderation and low-reputation conditions, including outbound-link requirements.
    • Preserved generic moderation messaging when no specific mute reason is available.

The app carried its own copy of the rules deciding when content is dimmed, and
it had drifted from the website: downvoted meant -7B rshares and 4 voters here
against -10B and 5 there, every author under reputation 25 was dimmed no matter
what they wrote, and the low-trust check did not exist at all. Low reputation
was also checked before downvotes, so a heavily downvoted post read "low
reputation account" here and "Downvoted by users" on the website. Downvotes sink
reputation, so that mislabelled the common case.

parsePost and parseComment now call getContentModerationReason from the SDK, and
the local thresholds are gone. MutedReason becomes the SDK enum under the same
local name, so components keep reading one mobile-side symbol. The feed's own
mute filter calls the shared isAuthorMuted, and the website now drops muted
authors from lists the same way instead of dimming them.

Two visible changes: low reputation on its own no longer dims anything, it needs
an outbound promotional link too, and heavily downvoted content is flagged as
downvoted rather than as a low reputation account. Reasons written by older app
versions are kept in LegacyMutedReason so cached posts keep their copy until the
cache turns over.

The rule tests moved to the SDK next to the implementation.
@feruzm
feruzm marked this pull request as ready for review August 15, 2026 07:36
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Aug 15, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Author check ordered wrongly 🐞 Bug ☼ Reliability
Description
postsListContainer calls isAuthorMuted(item.author, mutes) before verifying item.author
exists, so entries with a missing/empty author will still invoke the SDK helper. If isAuthorMuted
assumes a non-empty string, this can throw or misclassify items before they’re filtered out,
breaking feed rendering.
Code

src/components/postsList/container/postsListContainer.tsx[R109-111]

+    // Authors the viewer muted are dropped from the list rather than dimmed, and the
+    // website now does the same. Shared helper so both stay on one definition.
+    _data = _data.filter((item) => !isAuthorMuted(item.author, mutes) && !!item?.author);
Relevance

●●● Strong

Team has accepted defensive guard fixes in postsListContainer; reorder to check author before helper
call.

PR-#3103

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new filter evaluates the SDK helper before the author guard (left-to-right && evaluation),
and other code paths explicitly account for missing author/permlink, indicating these partial shapes
can occur in practice.

src/components/postsList/container/postsListContainer.tsx[103-123]
src/components/postCard/children/postCardContent.tsx[42-46]
PR-#3186

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`isAuthorMuted(item.author, mutes)` is evaluated before `!!item?.author`, so the helper is invoked with a potentially missing/empty author.
### Issue Context
This affects both the main `_data` filter and the promoted-posts filter.
### Fix Focus Areas
- src/components/postsList/container/postsListContainer.tsx[109-121]
### Suggested change
Reorder the predicate so author validation happens first:
- `_data = _data.filter((item) => !!item?.author && !isAuthorMuted(item.author, mutes));`
- Apply the same ordering in the `_promotedPosts` filter.
If `isAuthorMuted` accepts only strings, consider normalizing: `const author = item?.author ?? "";` and keep the explicit `!!author` guard before calling the helper.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Author check ordered wrongly 🐞 Bug ☼ Reliability
Description
postsListContainer calls isAuthorMuted(item.author, mutes) before verifying item.author
exists, so entries with a missing/empty author will still invoke the SDK helper. If isAuthorMuted
assumes a non-empty string, this can throw or misclassify items before they’re filtered out,
breaking feed rendering.
Code

src/components/postsList/container/postsListContainer.tsx[R109-111]

+    // Authors the viewer muted are dropped from the list rather than dimmed, and the
+    // website now does the same. Shared helper so both stay on one definition.
+    _data = _data.filter((item) => !isAuthorMuted(item.author, mutes) && !!item?.author);
Relevance

●●● Strong

Team has accepted defensive guard fixes in postsListContainer; reorder to check author before helper
call.

PR-#3103

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new filter evaluates the SDK helper before the author guard (left-to-right && evaluation),
and other code paths explicitly account for missing author/permlink, indicating these partial shapes
can occur in practice.

src/components/postsList/container/postsListContainer.tsx[103-123]
src/components/postCard/children/postCardContent.tsx[42-46]
PR-#3186

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`isAuthorMuted(item.author, mutes)` is evaluated before `!!item?.author`, so the helper is invoked with a potentially missing/empty author.
### Issue Context
This affects both the main `_data` filter and the promoted-posts filter.
### Fix Focus Areas
- src/components/postsList/container/postsListContainer.tsx[109-121]
### Suggested change
Reorder the predicate so author validation happens first:
- `_data = _data.filter((item) => !!item?.author && !isAuthorMuted(item.author, mutes));`
- Apply the same ordering in the `_promotedPosts` filter.
If `isAuthorMuted` accepts only strings, consider normalizing: `const author = item?.author ?? "";` and keep the explicit `!!author` guard before calling the helper.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. SDK exports may be missing ✓ Resolved 🐞 Bug ☼ Reliability
Description
This PR imports/re-exports getContentModerationReason, ContentModerationReason, and
isAuthorMuted from @ecency/sdk, while the repo lockfile pins @ecency/sdk to 2.3.86. If those
named exports are not present in the locked version, TypeScript/bundling will fail until
package.json/yarn.lock are bumped to a version that contains them.
Code

src/utils/postParser.tsx[4]

+import { getContentModerationReason } from '@ecency/sdk';
Relevance

●●● Strong

They routinely require ensuring SDK exports exist and bumping @ecency/sdk + yarn.lock to keep
CI/build green.

PR-#3108
PR-#3412

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR introduces new imports/re-exports from @ecency/sdk, while the project’s dependency and
lockfile currently resolve @ecency/sdk to 2.3.86, so compatibility must be ensured against that
resolved version.

src/utils/postParser.tsx[1-5]
src/providers/hive/hive.types.ts[14-24]
src/components/postsList/container/postsListContainer.tsx[21-23]
package.json[37-42]
yarn.lock[1213-1216]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New code depends on specific named exports from `@ecency/sdk`. The repo currently resolves `@ecency/sdk` to a specific locked version; if that version doesn’t ship these exports, builds/typecheck will fail.
### Issue Context
The PR adds new imports/re-exports from `@ecency/sdk` in multiple files, but the lockfile still resolves `@ecency/sdk` to 2.3.86.
### Fix Focus Areas
- src/utils/postParser.tsx[1-5]
- src/providers/hive/hive.types.ts[14-24]
- src/components/postsList/container/postsListContainer.tsx[21-23]
- package.json[37-42]
- yarn.lock[1213-1216]
### Suggested change
Once the SDK release containing these symbols is published:
1. Update `package.json` `@ecency/sdk` version to the minimum published version that exports:
- `getContentModerationReason`
- `ContentModerationReason`
- `isAuthorMuted`
2. Regenerate and commit `yarn.lock` so CI installs the compatible SDK.
3. Ensure the exported enum members used in code/tests (e.g., `MutedReason.MOD_MUTED`, `MutedReason.LOW_TRUST`) exist in that SDK version.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. MutedReason type widened 📘 Rule violation ⚙ Maintainability
Description
MutedReason was changed from a local enum to a re-export of the SDK’s ContentModerationReason,
which expands the set of possible values (e.g., new members like LOW_TRUST/MOD_MUTED). This
loosens an existing TypeScript type annotation and can break assumptions in code paths that
previously only handled the narrower enum.
Code

src/providers/hive/hive.types.ts[R14-15]

+export { ContentModerationReason as MutedReason } from '@ecency/sdk';
+
Relevance

●●● Strong

Change is intentional for SDK alignment; code updated to handle new enum members and legacy cache
values.

PR-#3138
PR-#3194

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2667850 forbids widening existing type annotations. The diff changes MutedReason from a
locally-defined enum to a broader SDK type, and new code uses additional enum members (LOW_TRUST,
MOD_MUTED) that were not part of the prior local enum.

Rule 2667850: Do not loosen existing TypeScript type annotations
src/providers/hive/hive.types.ts[14-24]
src/components/postCard/children/postCardContent.tsx[106-113]
src/utils/postParser.test.ts[284-300]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`MutedReason` was widened by changing it from a local enum to a re-export of `ContentModerationReason` from `@ecency/sdk`. This violates the rule against loosening existing TypeScript type annotations.
## Issue Context
The PR introduces new moderation reasons (e.g., `LOW_TRUST`, `MOD_MUTED`) by swapping the old enum out for an SDK type, which increases the allowed value set for `MutedReason`.
## Fix Focus Areas
- src/providers/hive/hive.types.ts[14-24]
- src/components/postCard/children/postCardContent.tsx[106-113]
- src/utils/postParser.test.ts[284-300]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. SDK exports may be missing ✓ Resolved 🐞 Bug ☼ Reliability
Description
This PR imports/re-exports getContentModerationReason, ContentModerationReason, and
isAuthorMuted from @ecency/sdk, while the repo lockfile pins @ecency/sdk to 2.3.86. If those
named exports are not present in the locked version, TypeScript/bundling will fail until
package.json/yarn.lock are bumped to a version that contains them.
Code

src/utils/postParser.tsx[4]

+import { getContentModerationReason } from '@ecency/sdk';
Relevance

●●● Strong

They routinely require ensuring SDK exports exist and bumping @ecency/sdk + yarn.lock to keep
CI/build green.

PR-#3108
PR-#3412

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR introduces new imports/re-exports from @ecency/sdk, while the project’s dependency and
lockfile currently resolve @ecency/sdk to 2.3.86, so compatibility must be ensured against that
resolved version.

src/utils/postParser.tsx[1-5]
src/providers/hive/hive.types.ts[14-24]
src/components/postsList/container/postsListContainer.tsx[21-23]
package.json[37-42]
yarn.lock[1213-1216]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New code depends on specific named exports from `@ecency/sdk`. The repo currently resolves `@ecency/sdk` to a specific locked version; if that version doesn’t ship these exports, builds/typecheck will fail.
### Issue Context
The PR adds new imports/re-exports from `@ecency/sdk` in multiple files, but the lockfile still resolves `@ecency/sdk` to 2.3.86.
### Fix Focus Areas
- src/utils/postParser.tsx[1-5]
- src/providers/hive/hive.types.ts[14-24]
- src/components/postsList/container/postsListContainer.tsx[21-23]
- package.json[37-42]
- yarn.lock[1213-1216]
### Suggested change
Once the SDK release containing these symbols is published:
1. Update `package.json` `@ecency/sdk` version to the minimum published version that exports:
 - `getContentModerationReason`
 - `ContentModerationReason`
 - `isAuthorMuted`
2. Regenerate and commit `yarn.lock` so CI installs the compatible SDK.
3. Ensure the exported enum members used in code/tests (e.g., `MutedReason.MOD_MUTED`, `MutedReason.LOW_TRUST`) exist in that SDK version.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@feruzm
feruzm marked this pull request as draft August 15, 2026 07:36
@qodo-code-review

qodo-code-review Bot commented Aug 15, 2026

Copy link
Copy Markdown

PR Summary by Qodo

Use SDK content moderation rules for consistent dimming and mute reasons

🐞 Bug fix 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Use SDK moderation rules for posts/comments to match website behavior.
• Add low-trust moderation reason and localized hint text.
• Preserve legacy cached reasons and share mute-author filtering via SDK helper.
Diagram

graph TD
  A["Post/Comment parser"] --> B["SDK moderation rules"] --> C["mutedReason + isMuted"] --> D["PostCard hint UI"]
  E["PostsList feed"] --> F["SDK mute filter"]
  D --> G["i18n strings"]
  C --> H["Local types shim"]
  H --> D
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Keep mobile-only moderation thresholds
  • ➕ No dependency on SDK release cadence
  • ➕ Avoids potential behavior changes from shared rules affecting mobile unexpectedly
  • ➖ Rules drift between clients (the issue this PR addresses)
  • ➖ Harder to test/maintain duplicated logic across codebases
2. Server-driven moderation config (remote thresholds/rules)
  • ➕ Can update thresholds without app release
  • ➕ Centralizes rules without requiring SDK updates
  • ➖ Adds runtime dependency and caching/versioning complexity
  • ➖ Harder to ensure deterministic behavior offline and in unit tests

Recommendation: Prefer the PR’s approach: using SDK-owned rules is the best way to eliminate drift and keep web/mobile consistent while still being testable locally. The main operational risk is SDK version availability—plan a follow-up dependency bump once the SDK publishes getContentModerationReason/isAuthorMuted, and consider temporarily pinning to a commit/patch if CI must be green before the publish.

Files changed (7) +66 / -103

Bug fix (2) +10 / -7
postCardContent.tsxMap SDK moderation reasons to updated dimming hint copy +7/-4

Map SDK moderation reasons to updated dimming hint copy

• Updates the muted hint text mapping to support the SDK’s reason set, including a new LOW_TRUST case. Introduces LegacyMutedReason handling so cached posts from older app versions still render the previous low-reputation copy when present.

src/components/postCard/children/postCardContent.tsx

postOptionsModal.tsxAvoid offering community unmute for non-moderator dimming reasons +3/-3

Avoid offering community unmute for non-moderator dimming reasons

• Clarifies (and preserves) the logic that uses stats.gray instead of parsed isMuted when deciding whether to show community unmute actions. This prevents downvoted/low-trust dimming from being treated as a moderator mute.

src/components/postOptionsModal/container/postOptionsModal.tsx

Refactor (3) +24 / -48
postsListContainer.tsxUse SDK helper for author-mute filtering in feed lists +5/-7

Use SDK helper for author-mute filtering in feed lists

• Replaces manual author-mute checks with isAuthorMuted from @ecency/sdk for both regular and promoted post lists. Keeps behavior the same while aligning definition with other clients.

src/components/postsList/container/postsListContainer.tsx

hive.types.tsRe-export SDK moderation enum and keep legacy reason values +14/-7

Re-export SDK moderation enum and keep legacy reason values

• Replaces the local MutedReason enum with a re-export of ContentModerationReason from @ecency/sdk to keep consumers using a single local symbol. Adds LegacyMutedReason to support rendering previously-cached reasons from older app versions.

src/providers/hive/hive.types.ts

postParser.tsxDelegate post/comment moderation reason calculation to the SDK +5/-34

Delegate post/comment moderation reason calculation to the SDK

• Removes local moderation thresholds and getMutedReason implementation. parsePost and parseComment now call getContentModerationReason from @ecency/sdk to assign mutedReason/isMuted consistently with the website.

src/utils/postParser.tsx

Tests (1) +31 / -48
postParser.test.tsUpdate parser moderation tests to reflect SDK rules and thresholds +31/-48

Update parser moderation tests to reflect SDK rules and thresholds

• Removes tests for the deleted getMutedReason helper and updates parsePost tests to assert the SDK’s moderation reasons and new thresholds. Adds coverage for low-trust (low rep + outbound link) and ensures cross-post moderation follows the displayed original entry.

src/utils/postParser.test.ts

Documentation (1) +1 / -0
en-US.jsonAdd low-trust moderation hint string +1/-0

Add low-trust moderation hint string

• Adds a new localized string (post.muted_low_trust) for the low-trust moderation reason shown when dimming content.

src/config/locales/en-US.json

@qodo-code-review

qodo-code-review Bot commented Aug 15, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Author check ordered wrongly 🐞 Bug ☼ Reliability
Description
postsListContainer calls isAuthorMuted(item.author, mutes) before verifying item.author
exists, so entries with a missing/empty author will still invoke the SDK helper. If isAuthorMuted
assumes a non-empty string, this can throw or misclassify items before they’re filtered out,
breaking feed rendering.
Code

src/components/postsList/container/postsListContainer.tsx[R109-111]

+    // Authors the viewer muted are dropped from the list rather than dimmed, and the
+    // website now does the same. Shared helper so both stay on one definition.
+    _data = _data.filter((item) => !isAuthorMuted(item.author, mutes) && !!item?.author);
Relevance

●●● Strong

Team has accepted defensive guard fixes in postsListContainer; reorder to check author before helper
call.

PR-#3103

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new filter evaluates the SDK helper before the author guard (left-to-right && evaluation),
and other code paths explicitly account for missing author/permlink, indicating these partial shapes
can occur in practice.

src/components/postsList/container/postsListContainer.tsx[103-123]
src/components/postCard/children/postCardContent.tsx[42-46]
PR-#3186

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`isAuthorMuted(item.author, mutes)` is evaluated before `!!item?.author`, so the helper is invoked with a potentially missing/empty author.

### Issue Context
This affects both the main `_data` filter and the promoted-posts filter.

### Fix Focus Areas
- src/components/postsList/container/postsListContainer.tsx[109-121]

### Suggested change
Reorder the predicate so author validation happens first:
- `_data = _data.filter((item) => !!item?.author && !isAuthorMuted(item.author, mutes));`
- Apply the same ordering in the `_promotedPosts` filter.

If `isAuthorMuted` accepts only strings, consider normalizing: `const author = item?.author ?? "";` and keep the explicit `!!author` guard before calling the helper.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. MutedReason type widened ✗ Dismissed 📘 Rule violation ⚙ Maintainability ⭐ New
Description
MutedReason was changed from a local enum to a re-export of the SDK’s ContentModerationReason,
which expands the set of possible values (e.g., new members like LOW_TRUST/MOD_MUTED). This
loosens an existing TypeScript type annotation and can break assumptions in code paths that
previously only handled the narrower enum.
Code

src/providers/hive/hive.types.ts[R14-15]

+export { ContentModerationReason as MutedReason } from '@ecency/sdk';
+
Relevance

●●● Strong

Change is intentional for SDK alignment; code updated to handle new enum members and legacy cache
values.

PR-#3138
PR-#3194

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2667850 forbids widening existing type annotations. The diff changes MutedReason from a
locally-defined enum to a broader SDK type, and new code uses additional enum members (LOW_TRUST,
MOD_MUTED) that were not part of the prior local enum.

Rule 2667850: Do not loosen existing TypeScript type annotations
src/providers/hive/hive.types.ts[14-24]
src/components/postCard/children/postCardContent.tsx[106-113]
src/utils/postParser.test.ts[284-300]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`MutedReason` was widened by changing it from a local enum to a re-export of `ContentModerationReason` from `@ecency/sdk`. This violates the rule against loosening existing TypeScript type annotations.

## Issue Context
The PR introduces new moderation reasons (e.g., `LOW_TRUST`, `MOD_MUTED`) by swapping the old enum out for an SDK type, which increases the allowed value set for `MutedReason`.

## Fix Focus Areas
- src/providers/hive/hive.types.ts[14-24]
- src/components/postCard/children/postCardContent.tsx[106-113]
- src/utils/postParser.test.ts[284-300]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. SDK exports may be missing ✓ Resolved 🐞 Bug ☼ Reliability
Description
This PR imports/re-exports getContentModerationReason, ContentModerationReason, and
isAuthorMuted from @ecency/sdk, while the repo lockfile pins @ecency/sdk to 2.3.86. If those
named exports are not present in the locked version, TypeScript/bundling will fail until
package.json/yarn.lock are bumped to a version that contains them.
Code

src/utils/postParser.tsx[4]

+import { getContentModerationReason } from '@ecency/sdk';
Relevance

●●● Strong

They routinely require ensuring SDK exports exist and bumping @ecency/sdk + yarn.lock to keep
CI/build green.

PR-#3108
PR-#3412

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR introduces new imports/re-exports from @ecency/sdk, while the project’s dependency and
lockfile currently resolve @ecency/sdk to 2.3.86, so compatibility must be ensured against that
resolved version.

src/utils/postParser.tsx[1-5]
src/providers/hive/hive.types.ts[14-24]
src/components/postsList/container/postsListContainer.tsx[21-23]
package.json[37-42]
yarn.lock[1213-1216]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
New code depends on specific named exports from `@ecency/sdk`. The repo currently resolves `@ecency/sdk` to a specific locked version; if that version doesn’t ship these exports, builds/typecheck will fail.

### Issue Context
The PR adds new imports/re-exports from `@ecency/sdk` in multiple files, but the lockfile still resolves `@ecency/sdk` to 2.3.86.

### Fix Focus Areas
- src/utils/postParser.tsx[1-5]
- src/providers/hive/hive.types.ts[14-24]
- src/components/postsList/container/postsListContainer.tsx[21-23]
- package.json[37-42]
- yarn.lock[1213-1216]

### Suggested change
Once the SDK release containing these symbols is published:
1. Update `package.json` `@ecency/sdk` version to the minimum published version that exports:
  - `getContentModerationReason`
  - `ContentModerationReason`
  - `isAuthorMuted`
2. Regenerate and commit `yarn.lock` so CI installs the compatible SDK.
3. Ensure the exported enum members used in code/tests (e.g., `MutedReason.MOD_MUTED`, `MutedReason.LOW_TRUST`) exist in that SDK version.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
✅ Compliance rules (platform): 43 rules
✅ Skills: 5 invoked
  add-feature
  add-mutation
  add-query
  add-sheet
  code-review
✅ Web pages:
  +9 more
Review mode: ⚖️ Balanced: Behavioral moderation changes span parsing, persisted-cache compatibility, feed filtering, UI messaging, and an SDK contract; this carries real cross-cutting risk, but not enough independent logic density to justify redundant extended passes.

Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous review results

Review updated until commit 32e2e6e

Results up to commit 9f856b9 ⚖️ Balanced


🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Author check ordered wrongly 🐞 Bug ☼ Reliability
Description
postsListContainer calls isAuthorMuted(item.author, mutes) before verifying item.author
exists, so entries with a missing/empty author will still invoke the SDK helper. If isAuthorMuted
assumes a non-empty string, this can throw or misclassify items before they’re filtered out,
breaking feed rendering.
Code

src/components/postsList/container/postsListContainer.tsx[R109-111]

+    // Authors the viewer muted are dropped from the list rather than dimmed, and the
+    // website now does the same. Shared helper so both stay on one definition.
+    _data = _data.filter((item) => !isAuthorMuted(item.author, mutes) && !!item?.author);
Relevance

●●● Strong

Team has accepted defensive guard fixes in postsListContainer; reorder to check author before helper
call.

PR-#3103

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new filter evaluates the SDK helper before the author guard (left-to-right && evaluation),
and other code paths explicitly account for missing author/permlink, indicating these partial shapes
can occur in practice.

src/components/postsList/container/postsListContainer.tsx[103-123]
src/components/postCard/children/postCardContent.tsx[42-46]
PR-#3186

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`isAuthorMuted(item.author, mutes)` is evaluated before `!!item?.author`, so the helper is invoked with a potentially missing/empty author.

### Issue Context
This affects both the main `_data` filter and the promoted-posts filter.

### Fix Focus Areas
- src/components/postsList/container/postsListContainer.tsx[109-121]

### Suggested change
Reorder the predicate so author validation happens first:
- `_data = _data.filter((item) => !!item?.author && !isAuthorMuted(item.author, mutes));`
- Apply the same ordering in the `_promotedPosts` filter.

If `isAuthorMuted` accepts only strings, consider normalizing: `const author = item?.author ?? "";` and keep the explicit `!!author` guard before calling the helper.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended
2. SDK exports may be missing ✓ Resolved 🐞 Bug ☼ Reliability
Description
This PR imports/re-exports getContentModerationReason, ContentModerationReason, and
isAuthorMuted from @ecency/sdk, while the repo lockfile pins @ecency/sdk to 2.3.86. If those
named exports are not present in the locked version, TypeScript/bundling will fail until
package.json/yarn.lock are bumped to a version that contains them.
Code

src/utils/postParser.tsx[4]

+import { getContentModerationReason } from '@ecency/sdk';
Relevance

●●● Strong

They routinely require ensuring SDK exports exist and bumping @ecency/sdk + yarn.lock to keep
CI/build green.

PR-#3108
PR-#3412

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR introduces new imports/re-exports from @ecency/sdk, while the project’s dependency and
lockfile currently resolve @ecency/sdk to 2.3.86, so compatibility must be ensured against that
resolved version.

src/utils/postParser.tsx[1-5]
src/providers/hive/hive.types.ts[14-24]
src/components/postsList/container/postsListContainer.tsx[21-23]
package.json[37-42]
yarn.lock[1213-1216]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
New code depends on specific named exports from `@ecency/sdk`. The repo currently resolves `@ecency/sdk` to a specific locked version; if that version doesn’t ship these exports, builds/typecheck will fail.

### Issue Context
The PR adds new imports/re-exports from `@ecency/sdk` in multiple files, but the lockfile still resolves `@ecency/sdk` to 2.3.86.

### Fix Focus Areas
- src/utils/postParser.tsx[1-5]
- src/providers/hive/hive.types.ts[14-24]
- src/components/postsList/container/postsListContainer.tsx[21-23]
- package.json[37-42]
- yarn.lock[1213-1216]

### Suggested change
Once the SDK release containing these symbols is published:
1. Update `package.json` `@ecency/sdk` version to the minimum published version that exports:
  - `getContentModerationReason`
  - `ContentModerationReason`
  - `isAuthorMuted`
2. Regenerate and commit `yarn.lock` so CI installs the compatible SDK.
3. Ensure the exported enum members used in code/tests (e.g., `MutedReason.MOD_MUTED`, `MutedReason.LOW_TRUST`) exist in that SDK version.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment on lines +109 to +111
// Authors the viewer muted are dropped from the list rather than dimmed, and the
// website now does the same. Shared helper so both stay on one definition.
_data = _data.filter((item) => !isAuthorMuted(item.author, mutes) && !!item?.author);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Author check ordered wrongly 🐞 Bug ☼ Reliability

postsListContainer calls isAuthorMuted(item.author, mutes) before verifying item.author
exists, so entries with a missing/empty author will still invoke the SDK helper. If isAuthorMuted
assumes a non-empty string, this can throw or misclassify items before they’re filtered out,
breaking feed rendering.
Agent Prompt
### Issue description
`isAuthorMuted(item.author, mutes)` is evaluated before `!!item?.author`, so the helper is invoked with a potentially missing/empty author.

### Issue Context
This affects both the main `_data` filter and the promoted-posts filter.

### Fix Focus Areas
- src/components/postsList/container/postsListContainer.tsx[109-121]

### Suggested change
Reorder the predicate so author validation happens first:
- `_data = _data.filter((item) => !!item?.author && !isAuthorMuted(item.author, mutes));`
- Apply the same ordering in the `_promotedPosts` filter.

If `isAuthorMuted` accepts only strings, consider normalizing: `const author = item?.author ?? "";` and keep the explicit `!!author` guard before calling the helper.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Half right, and worth fixing, though not for the stated reason. isAuthorMuted is null-safe on its own:

return !!author && !!mutedAuthors?.includes(author);

so an entry with a missing or empty author cannot throw there or be misclassified; it returns false and the !!item?.author check then drops the item.

What is real is the ordering: item.author is dereferenced twice before the ?. that exists to tolerate a nullish item, so a null entry would take the feed down at the dereference rather than being filtered out. That predates this PR (the previous line was !isMuted && !!item?.author), but it reads as the opposite of what the code means.

Fixed in #3504, guard first in both the main filter and the promoted one.

Comment thread src/utils/postParser.tsx
@feruzm
feruzm marked this pull request as ready for review August 15, 2026 08:37
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Aug 15, 2026

Copy link
Copy Markdown

Code Review by Qodo

Grey Divider

New Review Started

This review has been superseded by a new analysis

Grey Divider

Qodo Logo

@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: 9f856b9a18

ℹ️ 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 src/utils/postParser.tsx
import { get } from 'lodash';
import { Platform } from 'react-native';
import { postBodySummary, renderPostBody, catchPostImage } from '@ecency/render-helper';
import { getContentModerationReason } from '@ecency/sdk';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Bump the SDK before importing the moderation API

Every clean install remains locked to @ecency/sdk 2.3.86, which exports none of getContentModerationReason, isAuthorMuted, or ContentModerationReason; consequently yarn typecheck reports TS2305 at all three new imports and the app cannot build. Update package.json and yarn.lock to the SDK release containing these APIs as part of this change.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Right, and resolved in 32e2e6e before merge: @ecency/sdk 2.3.87 (published from ecency/vision-web#1493 under the patch:sdk label) is now pinned in both package.json and yarn.lock. The PR was open as a draft precisely because the SDK release did not exist yet.

The module the parser now calls landed in 2.3.87. Dependencies are unchanged
between 2.3.86 and 2.3.87, so the lockfile entry only moves version, resolved
and integrity; verified against the published tarball, whose sha1 matches the
resolved hash.
@feruzm

feruzm commented Aug 15, 2026

Copy link
Copy Markdown
Member Author

Unblocked and ready for review. @ecency/sdk 2.3.87 is on npm (ecency/vision-web#1493 merged with the patch:sdk label, which rebuilt dist and published), so 32e2e6e bumps the dependency and the lockfile.

Dependencies are identical between 2.3.86 and 2.3.87, so the yarn.lock entry only moves version, resolved and integrity. I verified that against the published tarball rather than trusting the edit: its sha1 is 1701b805..., matching the resolved hash, and it contains the moderation module.

Re-verified with the published package rather than my local build of it: 872 unit tests pass, tsc --noEmit clean, lint clean.

Still not verified on a device. Merged is not shipped here, this needs a build before anyone can see it.

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f661748-2a65-452d-a45c-1ce70f652f61

📥 Commits

Reviewing files that changed from the base of the PR and between 9f856b9 and 32e2e6e.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (1)
  • package.json

📝 Walkthrough

Walkthrough

The parser now uses the SDK moderation helper for posts and comments. The type layer preserves legacy reasons. Muted-post messaging includes low-trust content. Post lists use shared author-mute checks. Tests cover updated moderation and downvote conditions.

Changes

Moderation reason alignment

Layer / File(s) Summary
SDK moderation parser and validation
src/providers/hive/hive.types.ts, src/utils/postParser.tsx, src/utils/postParser.test.ts, package.json
The parser delegates moderation classification to getContentModerationReason. LegacyMutedReason preserves cached legacy values. Tests update moderation, low-reputation, and downvote fixtures. The SDK version is updated.
Muted post messaging
src/components/postCard/children/postCardContent.tsx, src/config/locales/en-US.json
Muted posts now show separate low-trust and legacy low-reputation messages. Existing downvoted and fallback messages remain.
Mute filtering and eligibility
src/components/postsList/container/postsListContainer.tsx, src/components/postOptionsModal/container/postOptionsModal.tsx
Regular and promoted post lists use isAuthorMuted. The eligibility comment clarifies direct use of stats.gray for community mute status.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: 🟡 Moderate · up to 32e2e

The PR now relies on a moderation API that is not yet available in the published SDK, leaving the current dependency state unable to pass CI. It is not merge-ready until the SDK is published and the dependency and lockfile are updated.

Sequence Diagram(s)

sequenceDiagram
  participant PostParser
  participant ModerationSDK
  participant PostCard
  PostParser->>ModerationSDK: getContentModerationReason(post)
  ModerationSDK-->>PostParser: mutedReason
  PostParser->>PostCard: provide parsed post
  PostCard->>PostCard: select muted message
Loading

Possibly related issues

Possibly related PRs

Poem

A rabbit checks each muted state,
The SDK names it clean and straight.
Low-trust links now show their sign,
Legacy reasons still align.
Shared mute checks guide the way.

🚥 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 and concisely describes the main change: using content moderation rules from the SDK.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bugfix/shared-moderation-rules

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.

Comment thread src/providers/hive/hive.types.ts
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 9f856b9

@feruzm
feruzm merged commit c33b3ec into development Aug 15, 2026
12 of 13 checks passed
@feruzm
feruzm deleted the bugfix/shared-moderation-rules branch August 15, 2026 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consume the SDK's shared content moderation rules

1 participant