Skip to content

test: mutation-hardening — kill surviving mutants in pipeline/youtube/http/tenancy/crypto/cron - #89

Merged
Bonobo791 merged 8 commits into
mainfrom
test-mutation-hardening
Aug 5, 2026
Merged

test: mutation-hardening — kill surviving mutants in pipeline/youtube/http/tenancy/crypto/cron#89
Bonobo791 merged 8 commits into
mainfrom
test-mutation-hardening

Conversation

@Bonobo791

@Bonobo791 Bonobo791 commented Aug 5, 2026

Copy link
Copy Markdown
Owner

User description

What

Mental-mutation audit of the repo's catastrophic-failure surface (moderation decisions, irreversible YouTube writes, cross-tenant isolation, token crypto, cron selection) found the suite strong on its primary axes but with surviving mutants concentrated where the blast radius is largest. This PR adds 38 behavior tests that kill them — each verified both directions: green on unmutated code, red under the exact one-token mutation, green again after revert. Test-only; no production changes.

Kills (mutant → new test)

pipeline.test.ts (9 mutants, 9 tests)

  • Rule action map banreject / deleteban (pipeline.ts:81-82) → rule delete + rule ban end-to-end tests (staged row AND exact YouTube call). A creator's ban rule silently degrading to reject, or a delete rule banning authors, was green under mutation — catastrophic.
  • Delete-enforcement loop deleted (:432-438) → same delete-rule test.
  • Hold dispatch 'heldForReview''rejected' (:429) → hold-rule test pins the status string.
  • Inactive-channel guard deleted (:526) → inactive channel is never fetched/scored.
  • DRY_RUN validation deleted (:527-529) → DRY_RUN=ture throws loudly.
  • Per-comment failure throw deleted (:558-560) → run rejects after staging, cursor NOT advanced.
  • nextPageToken→null, ?? channel.cursor removed, \|\|&& in complete (:501,493,495) → three cursor-persistence tests.

youtube.test.ts / http.test.ts / rules.test.ts (12 mutants, 8 tests)

  • banAuthor param deleted (youtube.ts:292) → outgoing URL carries banAuthor=true. Under this mutant every ban silently degrades to a reject — the highest-severity finding.
  • setModerationStatus non-OK throw deleted / POST→GET (:296,299-302) → fails loudly with status; method pinned.
  • deleteComment: DELETE→POST, raw id vs encodeURIComponent, 404-throws, non-OK swallowed (:344-354) → one test pins method+encoding+404-tolerance, one pins the throw.
  • order:'time''relevance' (:239) → request params pinned (silent comment loss under relevance ordering).
  • AbortSignal.any → timeout only; aborted-signal rethrow deleted (http.ts:95,98) → caller abort honored, no retry (I5).
  • Retry-After seconds→ms (http.ts:67) → settles only after ~2s with fake timers.
  • >= 500> 500; network error retry (http.ts:81) → 500 retried; fetch rejection retried.
  • rule.pattern.toLowerCase()rule.pattern (rules.ts:195) → uppercase stored keyword matches lowercase text.

session.test.ts / org.test.ts / hooks.server.test.ts (7 mutants, 6 tests)

  • requireRole(..., 'admin') deleted in removeMember (org.ts:374) → member caller removing another member 403s (privilege escalation; every prior caller was admin+ or tripped an earlier guard).
  • WHERE dropped from renewal / org-repair UPDATEs (session.ts:124,128) → two-session bystander tests (cross-tenant session rewrite — catastrophic).
  • Renewal-cookie branch deleted; httpOnly flipped (hooks.server.ts:52-60) → exact cookie attributes pinned.
  • Number.isNaN guard dropped (session.ts:102) → corrupt-expiry session resolves null + row deleted (fail-closed).
  • ensurePersonalOrg existence check deleted (org.ts:104) → raced same-sub signup yields one org, one membership.

crypto.test.ts / oauthState.test.ts / cron.test.ts / deletion.test.ts (10 mutants, 9 tests)

  • Fixed IV (crypto.ts:40) → encrypt(x) !== encrypt(x) (AES-GCM nonce reuse — catastrophic).
  • Constant key source (crypto.ts:30) → decrypt under a rotated key throws.
  • cookieSecure() inverted (oauthState.ts:39) → new oauthState.test.ts pins secure: true under https APP_URL + loud 500 when unset.
  • Cron lease ltgt; active=1 filter dropped; ascdesc; lastRunAt dropped from finally-update; failure path 500→200 (+server.ts:78,82,83,110,102-105) → five channel-selection/lease/rotation/failure-reporting tests. Entire mechanism previously had zero assertions.
  • Consent sweep: isNotNull dropped; .limit dropped (deletion.ts:229-230) → already-erased rows not re-selected; batch bounded at 50 with remainder draining next invocation.

Also fixed

  • Pre-existing latent hazard in http.test.ts: the shared afterEach restored mocks after useRealTimers, so a setTimeout spy reinstalled the fake timer for the next test. Reordered with a comment.

Verification

  • Every mutant above applied by hand: exactly the intended new test(s) went red; revert → green.
  • npm run test — 486 passed (448 before + 38 new). npm run check — 0/0. npm run build — clean. codacy-analysis on all 11 changed files — 0 issues.

Deferred (documented in the audit, not tested)

  • TOCTOU guards (org.ts:267,409) — defense-in-depth, not killable single-threaded.
  • Low-severity survivors (truncation lengths, batch sizes, TTL boundaries, refreshAccessToken/revokeGoogleToken shapes) and verified-equivalent mutants (backreference guard redundant under recheck, .limit(1) with destructure, response === undefined in retryable unreachable past its guard).

CodeAnt-AI Description

Add coverage for moderation safety, session isolation, secure cookies, and scheduled processing

What Changed

  • Verifies that moderation rules delete, reject-and-ban, or hold comments as configured, and that failed YouTube actions are reported instead of treated as successful
  • Verifies inactive or leased channels are skipped, scans preserve their cursors, and scheduled runs process older channels without starving others
  • Verifies caller cancellations, retry delays, server failures, and network failures are handled correctly
  • Verifies session renewal and organization repairs affect only the current session, invalid session data expires safely, and personal organizations are not duplicated
  • Verifies OAuth cookies use HTTPS security settings, encryption uses fresh values and the configured key, and consent cleanup processes only eligible rows in bounded batches
  • Verifies keyword matching works regardless of stored pattern capitalization and organization member permissions remain enforced

Impact

✅ Fewer unintended moderation actions
✅ Safer cross-user session and organization updates
✅ More reliable scheduled channel processing

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

… hold status, inactive channel, DRY_RUN validation, decide-failure, cursor persistence)
…oping, renewal cookie, NaN expiry, personal-org idempotency
…failure-reporting, OAuth cookie Secure, consent sweep bounds
@cla-bot cla-bot Bot added the cla-signed label Aug 5, 2026
@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Incremental review completed 033d94a Aug 05, 2026 · 14:19 14:20
✅ Incremental review completed 18097f0 Aug 05, 2026 · 13:20 13:23
✅ Reviewed your PR ec31b94 Aug 05, 2026 · 13:00 13:03

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@netlify

netlify Bot commented Aug 5, 2026

Copy link
Copy Markdown

Deploy Preview for moderaty ready!

Name Link
🔨 Latest commit 8f2f7c4
🔍 Latest deploy log https://app.netlify.com/projects/moderaty/deploys/6a7348dd2c4d310008791b39
😎 Deploy Preview https://deploy-preview-89--moderaty.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 92
Accessibility: 97
Best Practices: 100
SEO: 100
PWA: -
View the detailed breakdown and full score reports
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

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

Next review available in: 20 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: fae05cce-c096-4576-aa55-f86f1ae66ba4

📥 Commits

Reviewing files that changed from the base of the PR and between 966ab2f and 8f2f7c4.

📒 Files selected for processing (11)
  • src/hooks.server.test.ts
  • src/lib/server/crypto.test.ts
  • src/lib/server/deletion.test.ts
  • src/lib/server/http.test.ts
  • src/lib/server/oauthState.test.ts
  • src/lib/server/org.test.ts
  • src/lib/server/pipeline.test.ts
  • src/lib/server/rules.test.ts
  • src/lib/server/session.test.ts
  • src/lib/server/youtube.test.ts
  • src/routes/api/cron/cron.test.ts

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.

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

🏁 CodeAnt Quality Gate Results

Commit: 8f2f7c49
Scan Time: 2026-08-05 14:32:00 UTC

✅ Overall Status: PASSED

Quality Gate Details

Quality Gate Status Details
Secrets ✅ PASSED 0 secrets found
Duplicate Code ✅ PASSED 0.0% duplicated
SAST ✅ PASSED No security issues
Bugs ✅ PASSED Rating S: No bugs
IAC ✅ PASSED No IAC issues

View Full Results

@codeant-ai codeant-ai Bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Aug 5, 2026
@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Sequence Diagram

This PR hardens the scheduled moderation path by selecting eligible channels safely, applying rule decisions, enforcing the corresponding YouTube action, and persisting progress only after successful processing.

sequenceDiagram
    participant Scheduler
    participant Database
    participant Pipeline
    participant YouTube

    Scheduler->>Database: Select and claim eligible channel
    Database-->>Scheduler: Least recently run active channel
    Scheduler->>Pipeline: Run channel
    Pipeline->>YouTube: Fetch new comments in time order
    YouTube-->>Pipeline: Return new comments
    Pipeline->>Pipeline: Apply moderation rules
    Pipeline->>YouTube: Enforce delete ban or hold
    Pipeline->>Database: Save actions and cursor
    Scheduler->>Database: Record run and clear lease
Loading

Generated by CodeAnt AI

@amazon-q-developer amazon-q-developer 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.

This PR adds 38 mutation-hardening tests targeting critical security and correctness paths. The test additions strengthen coverage in areas where mutants previously survived, particularly for:

  • Cross-tenant isolation (session renewal/org repair scoped to caller only)
  • Cryptographic nonce reuse prevention
  • YouTube API parameter preservation (banAuthor, order, method)
  • Cron channel selection and lease management
  • Personal org race condition handling

All tests pass and build succeeds. Test-only changes with no production code modifications. Ready to merge.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

@codacy-production

Copy link
Copy Markdown

Not up to standards ⛔

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🔴 Metrics 57 complexity · 16 duplication

Metric Results
Complexity 57 (≤ 100 complexity)
Duplication ⚠️ 16 (≤ 1 duplication)

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Test: mutation-hardening for pipeline enforcement, tenancy/session safety, crypto, and cron

🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Add targeted mutation-killing tests around moderation actions, YouTube writes, and HTTP
 retry/abort semantics.
• Harden cross-tenant/session isolation and cookie security behaviour with regression tests.
• Add cron channel-selection/lease tests and consent-retention sweep batching tests.
Diagram

graph TD
  T["Vitest tests"] --> P(["Pipeline moderation"]) --> Y(["YouTube client"]) --> H(["HTTP fetchWithRetry"])
  T --> C(["Cron /api/cron"])
  C --> D[("DB (Drizzle/SQLite)")]
  T --> A(["Hooks + Session cookies"])
  A --> D
  T --> K(["AES-GCM crypto"])

  subgraph Legend
    direction LR
    _t["Tests"] ~~~ _m(["Module"]) ~~~ _d[("Database")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Run mutation testing in CI (Stryker/Mutant + curated scope)
  • ➕ Continuously prevents regression of killed mutants
  • ➕ Automatically finds new surviving mutants as code evolves
  • ➖ Can be slow/expensive; may require heavy scoping and caching
  • ➖ Adds CI/tooling complexity and occasional flakiness triage
2. Add higher-level contract tests around outbound YouTube requests
  • ➕ Catches request-shape regressions with less coupling to internal pipeline structure
  • ➕ Can be reused across features that call YouTube
  • ➖ Still needs targeted unit tests for internal invariants (cursor persistence, tenant scoping)
  • ➖ May require more harnessing/mocking infrastructure

Recommendation: The PR’s approach—surgically adding behavioural tests for previously surviving mutants in the highest-risk paths—is the right immediate hardening step, especially since it is test-only and directly ties to audited mutations. Consider layering periodic/scoped mutation testing in CI later to keep coverage honest without over-expanding the test suite manually.

Files changed (11) +558 / -3

Tests (11) +558 / -3
hooks.server.test.tsAssert session renewal refreshes cookie expiry + security flags +23/-0

Assert session renewal refreshes cookie expiry + security flags

• Adds a regression test ensuring renewed sessions re-set the session cookie with updated expiry and expected attributes (path/httpOnly/sameSite/secure). Prevents silent logout/security-flag regressions when the renewal branch or attribute wiring is mutated.

src/hooks.server.test.ts

crypto.test.tsAdd non-deterministic encryption + key-derivation hardening tests +21/-0

Add non-deterministic encryption + key-derivation hardening tests

• Introduces tests that (1) the same plaintext encrypts to different payloads (fresh IV) and (2) decryption fails after ENCRYPTION_KEY rotation. These kill mutants that reuse a fixed IV or substitute a constant key source.

src/lib/server/crypto.test.ts

deletion.test.tsTest consent-email retention sweep filters + per-call batch bound +31/-0

Test consent-email retention sweep filters + per-call batch bound

• Adds tests ensuring nullExpiredConsentEmails skips already-erased rows and enforces CONSENT_SWEEP_BATCH limits across calls. Protects retention compliance and cron runtime budget constraints.

src/lib/server/deletion.test.ts

http.test.tsCover abort-signal composition, Retry-After seconds, and retryable failures +64/-1

Cover abort-signal composition, Retry-After seconds, and retryable failures

• Fixes teardown ordering around fake timers/spies, then adds tests for caller abort signal preservation (no retries), Retry-After parsing in seconds, and retrying both 5xx and network failures within a deadline.

src/lib/server/http.test.ts

oauthState.test.tsAdd tests for APP_URL-derived Secure cookie behaviour +61/-0

Add tests for APP_URL-derived Secure cookie behaviour

• Adds a new test file validating cookieSecure()/storePendingStates sets Secure when APP_URL is https, toggles for http, and fails loudly when APP_URL is missing. Prevents silent weakening of OAuth CSRF protection.

src/lib/server/oauthState.test.ts

org.test.tsAdd member privilege and personal-org idempotency regression tests +33/-0

Add member privilege and personal-org idempotency regression tests

• Adds tests that a plain member cannot remove another member (403) and that ensurePersonalOrg is idempotent under raced same-sub signup scenarios. Targets privilege-escalation and duplicate-personal-org failure modes.

src/lib/server/org.test.ts

pipeline.test.tsMutation-hardening tests for rule actions, skip/validation, failure semantics, and cursor persistence +125/-1

Mutation-hardening tests for rule actions, skip/validation, failure semantics, and cursor persistence

• Adds end-to-end tests pinning rule actions (delete/ban/hold) to the correct YouTube operations, skipping inactive channels, failing loudly on invalid DRY_RUN, rejecting after staging without advancing cursor on decision failure, and persisting/clearing page-token vs cursor correctly. Also braces a forEach callback to satisfy tooling/linting expectations.

src/lib/server/pipeline.test.ts

rules.test.tsAssert keyword rule matching lowercases stored pattern as well +7/-0

Assert keyword rule matching lowercases stored pattern as well

• Adds a regression test ensuring keyword patterns are matched case-insensitively on both text and stored rule.pattern, preventing silent rule disablement when pattern-side lowercasing is removed.

src/lib/server/rules.test.ts

session.test.tsAdd tests for NaN expiry fail-closed and scoped renewal/org-repair updates +64/-0

Add tests for NaN expiry fail-closed and scoped renewal/org-repair updates

• Adds tests that unreadable expiresAt values are treated as expired (row deleted), and that sliding-renewal and org-repair UPDATEs only affect the resolving session row (protecting cross-tenant isolation).

src/lib/server/session.test.ts

youtube.test.tsPin YouTube request shape: banAuthor, POST enforcement, DELETE deleteComment, ordering +59/-1

Pin YouTube request shape: banAuthor, POST enforcement, DELETE deleteComment, ordering

• Adds tests verifying banAuthor=true is sent for bans, moderation updates use POST and throw on non-OK, deleteComment uses DELETE with proper encoding and tolerates 404, and fetchNewComments requests order=time with correct channel scoping.

src/lib/server/youtube.test.ts

cron.test.tsAdd cron selection/lease/order/failure-reporting regression tests +70/-0

Add cron selection/lease/order/failure-reporting regression tests

• Adds tests ensuring leased channels and inactive channels are not selected, selection is least-recently-run first, runs clear lease and set lastRunAt, and failures return 500/ok:false while still recording the run. Guards against concurrency/starvation and misleading success responses.

src/routes/api/cron/cron.test.ts

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

PR Code Suggestions ✨

Previous suggestions up to commit ec31b94
CategorySuggestion                                                                                                                                    SeverityGenerated at (UTC)
Api mismatch
The renewal-cookie test cannot detect loss of the Secure attribute in production

The test mocks cookieSecure to always return false, so it cannot verify that renewed
session cookies use the production APP_URL-derived security setting. A regression
that stops calling cookieSecure or hard-codes secure: false would still pass.
Configure the mocked helper to return true, or mock the environment and assert the
real helper is used for HTTPS.

src/hooks.server.test.ts [93-99]

Why it matters? 🤔
  • ❌ HTTPS renewal cookies could lose the Secure attribute.
  • ⚠️ Renewal tests miss APP_URL-derived security regressions.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/hooks.server.test.ts
**Line:** 93:99
**Comment:**
	*Api Mismatch: The test mocks `cookieSecure` to always return `false`, so it cannot verify that renewed session cookies use the production APP_URL-derived security setting. A regression that stops calling `cookieSecure` or hard-codes `secure: false` would still pass. Configure the mocked helper to return `true`, or mock the environment and assert the real helper is used for HTTPS.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
Major2026-08-05 13:03
Race condition
Sequential calls do not verify safety against concurrent personal-organization creation

The two calls are sequential, so this only verifies ordinary idempotency and never
exercises the check-then-insert race described by the test. Concurrent signups can
still both observe no organization and cause a unique-constraint failure or
duplicate creation. Run genuinely overlapping calls or simulate the insert conflict
so the claimed raced-signup behavior is actually verified.

src/lib/server/org.test.ts [320-321]

Why it matters? 🤔
  • ⚠️ Signup race behavior remains unverified.
  • ❌ Concurrent personal-org creation may fail.
  • ⚠️ Mutation coverage does not include overlapping calls.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/lib/server/org.test.ts
**Line:** 320:321
**Comment:**
	*Race Condition: The two calls are sequential, so this only verifies ordinary idempotency and never exercises the check-then-insert race described by the test. Concurrent signups can still both observe no organization and cause a unique-constraint failure or duplicate creation. Run genuinely overlapping calls or simulate the insert conflict so the claimed raced-signup behavior is actually verified.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
Major2026-08-05 13:03

Latest suggestions up to commit 18097f0
CategorySuggestion                                                                                                                                    SeverityGenerated at (UTC)
Possible bug
The claim mock hardcodes the intended atomic behavior instead of verifying the pipeline's update predicate

The mock ignores the actual update predicate and unconditionally filters pending
rows, then mutates every filtered row to dispatched. Consequently, a production
mutation that removes or broadens the conditional pending-state predicate can still
pass these tests because the mock itself enforces the intended atomic claim
semantics. Model the requested comment IDs and update condition in the test double
so the pipeline's claim query is actually verified.

src/lib/server/pipeline.test.ts [82-86]

Why it matters? 🤔
  • ⚠️ Claim-predicate regressions can pass the pipeline suite.
  • ❌ Concurrent moderation actions may be dispatched twice.
  • ⚠️ Requested comment-ID filtering is not modeled by the mock.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/lib/server/pipeline.test.ts
**Line:** 82:86
**Comment:**
	*Possible Bug: The mock ignores the actual update predicate and unconditionally filters pending rows, then mutates every filtered row to `dispatched`. Consequently, a production mutation that removes or broadens the conditional pending-state predicate can still pass these tests because the mock itself enforces the intended atomic claim semantics. Model the requested comment IDs and update condition in the test double so the pipeline's claim query is actually verified.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
Major2026-08-05 13:22
Api mismatch
The renewal isolation test does not verify that updates are scoped to the individual session

The isolation fixture places the bystander session under a different user, so it
only detects an unscoped update that affects every user's sessions. It will pass if
the renewal update is incorrectly scoped by userId rather than the resolving session
token, even though that would renew all sessions belonging to the same user. Add a
second aging or non-aging session for userId and assert that its expiry remains
unchanged.

src/lib/server/session.test.ts [84-90]

Why it matters? 🤔
  • ⚠️ Same-user session renewal isolation remains untested.
  • ⚠️ A bad scope could extend stale sessions unexpectedly.
  • ⚠️ Multiple login paths can create sessions per user.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/lib/server/session.test.ts
**Line:** 84:90
**Comment:**
	*Api Mismatch: The isolation fixture places the bystander session under a different user, so it only detects an unscoped update that affects every user's sessions. It will pass if the renewal update is incorrectly scoped by `userId` rather than the resolving session token, even though that would renew all sessions belonging to the same user. Add a second aging or non-aging session for `userId` and assert that its expiry remains unchanged.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
Major2026-08-05 13:22
Incomplete implementation
Single-invocation coverage does not verify that concurrent cron requests cannot claim the same channel

The test invokes only one handler, so it verifies filtering but not the atomic claim
under contention. A regression that removes or weakens claimable from the UPDATE
could still pass because the single invocation selects and processes the channel
normally. Run two cron calls concurrently while controlling runChannel, then assert
that only one invocation runs and the other returns claimed: false.

src/routes/api/cron/cron.test.ts [128-131]

Why it matters? 🤔
  • ❌ Concurrent cron requests could process one channel twice.
  • ⚠️ Duplicate moderation runs could duplicate YouTube operations.
  • ⚠️ Current tests do not protect the atomic claim invariant.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/routes/api/cron/cron.test.ts
**Line:** 128:131
**Comment:**
	*Incomplete Implementation: The test invokes only one handler, so it verifies filtering but not the atomic claim under contention. A regression that removes or weakens `claimable` from the `UPDATE` could still pass because the single invocation selects and processes the channel normally. Run two cron calls concurrently while controlling `runChannel`, then assert that only one invocation runs and the other returns `claimed: false`.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
Major2026-08-05 13:22

@qodo-code-review

qodo-code-review Bot commented Aug 5, 2026

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Remediation recommended

1. console.error spy not restored ✓ Resolved 🐞 Bug ☼ Reliability
Description
In cron.test.ts the new “failing channel run” test spies on console.error and never restores it, so
later tests in the same file will run with console.error still mocked. This can hide real errors and
create brittle interactions if later tests depend on real console.error or install their own spies.
Code

src/routes/api/cron/cron.test.ts[178]

+	vi.spyOn(console, 'error').mockImplementation(() => {});
Relevance

●●● Strong

Team has accepted restoring console spies in tests to avoid cross-test leakage.

PR-#53

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test adds a console.error spy but the file only has a beforeEach with vi.clearAllMocks() and no
afterEach/restore, so the spy’s mocked implementation can persist into following tests in the same
file.

src/routes/api/cron/cron.test.ts[172-188]
src/routes/api/cron/cron.test.ts[45-49]
src/routes/api/cron/cron.test.ts[233-241]

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

### Issue description
`src/routes/api/cron/cron.test.ts` installs a `vi.spyOn(console, 'error')` mock implementation in one test and never restores it. `vi.clearAllMocks()` in `beforeEach` only clears call history; it does not restore the original `console.error` implementation.

### Issue Context
This leak affects subsequent tests in the *same file* (several tests follow) by suppressing error output and potentially interfering with other spies.

### Fix Focus Areas
- src/routes/api/cron/cron.test.ts[45-49]
- src/routes/api/cron/cron.test.ts[172-188]

### Suggested fix
Pick one:
1) Add `afterEach(() => { vi.restoreAllMocks(); })` (or at least restore `console.error`) for the file.
2) In the specific test, capture the spy and restore in a `finally` block:
```ts
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
try {
 // test
} finally {
 errorSpy.mockRestore();
}
```

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



Informational

2. Relative import ./oauthState 📘 Rule violation ⚙ Maintainability
Description
src/lib/server/oauthState.test.ts and src/lib/server/youtube.test.ts import src/lib modules
via relative paths instead of the required $lib alias. This violates the project’s src/lib
import convention, which can reduce reliability of refactors and tooling.
Code

src/lib/server/oauthState.test.ts[27]

+import { cookieSecure, OAUTH_STATE_COOKIE, storePendingStates } from './oauthState';
Relevance

● Weak

Multiple PRs rejected switching test-file relative imports to $lib alias; convention not enforced in
tests.

PR-#50
PR-#78
PR-#35

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2401155 mandates that any import resolving into src/lib/** must use the $lib
alias rather than a relative path. In src/lib/server/oauthState.test.ts, the import ./oauthState
resolves to src/lib/server/oauthState.ts, and in src/lib/server/youtube.test.ts, the import
./youtube resolves to src/lib/server/youtube.ts, showing both files are not adhering to the
required alias convention.

Rule 2401155: Use $lib alias instead of relative paths for src/lib imports
src/lib/server/oauthState.test.ts[27-27]
src/lib/server/youtube.test.ts[19-20]

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

## Issue description
Tests under `src/lib/server` are importing modules that live in `src/lib/**` using relative paths (e.g., `./oauthState`, `./youtube`) instead of the required `$lib` alias, violating the repository import convention.

## Issue Context
PR Compliance ID 2401155 enforces that imports whose targets resolve into `src/lib/**` must use `$lib/...` rather than relative paths, to keep imports consistent and refactor/tooling-friendly.

## Fix Focus Areas
- src/lib/server/oauthState.test.ts[27-27]
- src/lib/server/youtube.test.ts[20-20]

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


Grey Divider

Context used
✅ Compliance rules (platform): 78 rules

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread src/routes/api/cron/cron.test.ts Outdated
@codeant-ai codeant-ai Bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:XL This PR changes 500-999 lines, ignoring generated files labels Aug 5, 2026
Repository owner deleted a comment from codeant-ai Bot Aug 5, 2026
@Bonobo791

Copy link
Copy Markdown
Owner Author

Review triage — all bot comments addressed

@qodo-code-review

  • Console.error spy not restored (bug, cron.test.ts) — valid, fixed in 18097f0. The spy is now restored via try/finally + errorSpy.mockRestore(), so a failing assertion can no longer leak the muted console into later tests.
  • Relative ./oauthState import violates the $lib convention (rule violation) — declined. Every colocated server test in the repo imports its subject via ./ (session, org, rules, youtube, crypto, deletion test files all do this); these tests live next to the route modules they exercise, and qodo's own relevance rating on this finding was "Weak".

@CodeAnt-AI

  • Major: renewal-cookie test cannot catch a hardcoded secure flagvalid, fixed in 18097f0. cookieSecure is now a hoisted vi.fn in the mocks object; the test sets mockReturnValue(true) and asserts both expect(mocks.cookieSecure).toHaveBeenCalled() and secure: true. Verified both directions: hardcoding secure: false or secure: true in hooks.server.ts turns exactly that test red; revert → green.
  • Sequential ensurePersonalOrg calls do not test a real racedeclined. The test's job is killing the deleted-existence-check mutant (verified red under that mutation). Production race safety comes from the user-insert unique constraint upstream, per ensurePersonalOrg's own docstring; the TOCTOU follow-up was deliberately flagged in the PR body rather than silently dropped.

@codacy-production — "Not up to standards ⛔" is the duplication gate (16 clones > threshold, 0 issues). Declined: the repetition is test fixtures, matching the repo's established test style; PR #59 had the identical gate result and was merged.

@coderabbitai — rate-limited this run, no actionable comments left to triage. Noted.

@netlify — deploy preview ready; informational. @sonarqubecloud — quality gate passed.

Gates on 18097f0: 486 tests green, svelte-check 0/0, codacy-analysis 0 issues on the changed files. Holding here for human review.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@Bonobo791 Acknowledged.

The valid test-isolation and renewal-cookie findings are fixed in 18097f0. The declined findings have documented scope and repository-style rationale. The reported verification results are consistent with a test-only hardening PR.

No further CodeRabbit action is requested.

You are interacting with an AI system.

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Question: renewal-cookie test cannot catch a hardcoded secure flag* — valid, fixed in 18097f0. cookiesecure is now a hoisted vi.fn in the mocks object; the test sets mockreturnvalue(true) and asserts both expect(mocks.cookiesecure).tohavebeencalled() and secure: true. verified both directions: hardcoding secure: false or secure: true in hooks.server.ts turns exactly that test red; revert → green.

  • sequential ensurepersonalorg calls do not test a real racedeclined. the test's job is killing the deleted-existence-check mutant (verified red under that mutation). production race safety comes from the user-insert unique constraint upstream, per ensurepersonalorg's own docstring; the toctou follow-up was deliberately flagged in the pr body rather than silently dropped.

@codacy-production — "not up to standards ⛔" is the duplication gate (16 clones > threshold, 0 issues). declined: the repetition is test fixtures, matching the repo's established test style; pr #59 had the identical gate result and was merged.

@coderabbitai — rate-limited this run, no actionable comments left to triage. noted.

@netlify — deploy preview ready; informational. @sonarqubecloud — quality gate passed.

gates on 18097f0: 486 tests green, svelte-check 0/0, codacy-analysis 0 issues on the changed files. holding here for human review.

Answer:

Review

No blocking issues found in the added tests.

  • The renewal-cookie test now correctly distinguishes cookieSecure() from a hardcoded value by mocking the helper, asserting it was called, and checking secure: true. It should fail for both secure: false and a hardcoded secure: true.
  • The sequential ensurePersonalOrg calls are sufficient for the stated purpose of killing the deleted-existence-check mutant. They do not prove concurrent race safety, but that is a separate concern and is appropriately covered by the upstream uniqueness constraint/documentation.
  • The Codacy duplication result appears to be fixture duplication in tests rather than a correctness issue, and the zero-analysis-issues result supports declining it.

One minor wording issue: ensurePersonalOrg is idempotent for a raced same-sub signup implies the test exercises concurrency, but the calls are sequential. Consider renaming it to something like:

ensurePersonalOrg is idempotent when called repeatedly for the same signup

If race behavior is eventually tested, that should be a separate concurrent test using Promise.all. Otherwise, the test’s implementation and mutant-killing purpose are sound.

@qodo-code-review

Copy link
Copy Markdown

Review triage — all bot comments addressed

@qodo-code-review

  • Console.error spy not restored (bug, cron.test.ts) — valid, fixed in 18097f0. The spy is now restored via try/finally + errorSpy.mockRestore(), so a failing assertion can no longer leak the muted console into later tests.
  • Relative ./oauthState import violates the $lib convention (rule violation) — declined. Every colocated server test in the repo imports its subject via ./ (session, org, rules, youtube, crypto, deletion test files all do this); these tests live next to the route modules they exercise, and qodo's own relevance rating on this finding was "Weak".

@CodeAnt-AI

  • Major: renewal-cookie test cannot catch a hardcoded secure flagvalid, fixed in 18097f0. cookieSecure is now a hoisted vi.fn in the mocks object; the test sets mockReturnValue(true) and asserts both expect(mocks.cookieSecure).toHaveBeenCalled() and secure: true. Verified both directions: hardcoding secure: false or secure: true in hooks.server.ts turns exactly that test red; revert → green.
  • Sequential ensurePersonalOrg calls do not test a real racedeclined. The test's job is killing the deleted-existence-check mutant (verified red under that mutation). Production race safety comes from the user-insert unique constraint upstream, per ensurePersonalOrg's own docstring; the TOCTOU follow-up was deliberately flagged in the PR body rather than silently dropped.

@codacy-production — "Not up to standards ⛔" is the duplication gate (16 clones > threshold, 0 issues). Declined: the repetition is test fixtures, matching the repo's established test style; PR #59 had the identical gate result and was merged.

@coderabbitai — rate-limited this run, no actionable comments left to triage. Noted.

@netlify — deploy preview ready; informational. @sonarqubecloud — quality gate passed.

Gates on 18097f0: 486 tests green, svelte-check 0/0, codacy-analysis 0 issues on the changed files. Holding here for human review.

Thanks for the triage update. Based on the diff, the two Qodo findings are addressed as follows:

  • finding 1 (console.error spy): the try/finally block now calls errorSpy.mockRestore(), including when assertions fail. This fix is correct.
  • finding 2 (relative ./oauthState import): your rationale for declining it is reasonable; the import matches the surrounding colocated test convention and is only an informational style concern.

The additional test-hardening changes and reported green gates provide good coverage for the revised behavior. No further Qodo action is needed from this review.

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:XL This PR changes 500-999 lines, ignoring generated files labels Aug 5, 2026
@Bonobo791

Copy link
Copy Markdown
Owner Author

Review triage follow-up

@CodeAnt-AI — thanks for the confirmatory review. Your one nit was right: the test name ensurePersonalOrg is idempotent for a raced same-sub signup implied concurrency the body never exercises. Fixed in 033d94a — renamed to ensurePersonalOrg is idempotent when called repeatedly for the same signup; the comment keeps the race rationale (the unique-constraint loser must find the winner's org). If a true concurrent test is ever added, it will be a separate Promise.all case per your suggestion. Verified: 22/22 in org.test.ts, codacy-analysis 0 issues on the file.

@qodo-code-review — thanks for confirming both verdicts (spy restore correct; ./ import decline reasonable). No further action on my side either.

@coderabbitai — acknowledged; still rate-limited, nothing new to triage.

@codacy-production, @netlify, @sonarqubecloud — no new findings since the last triage; prior verdicts stand (duplication-only gate declined; preview and SonarQube gate informational/pass).

Holding for human review.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@Bonobo791 Acknowledged.

The renamed test title now matches the test behavior. The separate Promise.all case remains appropriate if the project adds a true concurrency test later.

No further CodeRabbit action is requested.

You are interacting with an AI system.

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Question: the test name ensurepersonalorg is idempotent for a raced same-sub signup implied concurrency the body never exercises. fixed in 033d94a — renamed to ensurepersonalorg is idempotent when called repeatedly for the same signup; the comment keeps the race rationale (the unique-constraint loser must find the winner's org). if a true concurrent test is ever added, it will be a separate promise.all case per your suggestion. verified: 22/22 in org.test.ts, codacy-analysis 0 issues on the file.

@qodo-code-review — thanks for confirming both verdicts (spy restore correct; ./ import decline reasonable). no further action on my side either.

@coderabbitai — acknowledged; still rate-limited, nothing new to triage.

@codacy-production, @netlify, @sonarqubecloud — no new findings since the last triage; prior verdicts stand (duplication-only gate declined; preview and sonarqube gate informational/pass).

holding for human review.

Answer:
I don’t see a blocking issue in the revised test name or the other changes shown.

The rename correctly avoids claiming that the test exercises concurrency: it verifies sequential idempotence by calling ensurePersonalOrg twice and checking that the same organization and membership are retained. The note about the race rationale is useful context, provided it is understood as motivation rather than coverage.

One remaining coverage limitation is that the test does not validate the stated race behavior. Two concurrent calls can both pass the existence check before either inserts; unless ensurePersonalOrg handles the unique-constraint loser and then re-reads the existing organization, the second call could still reject. A future Promise.all([...]) test would be needed to prove that guarantee, as acknowledged in the thread. This is a test-coverage gap rather than a regression introduced by this PR.

@qodo-code-review

Copy link
Copy Markdown

Review triage follow-up

@CodeAnt-AI — thanks for the confirmatory review. Your one nit was right: the test name ensurePersonalOrg is idempotent for a raced same-sub signup implied concurrency the body never exercises. Fixed in 033d94a — renamed to ensurePersonalOrg is idempotent when called repeatedly for the same signup; the comment keeps the race rationale (the unique-constraint loser must find the winner's org). If a true concurrent test is ever added, it will be a separate Promise.all case per your suggestion. Verified: 22/22 in org.test.ts, codacy-analysis 0 issues on the file.

@qodo-code-review — thanks for confirming both verdicts (spy restore correct; ./ import decline reasonable). No further action on my side either.

@coderabbitai — acknowledged; still rate-limited, nothing new to triage.

@codacy-production, @netlify, @sonarqubecloud — no new findings since the last triage; prior verdicts stand (duplication-only gate declined; preview and SonarQube gate informational/pass).

Holding for human review.

Acknowledged. The rename addresses the concurrent-test naming concern, and the spy restoration in finding 1 is implemented. I’m also leaving the relative-import recommendation in finding 2 unchanged, consistent with your decision to decline it; no further Qodo action is needed.

@Bonobo791

Copy link
Copy Markdown
Owner Author

Triage closed

@CodeAnt-AI — agreed: the missing true-concurrency (Promise.all) coverage for the ensurePersonalOrg race is a pre-existing coverage gap, not a regression from this PR; it stays on the record as future work, and production race safety currently rests on the upstream unique constraint. Nothing further to change here.

@coderabbitai — thanks for confirming the rename. @qodo-code-review — verdicts confirmed in the previous round. All findings on this PR are now either fixed (18097f0, 033d94a) or declined with reasons. Holding for human review.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@Bonobo791 Acknowledged.

The ensurePersonalOrg concurrency coverage remains future work. The current PR does not regress that coverage gap. The fixed and declined findings have documented outcomes.

🐇

You are interacting with an AI system.

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Question: the missing true-concurrency (promise.all) coverage for the ensurepersonalorg race is a pre-existing coverage gap, not a regression from this pr; it stays on the record as future work, and production race safety currently rests on the upstream unique constraint. nothing further to change here.

@coderabbitai — thanks for confirming the rename. @qodo-code-review — verdicts confirmed in the previous round. all findings on this pr are now either fixed (18097f0, 033d94a) or declined with reasons. holding for human review.

Answer:
No further changes are needed for this point. The ensurePersonalOrg test verifies sequential idempotency, while true concurrent Promise.all coverage remains a pre-existing gap rather than a regression introduced by this PR. Production protection currently depends on the upstream unique constraint, so this is reasonable future work and can remain documented separately.

The rename and prior review findings are otherwise confirmed as addressed or intentionally declined.

@qodo-code-review

Copy link
Copy Markdown

Triage closed

@CodeAnt-AI — agreed: the missing true-concurrency (Promise.all) coverage for the ensurePersonalOrg race is a pre-existing coverage gap, not a regression from this PR; it stays on the record as future work, and production race safety currently rests on the upstream unique constraint. Nothing further to change here.

@coderabbitai — thanks for confirming the rename. @qodo-code-review — verdicts confirmed in the previous round. All findings on this PR are now either fixed (18097f0, 033d94a) or declined with reasons. Holding for human review.

Acknowledged. One discrepancy remains in the current Qodo index: finding 2 (the relative $lib import convention in src/lib/server/oauthState.test.ts) is still marked active/pending, while finding 1 is implemented. No further action has been taken here; human review can proceed, but finding 2 should be explicitly declined or fixed if the triage is intended to be complete.

# Conflicts:
#	src/lib/server/pipeline.test.ts
@sonarqubecloud

sonarqubecloud Bot commented Aug 5, 2026

Copy link
Copy Markdown

@codacy-production

Copy link
Copy Markdown

Not up to standards ⛔

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🔴 Metrics 57 complexity · 16 duplication

Metric Results
Complexity 57 (≤ 100 complexity)
Duplication ⚠️ 16 (≤ 1 duplication)

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

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

Labels

cla-signed size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant