Skip to content

Replace deprecated browser metadata parser#18

Merged
ChrisAdamsdevelopment merged 1 commit into
mainfrom
codex/add-music-metadata-support-for-browser-parsing
May 4, 2026
Merged

Replace deprecated browser metadata parser#18
ChrisAdamsdevelopment merged 1 commit into
mainfrom
codex/add-music-metadata-support-for-browser-parsing

Conversation

@ChrisAdamsdevelopment
Copy link
Copy Markdown
Owner

@ChrisAdamsdevelopment ChrisAdamsdevelopment commented May 4, 2026

Motivation

  • music-metadata-browser is deprecated and pulled vulnerable nested parser deps, so browser-side metadata analysis was migrated to the maintained music-metadata package while preserving the existing UX and app behavior.
  • The browser path must remain resilient: lazy parser loading, parse failure fallback with parseError, boundary-aware marker detection, filename marker scanning, and safe Quick Cleanse MP3 writing must be kept.

Description

  • Removed music-metadata-browser from package.json and updated the parser adapter in src/utils/metadata.js to dynamically import music-metadata and resolve parseBlob while preserving the memoized lazy loader and original readFileMetadata return shape (format, title, artist, genre, detectedMarkers, provenanceRisk, raw, parseError).
  • Added conservative browser safeguards: a max file-size guard (MAX_BROWSER_PARSE_BYTES = 100MB) that skips parsing and returns a parseError, and a parser timeout (PARSE_TIMEOUT_MS = 8000ms) implemented via withTimeout that returns a parseError when triggered.
  • Preserved boundary-aware marker regex logic, filename marker scanning, safeText sanitization, and the Quick Cleanse MP3 writer path (writeMP3Metadata using browser-id3-writer) unchanged.
  • Updated package-lock.json, docs/manual-qa-checklist.md, and README.md to remove the old deprecation note and document the new music-metadata usage and graceful-fallback behavior.

Testing

  • npm install completed successfully and npm run build completed successfully (Vite build finished; frontend bundles produced).
  • npm audit --json was run and the post-change audit reports 2 moderate vulnerabilities; before/after diff was not captured in this run.
  • npm outdated || true was executed and produced informational output; build and install steps passed.
  • Post-change validations performed: package-lock.json no longer contains music-metadata-browser, src/utils/metadata.js now dynamically imports music-metadata, readFileMetadata still catches parse failures and returns a parseError on fallback, Quick Cleanse still uses writeMP3Metadata, and Full Server Cleanse (/api/process) and auth/Stripe/usage/API/Docker behaviors were not modified.

Codex Task

Summary by Sourcery

Replace the deprecated browser metadata parser with the maintained music-metadata library while adding defensive limits and updating documentation and dependencies.

New Features:

  • Introduce browser-side file size and parse timeout guards for metadata analysis, returning a structured parseError when limits are exceeded or parsing fails.

Bug Fixes:

  • Eliminate reliance on the deprecated music-metadata-browser package to reduce exposure to vulnerable nested dependencies in browser-side metadata parsing.

Enhancements:

  • Switch browser metadata parsing to dynamically import music-metadata while preserving the existing readFileMetadata return shape and marker detection behavior.
  • Add a generic withTimeout helper around metadata parsing to prevent long-running browser parses from hanging the UI.

Build:

  • Remove music-metadata-browser from package.json and update the lockfile to reflect the new dependency set.

Documentation:

  • Document the new music-metadata-based browser analysis path, its graceful parseError fallback behavior, and clarify Quick Cleanse vs Full Server Cleanse responsibilities in README and manual QA checklist.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 4, 2026

Reviewer's Guide

Replaces the deprecated browser-side metadata parser with the maintained music-metadata library, adding defensive limits and timeouts while preserving existing metadata extraction behavior and Quick Cleanse paths.

Sequence diagram for updated browser metadata parsing with lazy loading and timeout

sequenceDiagram
  title Browser_metadata_parsing_flow_with_lazy_loading_and_timeout
  actor User
  participant BrowserUI
  participant MetadataUtils as metadata_js
  participant MusicMetadata as music_metadata_library

  User->>BrowserUI: Selects_audio_file
  BrowserUI->>MetadataUtils: readFileMetadata(file)

  MetadataUtils->>MetadataUtils: Check_file_size(file.size)
  alt File_size_exceeds_MAX_BROWSER_PARSE_BYTES
    MetadataUtils->>MetadataUtils: Throw_Error(File_too_large)
    MetadataUtils-->>BrowserUI: Return_metadata({parseError, format, title, artist, genre, detectedMarkers, provenanceRisk, raw})
    BrowserUI-->>User: Show_parse_error_and_continue_fallback
  else File_size_within_limit
    MetadataUtils->>MetadataUtils: getParseBlob()
    alt First_time_load
      MetadataUtils->>MusicMetadata: dynamic_import(music-metadata)
      MusicMetadata-->>MetadataUtils: parseBlob_export
    else Cached_loader
      MetadataUtils-->>MetadataUtils: Reuse_cached_parseBlob
    end

    MetadataUtils->>MetadataUtils: withTimeout(parseBlob(file), PARSE_TIMEOUT_MS)
    alt Parse_completes_before_timeout
      MusicMetadata-->>MetadataUtils: Parsed_metadata
      MetadataUtils->>MetadataUtils: Detect_markers_and_sanitize
      MetadataUtils-->>BrowserUI: Return_metadata({format, title, artist, genre, detectedMarkers, provenanceRisk, raw})
      BrowserUI-->>User: Proceed_with_metadata_driven_workflow
    else Parse_times_out_or_throws
      MusicMetadata-->>MetadataUtils: Error_or_timeout
      MetadataUtils->>MetadataUtils: Set_parseError
      MetadataUtils-->>BrowserUI: Return_metadata({parseError, format, title, artist, genre, detectedMarkers, provenanceRisk, raw})
      BrowserUI-->>User: Show_parse_error_and_continue_fallback
    end
  end

  note over BrowserUI,MetadataUtils: Quick_Cleanse_MP3_writing_still_uses_writeMP3Metadata_with_browser_id3_writer
Loading

Class diagram for updated metadata utilities using music-metadata with timeout

classDiagram
  class metadata_js {
    <<module>>
    +AI_MARKERS : string[]
    +MARKER_REGEX_CACHE : Map
    +MAX_BROWSER_PARSE_BYTES : number
    +PARSE_TIMEOUT_MS : number
    +getParseBlob() Promise
    +withTimeout(promise, timeoutMs) Promise
    +escapeRegex(value) string
    +getMarkerRegex(marker) RegExp
    +detectMarkersFromText(text) string[]
    +detectMarkersFromFilename(name) string[]
    +safeText(value) string
    +readFileMetadata(file) Promise~MetadataResult~
    +writeMP3Metadata(file, metadata) Promise~File~
  }

  class MusicMetadataLibrary {
    <<external_library>>
    +parseBlob(blob) Promise~ParsedMetadata~
  }

  class MetadataResult {
    +format : any
    +title : string
    +artist : string
    +genre : string
    +detectedMarkers : string[]
    +provenanceRisk : string
    +raw : any
    +parseError : Error
  }

  class QuickCleanseFlow {
    <<browser_feature>>
    +invokeQuickCleanse(file) void
  }

  class BrowserID3Writer {
    <<external_library>>
    +setFrame(frameId, value) BrowserID3Writer
    +addTag() void
  }

  metadata_js ..> MusicMetadataLibrary : dynamic_import_music_metadata_and_use_parseBlob
  metadata_js ..> MetadataResult : constructs
  QuickCleanseFlow --> metadata_js : uses_writeMP3Metadata
  metadata_js ..> BrowserID3Writer : uses_for_MP3_metadata_writing
Loading

File-Level Changes

Change Details Files
Switch browser metadata parsing from music-metadata-browser to music-metadata with lazy dynamic import and timeout handling.
  • Updated the lazy loader in getParseBlob to dynamically import music-metadata instead of music-metadata-browser and validate the parseBlob export.
  • Introduced a withTimeout helper that wraps parseBlob calls and enforces a configurable parse timeout, propagating failures as errors.
  • Adjusted readFileMetadata to use the new withTimeout wrapper around parseBlob while keeping the existing return shape and error capture via parseError.
src/utils/metadata.js
Add browser-side safety limits for metadata parsing based on file size and preserve existing marker detection and writing paths.
  • Defined MAX_BROWSER_PARSE_BYTES (100MB) and added a guard in readFileMetadata that skips parsing oversized files and surfaces a parseError.
  • Ensured boundary-aware AI marker regex caching, filename marker scanning, and safeText sanitization logic remain unchanged.
  • Kept Quick Cleanse MP3 metadata writing via browser-id3-writer (writeMP3Metadata) intact, ensuring only the read path was altered.
src/utils/metadata.js
Remove deprecated music-metadata-browser dependency and update documentation to reflect the new parser behavior and safeguards.
  • Removed music-metadata-browser from package.json and refreshed package-lock.json to drop the deprecated dependency and its transitive tree.
  • Updated manual QA checklist to describe the new music-metadata-based browser analysis, including lazy loading, size bounds, and timeout fallback behavior.
  • Documented in README that browser metadata analysis uses music-metadata with graceful fallback and clarified Quick Cleanse vs Full Server Cleanse responsibilities.
package.json
package-lock.json
docs/manual-qa-checklist.md
README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@ChrisAdamsdevelopment ChrisAdamsdevelopment merged commit bfe4fe0 into main May 4, 2026
2 of 5 checks passed
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant