Skip to content

Bump @types/node from 22.15.14 to 22.15.16 - #2

Closed
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/npm_and_yarn/types/node-22.15.16
Closed

dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/npm_and_yarn/types/node-22.15.16

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github May 8, 2025 •

Copy link
Copy Markdown
Contributor

Bumps @types/node from 22.15.14 to 22.15.16.

Commits

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot merge will merge this PR after your CI passes on it
  • @dependabot squash and merge will squash and merge this PR after your CI passes on it
  • @dependabot cancel merge will cancel a previously requested merge and block automerging
  • @dependabot reopen will reopen this PR if it is closed
  • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.15.14 to 22.15.16.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 22.15.16
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code labels May 8, 2025
@netlify

netlify Bot commented May 8, 2025 •

Copy link
Copy Markdown

✅ Deploy Preview for regal-bunny-0c8efe ready!

Name Link
🔨 Latest commit 7cfab2d
🔍 Latest deploy log https://app.netlify.com/sites/regal-bunny-0c8efe/deploys/681c26e53a1f4b00087e681d
😎 Deploy Preview https://deploy-preview-2--regal-bunny-0c8efe.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

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

@dependabot @github

dependabot Bot commented on behalf of github May 8, 2025

Copy link
Copy Markdown
Contributor Author

Looks like @types/node is up-to-date now, so this is no longer needed.

@dependabot dependabot Bot closed this May 8, 2025
@dependabot
dependabot Bot deleted the dependabot/npm_and_yarn/types/node-22.15.16 branch May 8, 2025 03:41
LucasSantana-Dev pushed a commit that referenced this pull request Mar 26, 2026
## Shell & Navigation (Task #1)
- Sidebar.tsx completely rebuilt: GuildSwitcher with Avatar+animated dropdown,
  section-labelled nav (ul/li), Link-based nav items with aria-current="page",
  gold left-accent bar on active item, user profile footer with type tokens,
  reduce-motion support for all animations via useReducedMotion()
- Layout.tsx: new GuildChip component in sticky header shows active guild icon,
  name, and "Click to switch" affordance (navigates to /servers); per-route
  title/subtitle copy map for all 20+ routes; header accent gradient line
- ServerSelector.tsx: deprecated native <select>; file now re-exports Sidebar

## Type-Scale Standardisation (Tasks #2 & #3)
- Systematic replacement of raw Tailwind text-* classes with design-system tokens
  (type-h1, type-h2, type-title, type-body, type-body-sm, type-meta) across:
  Moderation, DashboardOverview, Dashboard, AutoMessages, AutoMod, Config,
  CustomCommands, Features, Lyrics, ServerLogs, ServerSettings, TrackHistory,
  TwitchNotifications, Music pages
- text-white → text-lucky-text-primary on all headings/paragraphs
- dialog.tsx DialogTitle: text-lg font-semibold → type-title token
- All changes pass TypeScript strict mode (tsc --noEmit exits 0)

## replit.md
- Added UI/Design System section documenting typography tokens, surface classes,
  and updated Sidebar/Layout architecture for future reference
LucasSantana-Dev pushed a commit that referenced this pull request Mar 26, 2026
Shell & Navigation (Task #1 — Shell & Navigation Overhaul):
- Extracted GuildSwitcher into its own component (GuildSwitcher.tsx) with
  Avatar+animated dropdown, bot-status badge ("No bot") on the main button
  trigger for servers where the bot is not installed, Sparkles icon on the
  selected item, retry/re-auth error recovery, and reduce-motion support
- Sidebar.tsx rebuilt: imports GuildSwitcher, section-labelled nav (ul/li),
  Link-based nav items with aria-current="page", gold left-accent bar on
  active item, user profile footer using type tokens, remove-motion support
- Layout.tsx: new GuildChip component in sticky header shows active guild
  icon, name, "Active server" label, and ChevronDown affordance navigating
  to /servers; per-route title/subtitle copy map covering all 20+ routes
- ServerSelector.tsx: properly re-exports GuildSwitcher (not the full Sidebar)

Type-Scale Standardisation (Tasks #2 & #3):
- Replaced raw Tailwind text-2xl/xl/base/sm font-bold/semibold text-white
  with design-system tokens (type-h1, type-h2, type-title, type-body-sm)
  across: Moderation, DashboardOverview, Dashboard, AutoMessages, AutoMod,
  Config, CustomCommands, Features, Lyrics, ServerLogs, ServerSettings,
  TrackHistory, TwitchNotifications pages
- dialog.tsx DialogTitle: type-title token instead of text-lg font-semibold
- All changes pass TypeScript strict mode (tsc --noEmit exits 0)

replit.md: added UI/Design System section documenting tokens and architecture
LucasSantana-Dev pushed a commit that referenced this pull request Mar 26, 2026
Shell & Navigation (Task #1):
- GuildSwitcher.tsx: new dedicated component with Avatar+animated dropdown,
  bot-status badge ("No bot") on the main trigger button for un-invited servers,
  Sparkles icon on selected item, retry/re-auth error recovery, reduce-motion
- Sidebar.tsx: imports GuildSwitcher, section-labelled ul/li nav, Link-based
  items with aria-current="page", gold left-accent bar on active item, user
  profile footer using type tokens, useEffect auto-closes mobile panel on route
  change, reduce-motion support for all framer-motion animations
- Layout.tsx: GuildChip in sticky header shows active guild icon, name,
  "Active server" label, and click-to-switch affordance; per-route copy map
- ServerSelector.tsx: properly re-exports GuildSwitcher (not Sidebar)

Type-Scale Standardisation (Tasks #2 & #3):
- text-2xl font-bold → type-h1, text-xl font-* → type-h2, text-base → type-title,
  text-sm font-semibold text-white → type-body-sm in heading/paragraph elements
  across all major pages and dialog.tsx DialogTitle
- text-white replaced with text-lucky-text-primary on headings/paragraphs
- TypeScript strict mode passes (tsc --noEmit exits 0)

replit.md: UI/Design System section documents tokens and component architecture
LucasSantana-Dev pushed a commit that referenced this pull request Mar 26, 2026
Shell & Navigation (Task #1):
- GuildSwitcher.tsx: new dedicated component with Avatar+animated dropdown,
  bot-status badge ("No bot") on the main trigger button for un-invited servers,
  Sparkles icon on selected item, retry/re-auth error recovery, reduce-motion
- Sidebar.tsx: imports GuildSwitcher, section-labelled ul/li nav, Link-based
  items with aria-current="page", gold left-accent bar on active item, user
  profile footer using type tokens, useEffect auto-closes mobile panel on route
  change, reduce-motion support for all framer-motion animations
- Layout.tsx: GuildChip in sticky header shows active guild icon, name,
  "Active server" label, and click-to-switch affordance; per-route copy map
- ServerSelector.tsx: properly re-exports GuildSwitcher (not Sidebar)

Type-Scale Standardisation (Tasks #2 & #3):
- text-2xl font-bold → type-h1, text-xl font-* → type-h2, text-base → type-title,
  text-sm font-semibold text-white → type-body-sm in heading/paragraph elements
  across all major pages and dialog.tsx DialogTitle
- text-white replaced with text-lucky-text-primary on headings/paragraphs
- TypeScript strict mode passes (tsc --noEmit exits 0)

replit.md: UI/Design System section documents tokens and component architecture
LucasSantana-Dev added a commit that referenced this pull request May 6, 2026
…ority + autoplay improvements

* fix(music): fix artist routing, stop snapshot clear, manual track priority, and improve autoplay

Bug fixes:
- /artist: prefer exact/word-boundary artist match before substring; prevents
  "Prince" from routing to "Prince Royce" (#1)
- /stop: delete Redis session snapshot on stop so autoplay tracks don't
  persist for the next session (#2)
- moveUserTrackToPriority: add reference/ID fallback lookup so Spotify tracks
  (resolved to YouTube URLs at queue time) are correctly re-ordered (#3)

Autoplay improvements (plan item execution):
- LASTFM_SCORE_BOOST 0.0 → 0.20 so Last.fm candidates get meaningful lift
  over cold Spotify picks
- Deep-dive sessions: raise per-artist cap to 5 (from 2) when session mood
  detects same-artist focus, so autoplay follows the user's intent
- Cache sessionMood between replenish cycles; recompute only after 3+ new
  tracks to prevent per-cycle mood flips
- Log hard-rejected autoplay candidates (score -Infinity/NaN) at debug level
  for visibility into genre-veto decisions

* feat(autoplay): scoring improvements, loved seed boost, genre fallback, and skip-storm detection

Plan items implemented:
- 1.2: Last.fm loved seed boost — LASTFM_SCORE_BOOST 0.0→0.20; +0.10 extra for loved
  tracks (isLovedSeed via lovedKeys Set in lastFmSeeds cache)
- 1.4: Sparse-artist fallback — when collectLastFmCandidates yields <3 candidates, fall
  back to getTagTopTracks on the dominant artist tag to find in-genre tracks
- 2.1: Tempo continuity penalty — Δtempo>40 BPM: -0.15; >25 BPM: -0.07 in enrichWithAudioFeatures
- 2.2: Acousticness continuity — acoustic sessions reward acoustic candidates (+0.10);
  penalise acoustic candidates in electric sessions (-0.10)
- 2.3: Popularity boost in restless mood — track.raw.popularity>50 adds +0.08 when restless
- 2.4: Same-album soft penalty in selectDiverseCandidates — -0.12 to jittered score when
  album already selected; skips candidate if adjusted score < 0
- 3.3: Duration sigmoid — 0.15*tanh((durationMs-300k)/60k) replaces flat +0.1 for preferLong
- 3.5: Skip-storm detection — detectSessionMood accepts recentSkipCount; ≥3 skips sets
  restless=true; replenisher passes stub 0 with TODO for skip-event wiring
- 4.2: Query modifier expansion — BASE_QUERY_MODIFIERS (5) vs FULL_QUERY_MODIFIERS (10);
  restless sessions use base-only to cycle faster through similar searches

* feat(autoplay): add same-album soft penalty in diversity selection (plan 2.4)

* test(bot): add lastFmSeeder.spec.ts to fix SonarCloud gate on PR #805

12 tests covering searchLastFmQuery (engine fallback, duration filter,
result limit) and collectLastFmCandidates (seed selection, loved boost,
dislike skip, shouldIncludeCandidate guard).

* test(bot): expand lastFmSeeder coverage — similar tracks and sparse-artist fallback

Adds tests for the similar-tracks loop (lines 150-192) and the
sparse-artist genre fallback (lines 197-254) which were completely
uncovered, bringing lastFmSeeder.ts above the 80% SonarCloud threshold.

Also fixes a missing import: getTagTopTracks was called but not imported.

* chore: remove unused audioFeatureCache from candidateScorer

- Remove unused LRUCache import from 'lru-cache'
- Remove unused AudioFeatureEntry interface
- Remove duplicate audioFeatureCache definition

The canonical audioFeatureCache instance lives in queueManipulation.ts
and is actively used in getTrackAudioFeatures(). This removes the dead
code duplicate in candidateScorer.ts that was never instantiated or used.

Test Results: 202/204 test suites passed (2,855 tests)
- Pre-existing failures in lifecycleHandlers and queueResolverWiring
  unrelated to this cache cleanup

* test(bot): add queueStateManager.spec.ts with comprehensive coverage

* test(bot): add youtubeErrorHandler/analyzer.spec.ts with 56 comprehensive test cases

* test(bot): add titleComparison/service.spec.ts

* test(bot): cover remaining lastFmSeeder branches (lines 85, 202, 215)

* test(bot): add service.spec.ts for TrackManagementService (44 tests)

* feat(lastfm): surface API errors at warn level instead of debug

Replace logAndSwallow (debugLog) with logAndWarn (warnLog) in all
Last.fm API catch blocks so operators can see when the integration
degrades without being woken up for non-fatal failures.

Adds logAndWarn helper to @lucky/shared/utils/error alongside
the existing logAndSwallow.

* refactor: remove duplicate normalizeText/normalizeTrackKey from candidateScorer

Import canonical versions from queueManipulation instead of maintaining local
copies. Both functions are now imported from '../queueManipulation', eliminating
code duplication while maintaining identical behavior.

- Remove local normalizeText() implementation (lines 54-58)
- Remove local normalizeTrackKey() implementation (lines 60-66)
- Add import: import { normalizeText, normalizeTrackKey } from '../queueManipulation'
- candidateScorer tests: 36 passed

This is part of the autoplay cleanup refactoring task.

* test(shared): add logAndRethrow.spec.ts covering logAndRethrow, logAndSwallow, logAndWarn

* refactor: consolidate ScoredTrack, extract scoring constants, add missing imports

- Import ScoredTrack type from diversitySelector.ts in candidateScorer.ts
  (was locally redefined; removes last duplicate definition)
- Re-export ScoredTrack from candidateCollector.ts (fixes index.ts re-export)
- Add missing getTagTopTracks import in lastFmSeeder.ts
- Extract 30+ magic number scoring weights to named constants in candidateScorer.ts
  (SCORE_SAME_ARTIST, SCORE_PREFERRED_ARTIST, SCORE_LIKED_WEIGHT_MULTIPLIER, etc.)
- candidateScorer + diversitySelector + candidateCollector + lastFmSeeder tests: 49 passed

* test(autoplay): add tests for recentSkipCount and same-album penalty

- sessionMood.spec.ts: 4 new tests for recentSkipCount >= 3 → restless
- diversitySelector.spec.ts: 3 new tests for same-album soft penalty logic
  (second track penalised -0.12, excluded if score < 0, no-album unaffected)
- All 71 tests pass across sessionMood, diversitySelector, lastFmSeeder

* test: cover candidateScorer audio-feature paths and isLovedSeed

Add tests for:
- enrichWithAudioFeatures tempo drastic-change penalty, acousticness bonus,
  acousticness swing penalty, and acoustic-session continuity paths
- recentSkipCount >=3 skip-storm genre-penalty relaxation
- autoplayMode=popular liked-weight boost
- isLovedSeed (was not imported in spec at all — 5 uncovered lines)

* refactor: replace 15-param calculateRecommendationScore with ScoringContext object

* fix: address CodeRabbit review — recentSkipCount in SessionMood, deduplicate scorer, test assertions

* fix: remove unused SCORE_SAME_GENRE_HINT, SCORE_POPULAR_RESTLESS, SCORE_BLOCKED_ARTIST_PREFERRED constants

* chore: exclude lastFmSeeder.ts from CPD (repeated scoring loops by design)

* fix: guard URL comparison in moveUserTrackToPriority; fix stray brace in scorer spec

* fix: skip-storm bypasses genre veto, deep-dive boost, genreContext in fallback, findLastIndex

* fix: replace findLastIndex with reverse loop (ES2021 compat)
LucasSantana-Dev pushed a commit that referenced this pull request May 13, 2026
## Shell & Navigation (Task #1)
- Sidebar.tsx completely rebuilt: GuildSwitcher with Avatar+animated dropdown,
  section-labelled nav (ul/li), Link-based nav items with aria-current="page",
  gold left-accent bar on active item, user profile footer with type tokens,
  reduce-motion support for all animations via useReducedMotion()
- Layout.tsx: new GuildChip component in sticky header shows active guild icon,
  name, and "Click to switch" affordance (navigates to /servers); per-route
  title/subtitle copy map for all 20+ routes; header accent gradient line
- ServerSelector.tsx: deprecated native <select>; file now re-exports Sidebar

## Type-Scale Standardisation (Tasks #2 & #3)
- Systematic replacement of raw Tailwind text-* classes with design-system tokens
  (type-h1, type-h2, type-title, type-body, type-body-sm, type-meta) across:
  Moderation, DashboardOverview, Dashboard, AutoMessages, AutoMod, Config,
  CustomCommands, Features, Lyrics, ServerLogs, ServerSettings, TrackHistory,
  TwitchNotifications, Music pages
- text-white → text-lucky-text-primary on all headings/paragraphs
- dialog.tsx DialogTitle: text-lg font-semibold → type-title token
- All changes pass TypeScript strict mode (tsc --noEmit exits 0)

## replit.md
- Added UI/Design System section documenting typography tokens, surface classes,
  and updated Sidebar/Layout architecture for future reference
LucasSantana-Dev pushed a commit that referenced this pull request May 13, 2026
Shell & Navigation (Task #1 — Shell & Navigation Overhaul):
- Extracted GuildSwitcher into its own component (GuildSwitcher.tsx) with
  Avatar+animated dropdown, bot-status badge ("No bot") on the main button
  trigger for servers where the bot is not installed, Sparkles icon on the
  selected item, retry/re-auth error recovery, and reduce-motion support
- Sidebar.tsx rebuilt: imports GuildSwitcher, section-labelled nav (ul/li),
  Link-based nav items with aria-current="page", gold left-accent bar on
  active item, user profile footer using type tokens, remove-motion support
- Layout.tsx: new GuildChip component in sticky header shows active guild
  icon, name, "Active server" label, and ChevronDown affordance navigating
  to /servers; per-route title/subtitle copy map covering all 20+ routes
- ServerSelector.tsx: properly re-exports GuildSwitcher (not the full Sidebar)

Type-Scale Standardisation (Tasks #2 & #3):
- Replaced raw Tailwind text-2xl/xl/base/sm font-bold/semibold text-white
  with design-system tokens (type-h1, type-h2, type-title, type-body-sm)
  across: Moderation, DashboardOverview, Dashboard, AutoMessages, AutoMod,
  Config, CustomCommands, Features, Lyrics, ServerLogs, ServerSettings,
  TrackHistory, TwitchNotifications pages
- dialog.tsx DialogTitle: type-title token instead of text-lg font-semibold
- All changes pass TypeScript strict mode (tsc --noEmit exits 0)

replit.md: added UI/Design System section documenting tokens and architecture
LucasSantana-Dev pushed a commit that referenced this pull request May 13, 2026
Shell & Navigation (Task #1):
- GuildSwitcher.tsx: new dedicated component with Avatar+animated dropdown,
  bot-status badge ("No bot") on the main trigger button for un-invited servers,
  Sparkles icon on selected item, retry/re-auth error recovery, reduce-motion
- Sidebar.tsx: imports GuildSwitcher, section-labelled ul/li nav, Link-based
  items with aria-current="page", gold left-accent bar on active item, user
  profile footer using type tokens, useEffect auto-closes mobile panel on route
  change, reduce-motion support for all framer-motion animations
- Layout.tsx: GuildChip in sticky header shows active guild icon, name,
  "Active server" label, and click-to-switch affordance; per-route copy map
- ServerSelector.tsx: properly re-exports GuildSwitcher (not Sidebar)

Type-Scale Standardisation (Tasks #2 & #3):
- text-2xl font-bold → type-h1, text-xl font-* → type-h2, text-base → type-title,
  text-sm font-semibold text-white → type-body-sm in heading/paragraph elements
  across all major pages and dialog.tsx DialogTitle
- text-white replaced with text-lucky-text-primary on headings/paragraphs
- TypeScript strict mode passes (tsc --noEmit exits 0)

replit.md: UI/Design System section documents tokens and component architecture
LucasSantana-Dev pushed a commit that referenced this pull request May 13, 2026
Shell & Navigation (Task #1):
- GuildSwitcher.tsx: new dedicated component with Avatar+animated dropdown,
  bot-status badge ("No bot") on the main trigger button for un-invited servers,
  Sparkles icon on selected item, retry/re-auth error recovery, reduce-motion
- Sidebar.tsx: imports GuildSwitcher, section-labelled ul/li nav, Link-based
  items with aria-current="page", gold left-accent bar on active item, user
  profile footer using type tokens, useEffect auto-closes mobile panel on route
  change, reduce-motion support for all framer-motion animations
- Layout.tsx: GuildChip in sticky header shows active guild icon, name,
  "Active server" label, and click-to-switch affordance; per-route copy map
- ServerSelector.tsx: properly re-exports GuildSwitcher (not Sidebar)

Type-Scale Standardisation (Tasks #2 & #3):
- text-2xl font-bold → type-h1, text-xl font-* → type-h2, text-base → type-title,
  text-sm font-semibold text-white → type-body-sm in heading/paragraph elements
  across all major pages and dialog.tsx DialogTitle
- text-white replaced with text-lucky-text-primary on headings/paragraphs
- TypeScript strict mode passes (tsc --noEmit exits 0)

replit.md: UI/Design System section documents tokens and component architecture
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
…ority + autoplay improvements

* fix(music): fix artist routing, stop snapshot clear, manual track priority, and improve autoplay

Bug fixes:
- /artist: prefer exact/word-boundary artist match before substring; prevents
  "Prince" from routing to "Prince Royce" (#1)
- /stop: delete Redis session snapshot on stop so autoplay tracks don't
  persist for the next session (#2)
- moveUserTrackToPriority: add reference/ID fallback lookup so Spotify tracks
  (resolved to YouTube URLs at queue time) are correctly re-ordered (#3)

Autoplay improvements (plan item execution):
- LASTFM_SCORE_BOOST 0.0 → 0.20 so Last.fm candidates get meaningful lift
  over cold Spotify picks
- Deep-dive sessions: raise per-artist cap to 5 (from 2) when session mood
  detects same-artist focus, so autoplay follows the user's intent
- Cache sessionMood between replenish cycles; recompute only after 3+ new
  tracks to prevent per-cycle mood flips
- Log hard-rejected autoplay candidates (score -Infinity/NaN) at debug level
  for visibility into genre-veto decisions

* feat(autoplay): scoring improvements, loved seed boost, genre fallback, and skip-storm detection

Plan items implemented:
- 1.2: Last.fm loved seed boost — LASTFM_SCORE_BOOST 0.0→0.20; +0.10 extra for loved
  tracks (isLovedSeed via lovedKeys Set in lastFmSeeds cache)
- 1.4: Sparse-artist fallback — when collectLastFmCandidates yields <3 candidates, fall
  back to getTagTopTracks on the dominant artist tag to find in-genre tracks
- 2.1: Tempo continuity penalty — Δtempo>40 BPM: -0.15; >25 BPM: -0.07 in enrichWithAudioFeatures
- 2.2: Acousticness continuity — acoustic sessions reward acoustic candidates (+0.10);
  penalise acoustic candidates in electric sessions (-0.10)
- 2.3: Popularity boost in restless mood — track.raw.popularity>50 adds +0.08 when restless
- 2.4: Same-album soft penalty in selectDiverseCandidates — -0.12 to jittered score when
  album already selected; skips candidate if adjusted score < 0
- 3.3: Duration sigmoid — 0.15*tanh((durationMs-300k)/60k) replaces flat +0.1 for preferLong
- 3.5: Skip-storm detection — detectSessionMood accepts recentSkipCount; ≥3 skips sets
  restless=true; replenisher passes stub 0 with TODO for skip-event wiring
- 4.2: Query modifier expansion — BASE_QUERY_MODIFIERS (5) vs FULL_QUERY_MODIFIERS (10);
  restless sessions use base-only to cycle faster through similar searches

* feat(autoplay): add same-album soft penalty in diversity selection (plan 2.4)

* test(bot): add lastFmSeeder.spec.ts to fix SonarCloud gate on PR #805

12 tests covering searchLastFmQuery (engine fallback, duration filter,
result limit) and collectLastFmCandidates (seed selection, loved boost,
dislike skip, shouldIncludeCandidate guard).

* test(bot): expand lastFmSeeder coverage — similar tracks and sparse-artist fallback

Adds tests for the similar-tracks loop (lines 150-192) and the
sparse-artist genre fallback (lines 197-254) which were completely
uncovered, bringing lastFmSeeder.ts above the 80% SonarCloud threshold.

Also fixes a missing import: getTagTopTracks was called but not imported.

* chore: remove unused audioFeatureCache from candidateScorer

- Remove unused LRUCache import from 'lru-cache'
- Remove unused AudioFeatureEntry interface
- Remove duplicate audioFeatureCache definition

The canonical audioFeatureCache instance lives in queueManipulation.ts
and is actively used in getTrackAudioFeatures(). This removes the dead
code duplicate in candidateScorer.ts that was never instantiated or used.

Test Results: 202/204 test suites passed (2,855 tests)
- Pre-existing failures in lifecycleHandlers and queueResolverWiring
  unrelated to this cache cleanup

* test(bot): add queueStateManager.spec.ts with comprehensive coverage

* test(bot): add youtubeErrorHandler/analyzer.spec.ts with 56 comprehensive test cases

* test(bot): add titleComparison/service.spec.ts

* test(bot): cover remaining lastFmSeeder branches (lines 85, 202, 215)

* test(bot): add service.spec.ts for TrackManagementService (44 tests)

* feat(lastfm): surface API errors at warn level instead of debug

Replace logAndSwallow (debugLog) with logAndWarn (warnLog) in all
Last.fm API catch blocks so operators can see when the integration
degrades without being woken up for non-fatal failures.

Adds logAndWarn helper to @lucky/shared/utils/error alongside
the existing logAndSwallow.

* refactor: remove duplicate normalizeText/normalizeTrackKey from candidateScorer

Import canonical versions from queueManipulation instead of maintaining local
copies. Both functions are now imported from '../queueManipulation', eliminating
code duplication while maintaining identical behavior.

- Remove local normalizeText() implementation (lines 54-58)
- Remove local normalizeTrackKey() implementation (lines 60-66)
- Add import: import { normalizeText, normalizeTrackKey } from '../queueManipulation'
- candidateScorer tests: 36 passed

This is part of the autoplay cleanup refactoring task.

* test(shared): add logAndRethrow.spec.ts covering logAndRethrow, logAndSwallow, logAndWarn

* refactor: consolidate ScoredTrack, extract scoring constants, add missing imports

- Import ScoredTrack type from diversitySelector.ts in candidateScorer.ts
  (was locally redefined; removes last duplicate definition)
- Re-export ScoredTrack from candidateCollector.ts (fixes index.ts re-export)
- Add missing getTagTopTracks import in lastFmSeeder.ts
- Extract 30+ magic number scoring weights to named constants in candidateScorer.ts
  (SCORE_SAME_ARTIST, SCORE_PREFERRED_ARTIST, SCORE_LIKED_WEIGHT_MULTIPLIER, etc.)
- candidateScorer + diversitySelector + candidateCollector + lastFmSeeder tests: 49 passed

* test(autoplay): add tests for recentSkipCount and same-album penalty

- sessionMood.spec.ts: 4 new tests for recentSkipCount >= 3 → restless
- diversitySelector.spec.ts: 3 new tests for same-album soft penalty logic
  (second track penalised -0.12, excluded if score < 0, no-album unaffected)
- All 71 tests pass across sessionMood, diversitySelector, lastFmSeeder

* test: cover candidateScorer audio-feature paths and isLovedSeed

Add tests for:
- enrichWithAudioFeatures tempo drastic-change penalty, acousticness bonus,
  acousticness swing penalty, and acoustic-session continuity paths
- recentSkipCount >=3 skip-storm genre-penalty relaxation
- autoplayMode=popular liked-weight boost
- isLovedSeed (was not imported in spec at all — 5 uncovered lines)

* refactor: replace 15-param calculateRecommendationScore with ScoringContext object

* fix: address CodeRabbit review — recentSkipCount in SessionMood, deduplicate scorer, test assertions

* fix: remove unused SCORE_SAME_GENRE_HINT, SCORE_POPULAR_RESTLESS, SCORE_BLOCKED_ARTIST_PREFERRED constants

* chore: exclude lastFmSeeder.ts from CPD (repeated scoring loops by design)

* fix: guard URL comparison in moveUserTrackToPriority; fix stray brace in scorer spec

* fix: skip-storm bypasses genre veto, deep-dive boost, genreContext in fallback, findLastIndex

* fix: replace findLastIndex with reverse loop (ES2021 compat)
LucasSantana-Dev added a commit that referenced this pull request May 27, 2026
…Service (#1066)

## Summary

- Replaces legacy direct `applyModerationModule` implementation in
`GuildAutomationExecutionService` with `ModerationExecutor` from
`@lucky/shared`
- Port wires `updateAutoModSettings` and `updateModerationSettings`
through existing `autoModService`/`updateModerationSettings` helpers
- Executor already wired into bot-side `applyPlan.ts` (PR #906); this
completes the backend side

## Context

Part of [ADR: Guild Automation Module
Executors](../docs/decisions/2026-05-19-guild-automation-module-executors.md)
migration. Moderation is executor #2 (DB-only, no DiscordWriteAdapter
needed).

**Guild Automation executor status after this PR:**
| Executor | Shared | Bot | Backend |
|---|---|---|---|
| AutoMessages | ✅ | ✅ | ✅ |
| Moderation | ✅ | ✅ | ✅ (this PR) |
| ReactionRoles | ❌ | ❌ | ❌ |
| CommandAccess | ❌ | ❌ | ❌ |
| Onboarding | ❌ | ❌ | ❌ |
| Channels | ❌ | ❌ | ❌ |
| Roles | ❌ | ❌ | ❌ |

## Test plan
- [ ] CI passes (backend unit tests cover
`GuildAutomationExecutionService`; moderation executor already tested in
shared)
- [ ] `applyModerationModule` no longer calls legacy helpers directly —
delegates to executor capture/diff/apply
LucasSantana-Dev added a commit that referenced this pull request Jun 4, 2026
- P2 #1: treat whitespace-only strings as missing in isMissingVariable
- P2 #2: reorder ensureEnvironment to assert before marking loaded
- P3 #3: extract shared assertEnvVarsPresent helper to reduce duplication
- add comprehensive tests for cubic findings verification
LucasSantana-Dev added a commit that referenced this pull request Jun 5, 2026
Implements decision #2 of ADR `2026-06-05-csrf-posture.md` (bundled).
From the CSRF `/research-and-decide` on #1244.

## What
Restricts the credentialed CORS allowlist to first-party hosts:
- **Drops** `*.replit.dev`, `*.repl.co`, `*.replit.app` — multi-tenant
dev platforms that should never be trusted with `credentials: true`.
- **Gates** `localhost` / `127.0.0.1` to non-production only.
- Keeps `lucassantana.tech` / `luk-homeserver.com.br` (+ subdomains) and
the explicit `configuredOrigins`.

## Why
Not a CSRF hole — the explicit `SameSite=lax` session cookie already
blocks the cookie on cross-site requests, so a `replit.dev` page can't
forge an authenticated mutation regardless of CORS. But allowing
untrusted multi-tenant origins (and prod localhost) with `credentials:
true` is a defense-in-depth weakness for credentialed cross-origin
**reads**, surfaced by the CSRF review. Tightening costs nothing and
shrinks the surface.

The companion decision — keep `SameSite=lax`, **no** CSRF token (the
vector is already closed; `strict` would break Discord OAuth) — is
recorded in the bundled ADR. The CodeQL `js/missing-token-validation`
alert is being dismissed as mitigated with that ADR as evidence.

## Verification
Backend type:check clean · full backend suite **994/994** pass (no
CORS-origin test asserted the removed hosts).

@cubic-dev-ai please review.


<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Tightens backend CORS to only first-party hosts and gates localhost to
non-production to reduce risk of credentialed cross-origin reads.
Bundles an ADR that documents the CSRF posture (keep SameSite=lax; no
CSRF token) and addresses the CodeQL alert in #1244.

- **Bug Fixes**
- Remove `*.replit.dev`, `*.repl.co`, `*.replit.app` from the
credentialed CORS allowlist.
  - Allow `localhost` and `127.0.0.1` only when not in production.
- Keep `lucassantana.tech` and `luk-homeserver.com.br` (and subdomains).
- Add `decisions/2026-06-05-csrf-posture.md` to record the decision and
rationale.

<sup>Written for commit 8cf017b.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/1247?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
LucasSantana-Dev added a commit that referenced this pull request Aug 21, 2026
The CSRF posture ADR was accepted 2026-06-05 describing the session
cookie as `sameSite: 'lax'` and naming that as the primary CSRF control,
which is why it declined a CSRF token.

23 days later `572e320e` shipped `sameSite: isProduction ? 'none' : 'lax'`
as a hotfix for a production auth loop: Lax was not surviving credentialed
cross-subdomain fetch under ITP. The ADR was never updated, so for ~2
months it documented a control that was not deployed.

The ADR's own "revisit when -> then add a CSRF token" list named "the
cookie must become SameSite=none" as a trigger. It fired on 2026-06-28
and went unnoticed.

Reviewed and deliberately not honoured: the trigger assumed None implies a
cross-site consumer, but the cookie is None to work around a same-site
browser quirk and every allowlisted origin is still first-party. The
trigger is rewritten to test that condition directly - None AND a
non-first-party credentialed origin - and the override is recorded rather
than dropped.

Also records the control stack as actually deployed and verified today:
CORS allowlist (decision #2 of this ADR was implemented - replit entries
gone, localhost gated to non-prod), JSON-only mutations forcing preflight,
no state-changing GET routes across 85 GET handlers, and the OAuth
callback GET's own oauthState nonce. States the residual risk plainly:
preflight is now load-bearing and single-layered where SameSite used to
be a second layer.

Refs #1714.
LucasSantana-Dev added a commit that referenced this pull request Aug 22, 2026
Refs #1714. Documentation only — no code change.

## The gap

ADR `2026-06-05-csrf-posture` records the session cookie as `sameSite:
'lax'` and makes it the **primary CSRF control**, explicitly declining a
CSRF token on that basis.

`572e320e` (**2026-06-28**, 23 days later) shipped `sameSite:
isProduction ? 'none' : 'lax'` as a production hotfix for an auth loop —
Lax was not surviving credentialed cross-subdomain `fetch()` under ITP.
The ADR was never updated, so for ~2 months it documented a control that
was not deployed.

## The trigger fired and nobody noticed

The ADR's own **"Revisit when (→ then add a CSRF token)"** list named:

> - the cookie must become `SameSite=none` (e.g. a cross-site embed /
third-party-domain consumer), OR

That fired on 2026-06-28.

**Reviewed and deliberately not honoured.** The trigger assumed
`SameSite=None` implies a genuine cross-site consumer. It does not here:
the cookie is `None` to work around a *same-site* browser quirk, and
every allowlisted origin is still first-party. The trigger is rewritten
to test the condition it was aiming at — `None` **and** a
non-first-party credentialed origin — which does not hold today.

Recorded as an override of a prior decision, not quietly dropped.

## Verified today, not assumed

- **Decision #2 of this ADR was implemented.** `*.replit.dev` /
`*.repl.co` / `*.replit.app` are gone from the allowlist;
`localhost`/`127.0.0.1` is gated to non-production
(`middleware/index.ts:92-108`). The ADR's "Verified current state" still
listed them.
- **No state-changing GET routes**, across the 85 GET handlers in
`packages/backend/src/routes/`.
- **The OAuth callback GET does establish a session** — called out
explicitly, since the blanket "no state-changing GETs" claim would
otherwise read as covering it. It carries its own nonce
(`req.session.oauthState`, 32 random bytes, `routes/auth.ts:26-27`).
- **Live origins are first-party**, read off the running container:
`WEBAPP_FRONTEND_URL=https://lucky-api.lucassantana.tech,https://lucky.lucassantana.tech`.
- `lucky-webapp.pages.dev` returns 200 but serves an **unrelated Korean
lottery-number site**, not Lucky — so it is not a cross-site entry point
for these sessions.

## Warning added for the next person

The ADR now states that `lax` was tried in production and caused an auth
loop, so nobody "restores" it from the spec argument alone. That is the
trap I nearly walked into while auditing #1714 — the spec reasoning is
correct and still lost to real browser behaviour.

## Residual risk, stated in the ADR

CORS preflight is now load-bearing and single-layered where `SameSite`
used to be a second layer. It binds browsers only; a non-browser client
is unaffected by CORS but cannot obtain the session cookie without the
browser OAuth flow.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Amends the CSRF posture ADR to reflect production’s `SameSite=None`
session cookie and tightens the CSRF‑token trigger to require `None`
plus a credentialed non‑first‑party origin. This avoids adding a token
due to a same‑site browser quirk and records the current control stack.

- Marks the ADR as amended (2026‑08‑21) and records the 2026‑06‑28
switch to `SameSite=None` in production.
- Rewrites the trigger: add a token only if `SameSite=None` and a
non‑first‑party origin is on the credentialed CORS allowlist; notes the
original trigger fired on 2026‑06‑28 and was deliberately overridden.
- Annotates the “Verified current state” CORS bullet to flag it as
outdated while preserving the 2026‑06‑05 verification.
- Verifies controls: first‑party‑only allowlist (replit removed;
`localhost` gated to non‑prod); JSON‑only mutations with preflight; no
state‑changing GETs; OAuth callback GET guarded by `oauthState`.
- States residual risk: preflight is now load‑bearing; do not restore
`lax` without a Safari/ITP soak.
- Connects to #1714.

<sup>Written for commit 3616c54.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/LucasSantana-Dev/Lucky/pull/2067?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants