Commit graph

13505 commits

Author SHA1 Message Date
Cody Kickertz
f4f7253165
chore(ci): standardize branch naming to use main instead of master (#91)
- Update workflow triggers to use main instead of master
- Update CONTRIBUTING.md to reference main branch
- Aligns with documentation in CLAUDE.md

Closes #52

Note: Actual branch rename (master → main) must be done on GitHub.

Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-21 11:11:39 -06:00
Cody Kickertz
168ea24266
perf(backend): cache additional regex patterns (#89)
* perf(backend): cache regex patterns for better performance

- TransmissionBase: add static VersionRegex, share with Transmission
- SearchCriteriaBase: cache RepeatingPlusRegex
- SearchMovieComparer: cache QueryYearRegex
- XbmcMetadata: cache WatchedRegex

Avoids regex compilation on each method call.

Partially addresses #36

* fix(security): add regex timeout to prevent ReDoS vulnerabilities

All cached regex patterns now include TimeSpan.FromSeconds(1) timeout
to prevent potential denial of service from malicious input patterns.

---------

Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-21 10:38:37 -06:00
Cody Kickertz
b17381f53f
fix(frontend): replace any types with proper TypeScript types (#88)
* fix(frontend): replace any types with proper TypeScript types

- AutoSuggestInput: use Data type from popper.js for modifier callback
- Tooltip: use Data type from popper.js for computeMaxSize callback
- OverlayScroller: use ComponentPropsWithoutRef<'div'> for renderView
- index.ts: use unknown[] instead of any[] for logError parameters

Improves type safety and removes eslint-disable comments.

Partially addresses #37

* fix(frontend): use ModifierFn type and string values for Popper styles

- Use ModifierFn type from popper.js for modifier callbacks
- Calculate bottom/right from offset properties (top+height, left+width)
- Convert numeric style values to strings with 'px' suffix
- Fix typo: 'botton' -> 'bottom' in AutoSuggestInput

---------

Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-21 10:38:16 -06:00
Cody Kickertz
c89ee01b63
chore(ci): standardize branch naming to use main instead of master (#90)
- Update workflow triggers to use main instead of master
- Update CONTRIBUTING.md to reference main branch
- Aligns with documentation in CLAUDE.md

Closes #52

Note: Actual branch rename (master → main) must be done on GitHub.

Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-20 09:00:25 -06:00
Cody Kickertz
1230212df8
fix(frontend): memoize inline JSX objects for performance (#87)
- MovieIndexTable: memoize itemData, move row flex styles to CSS
- MovieIndexOverviews: memoize itemData, extract listStyle constant
- MovieIndexOverview: memoize elementStyle and infoStyle
- CircularProgressBar: memoize containerStyle and circleStyle

Reduces unnecessary re-renders in virtualized lists and frequently
rendered components.

Closes #41

Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-19 20:01:07 -06:00
Cody Kickertz
80c364110c
fix(ui): update user-facing links to Aletheia resources (#86)
- MoreInfo: point to Aletheia GitHub instead of Radarr resources
- UpdateChanges: link issue numbers to Aletheia repo
- Add "Upstream" translation key for Radarr reference link

Closes #53

Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-19 20:00:39 -06:00
Cody Kickertz
b6b1df9dfe
chore: update GitHub Actions and consolidate .editorconfig rules (#85)
Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-19 20:00:23 -06:00
Cody Kickertz
a73b82d40c
fix(frontend): remove index from React keys in dynamic lists (#84)
Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-19 19:35:56 -06:00
Cody Kickertz
c4dae9a279
fix: add null safety to LINQ First/Single calls (#83)
Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-19 19:35:45 -06:00
Cody Kickertz
934a18e9a5
perf: cache regex patterns in Parser.ToUrlSlug and FileNameBuilder.GetEditionToken (#82)
Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-19 19:35:29 -06:00
Cody Kickertz
f2fff6419d
refactor: notification provider deduplication + docs (#81)
* fix: SonarCloud null safety and struct comparison issues

- OsPath.cs: Remove ReferenceEquals checks on struct (always false)
- SkyHookProxy.cs: Add null-conditional operators for Credits.Cast/Crew

* fix: remaining React index-as-key issues and backend null safety

Frontend:
- Fix 8 remaining index-as-key violations using content-based keys
- ImportMovieSelectFolder.js: use errorMessage as key
- ImportMovieFooter.js: use errorMessage as key
- CustomFormat.js: use item.name as key
- AddSpecificationItem.js: use preset.name as key
- QualityProfileItems.js: use message as key
- QualityProfileFormatItems.js: use message as key

Backend (cherry-picked from batch-3):
- OsPath.cs: Remove ReferenceEquals on struct
- SkyHookProxy.cs: Add null-conditional for Credits

* refactor(notifications): consolidate GetPosterUrl to base class

* docs: add architectural decisions log

* fix(sonar): enable path traversal suppressions for media management app

---------

Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-19 19:35:14 -06:00
Cody Kickertz
b7d5ffb6e9
fix: remaining React index-as-key issues + backend null safety (#78)
* fix: SonarCloud null safety and struct comparison issues

- OsPath.cs: Remove ReferenceEquals checks on struct (always false)
- SkyHookProxy.cs: Add null-conditional operators for Credits.Cast/Crew

* fix: remaining React index-as-key issues and backend null safety

Frontend:
- Fix 8 remaining index-as-key violations using content-based keys
- ImportMovieSelectFolder.js: use errorMessage as key
- ImportMovieFooter.js: use errorMessage as key
- CustomFormat.js: use item.name as key
- AddSpecificationItem.js: use preset.name as key
- QualityProfileItems.js: use message as key
- QualityProfileFormatItems.js: use message as key

Backend (cherry-picked from batch-3):
- OsPath.cs: Remove ReferenceEquals on struct
- SkyHookProxy.cs: Add null-conditional for Credits

---------

Co-authored-by: admin <admin@ardentleatherworks.com>
2025-12-19 16:11:24 -06:00
Cody Kickertz
a5c2675c2b
Merge pull request #77 from cheir-mneme/fix/sonarcloud-batch-3
fix: SonarCloud null safety and struct comparison
2025-12-19 16:06:20 -06:00
admin
70cfd14971 fix: SonarCloud null safety and struct comparison issues
- OsPath.cs: Remove ReferenceEquals checks on struct (always false)
- SkyHookProxy.cs: Add null-conditional operators for Credits.Cast/Crew
2025-12-19 15:53:17 -06:00
Cody Kickertz
2612b184d8
Merge pull request #74 from cheir-mneme/fix/sonarcloud-bugs-2
fix: SonarCloud bugs batch 2
2025-12-19 15:44:53 -06:00
Cody Kickertz
88c81cf233
Merge pull request #73 from cheir-mneme/fix/sonarcloud-bugs
Fix SonarCloud bugs: threading, React state, sorting
2025-12-19 15:44:38 -06:00
admin
835ec47313 fix: SonarCloud bugs batch 2
- S2445: Make _connections readonly for thread-safe locking (MessageHub.cs)
- S6756: Use setState callbacks for 5 React components
- S1764: Remove duplicate expression in QualityProfileSelectInput.tsx
- S2583: Remove unreachable conditions in NotificationDefinition.cs
- S2259: Fix null reference in Pushcut.cs
2025-12-19 15:22:56 -06:00
Cody Kickertz
5aa9fd0abe
Merge pull request #72 from cheir-mneme/fix/sonarcloud-cleanup
Fix SonarCloud issues and add suppression config
2025-12-19 15:16:39 -06:00
admin
6d17e5eaff Fix SonarCloud bugs: threading, React state, sorting
Backend:
- S2445: Make _connections readonly in MessageHub.cs to fix locking issue

Frontend:
- S6756: Use callback form of setState when referencing previous state
  - Collection.js, DiscoverMovie.js, ImportMovie.js
  - ImportMovieSelectMovie.js, EditQualityProfileModalContentConnector.js
- S2871: Add localeCompare for proper alphabetical sorting
  - Collection.js, DiscoverMovie.js, MovieIndex.tsx
- S1764: Remove duplicate condition in QualityProfileSelectInput.tsx
2025-12-19 15:15:24 -06:00
Cody Kickertz
220eba471b
Merge pull request #71 from cheir-mneme/fix/eslint-v9-migration
Migrate to ESLint 9 flat config
2025-12-19 15:03:41 -06:00
admin
4cf5f1d576 Fix SonarCloud issues and add suppression config
Backend:
- Add regex timeout to prevent ReDoS (S6444):
  - SkyHookProxy.cs: ImdbUrlRegex, TmdbUrlRegex
  - PushsaferSettings.cs: HexColorRegex
  - Parser.cs: ImdbIdRegex

Frontend:
- Fix sorting without localeCompare (S2871):
  - MovieIndex.tsx, Collection.js, DiscoverMovie.js

Config:
- Add sonar-project.properties with documented false positive suppressions:
  - S8135: TMDB public API token (not a secret)
  - S6680: Directory depth iteration (naturally bounded)
  - S6674: NLog structured logging placeholder syntax
  - S4662: PostCSS mixin directives
  - S5145: Sanitized log data
2025-12-19 15:03:23 -06:00
admin
cca1b47936 Migrate to ESLint 9 flat config
- Create eslint.config.mjs with ESM flat config format
- Remove legacy .eslintrc.js and .eslintignore
- Remove eslint-plugin-filenames (not ESLint 9 compatible)
- Update lint-staged to use new config
- Clean up unused eslint-disable directives
2025-12-19 14:44:01 -06:00
Cody Kickertz
32d072dd8a
Merge pull request #70 from cheir-mneme/fix/p4-frontend
fix(frontend): React quality improvements - keys, types, memoization
2025-12-19 14:39:40 -06:00
admin
a7852b6fcf fix(frontend): address React and TypeScript quality issues
- Replace index-as-key antipattern with stable keys (#34)
- Remove TypeScript any types in favor of proper types (#37)
- Memoize inline style objects to prevent unnecessary re-renders (#41)

Files: 17 frontend components updated
2025-12-19 14:20:40 -06:00
Cody Kickertz
0366c8f258
Merge pull request #68 from cheir-mneme/fix/p4-backend
perf: backend optimizations for regex caching and O(n*m) patterns
2025-12-19 13:45:24 -06:00
Cody Kickertz
fcb1c783f7
Merge pull request #69 from cheir-mneme/fix/p4-audit-security
fix(security): address audit findings - path validation and ReDoS
2025-12-19 13:33:59 -06:00
admin
189039c875 fix(security): add path validation to OpenWriteStream and regex timeouts
- DiskProviderBase: Add Ensure.That path validation to OpenWriteStream
- CleanseLogMessage: Add 5-second timeout to all 22 regex patterns to prevent ReDoS
2025-12-19 13:22:25 -06:00
admin
dda89e2fda Optimize O(n*m) Contains patterns with HashSet
- MovieService.FindByTitle: Convert title lists to HashSets
- MoviesSearchService: Convert queue IDs to HashSet
2025-12-19 13:11:07 -06:00
admin
0e5abe56f0 Cache regex instances as static compiled fields
- SkyHookProxy: Cache IMDB/TMDB URL regexes
- PushsaferSettings: Cache hex color validation regex
- Parser: Cache IMDB ID validation regex
2025-12-19 13:08:40 -06:00
Cody Kickertz
b85eb4fcde
Merge pull request #67 from cheir-mneme/fix/p3-security
fix(security): P3 security vulnerabilities and mitigations
2025-12-19 12:27:44 -06:00
admin
019f0862b3 fix(security): address P3 vulnerabilities and add mitigations
Security fixes:
- XXE prevention: disable XmlResolver in UTorrentProxy.cs (#42)
- Path traversal: validate paths in LogFileController.cs (#44)
- Path traversal: validate paths in MediaCoverController.cs (#44)
- ReDoS mitigation: add 5s timeout to user regex patterns

Documentation:
- CORS: document security rationale in Startup.cs (#43)

Closes #42, #43, #44
Related: #59, #60, #61 (SonarCloud triage - GitHub alerts now at 0 open)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 12:12:54 -06:00
Cody Kickertz
f7fca51da7
Merge pull request #66 from cheir-mneme/fix/p2-ci-tooling
fix(ci): P2 improvements - editorconfig, integration tests, Prettier 3
2025-12-19 12:00:25 -06:00
admin
7961b36547 fix(ci): P2 improvements - editorconfig, integration tests, Prettier 3
- Remove duplicate dotnet_style_qualification rules in .editorconfig
- Update Radarr branding to Aletheia in .editorconfig
- Add integration tests step to build.yml (with continue-on-error)
- Upgrade Prettier to 3.7.4, eslint-plugin-prettier to 5.5.4
- Upgrade eslint-config-prettier to 10.1.8
- Fix pre-existing lint errors (unused vars, radix parameter)
- Reformat frontend code with Prettier 3 formatting changes

Closes #57 (SonarCloud deferred - needs org setup)
Closes #58, #62 (partial - ESLint 9 deferred), #63

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 11:46:44 -06:00
Cody Kickertz
b10c795c24
Merge pull request #65 from cheir-mneme/fix/ci-p1-workflow
fix(ci): add CODEOWNERS, enable test blocking, add pre-commit hooks
2025-12-19 11:29:59 -06:00
admin
1fcbee8227 chore: update yarn.lock with husky and lint-staged 2025-12-19 11:13:45 -06:00
admin
37ed597adf fix(ci): add CODEOWNERS, enable test blocking, add pre-commit hooks 2025-12-19 11:03:07 -06:00
Cody Kickertz
ca643b656e
Merge pull request #64 from cheir-mneme/fix/ci-p0-cleanup
fix(ci): pin Trivy action and update branding
2025-12-19 10:53:53 -06:00
admin
c0ae8a8506 fix(ci): pin Trivy action and update branding 2025-12-19 10:44:32 -06:00
admin
a57775a9ee fix: thread-safe SHA1 hashing in HashConverter 2025-12-19 10:29:44 -06:00
admin
1fe49f6bf2 test: add IMDb list error message verification tests 2025-12-19 10:15:33 -06:00
Cody Kickertz
7b4f77604f
Merge pull request #49 from cheir-mneme/fix/technical-debt-cleanup
fix: Remaining technical debt bugs (Bug-001, Bug-006)
2025-12-19 10:03:38 -06:00
admin
0dc6442986 Fix CancellationTokenSource resource leaks (BLOCKER severity)
- ManagedHttpDispatcher: Dispose quickFailCts and linkedTokenSource in finally block
- CommandExecutor: Dispose _cancellationTokenSource on shutdown
- Scheduler: Dispose _cancellationTokenSource on shutdown
- IntegrationTestBase: Store CTS as field and dispose in TearDown

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 09:35:35 -06:00
admin
e2b2227a17 Fix blocking semaphore in MediaCoverService
Convert _semaphore.Wait() to async pattern with WaitAsync()
to prevent thread blocking during image resizing operations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 09:26:41 -06:00
admin
f435f38a27 Fix remaining technical debt bugs
- Bug-001: Add null check for SingleOrDefault() in TorrentRssParser
- Bug-006: Replace generic Exception with PathCombinationException in OsPath
- Bug-006: Replace generic Exception with NotSupportedException in IMDbListRequestGenerator
2025-12-19 09:05:54 -06:00
Cody Kickertz
d82f07e872
Merge pull request #31 from cheir-mneme/fix/sonarcloud-cleanup
refactor: SonarCloud technical debt cleanup
2025-12-19 08:42:54 -06:00
admin
79e3a6b126 Fix CodeQL rule ID for insecure-direct-object-reference 2025-12-18 21:42:06 -06:00
admin
320371ab71 Remove SonarCloud CI workflow - conflicts with automatic analysis 2025-12-18 21:30:57 -06:00
admin
09174a6303 Remove sonar-project.properties - not supported by SonarScanner for .NET 2025-12-18 21:25:33 -06:00
admin
94ff8a3874 Add CI-based SonarCloud workflow with rule exclusions 2025-12-18 21:21:09 -06:00
admin
809dfdafab Suppress S5145 log injection false positive in editorconfig 2025-12-18 21:15:30 -06:00