Skip to content

Releases

Infinitune 1.5.1: the radio opens over plain HTTP again

Choose a tag to compare

@beastyrabbit beastyrabbit released this 27 Oct 07:55
7200c92

Note

🤖 Claude Opus 5.5 responding on behalf of beastyrabbit

The radio opens again when you reach Infinitune over plain HTTP, for example on its LAN address. Since 1.1.0, /autoplayer crashed in that setup before anything rendered. This release also stops two Node 26 startup warnings from being reported to GlitchTip as errors at every pod start.

1.5.0 over http:// 1.5.1 over http://
1.5.0: /autoplayer shows ERROR, SOMETHING WENT WRONG 1.5.1: /autoplayer renders the radio player

Both captured with no backend running, which is why the yellow "Reconnecting to server..." bar shows. Technical note with setup and console output.

Fixed

  • /autoplayer over plain HTTP. Browsers only provide crypto.randomUUID on HTTPS and localhost, and the radio listener ID depended on it, so the page failed with crypto.randomUUID is not a function. The listener ID now falls back to a random v4 UUID built from crypto.getRandomValues, which works on any origin. HTTPS behaves as before.
  • No localStorage warning during server rendering. The player reads and writes its saved volume and mute setting only in the browser. Server rendering uses the defaults, so Node 26 no longer prints its localStorage ExperimentalWarning. Your saved volume and mute still apply once the page loads.
  • No module.register() deprecation at startup. Server telemetry no longer installs Sentry's ESM loader hooks. Infinitune doesn't use the automatic instrumentation they serve, so Node 26 stops printing DEP0205. Manual telemetry spans still work.
  • Node warnings stay out of GlitchTip. Captured console output that is a Node process warning ((node:<pid>) …Warning: …) is dropped before sending, so the next deprecation doesn't open a new issue. Other console.error output and exceptions are still reported.

Also new since 1.4.3

1.5.0 was tagged and deployed without release notes. It added:

  • GET /api/version, which returns { "release": "<version>" } with Cache-Control: no-store and nothing else.
  • Safer releases. A version tag now publishes an image only after main CI has passed for that exact commit. After publishing, the workflow waits until the homelab deployment reports the new version and its front page responds. See docs/releasing.md. (#81)

Upgrading

No configuration, schema or data changes. Pull the new image or let Flux roll it out.

Full change: #82 (and #81 for 1.5.0).

Infinitune 1.4.3: the privacy policy states the 25-month analytics retention

Choose a tag to compare

@beastyrabbit beastyrabbit released this 21 Oct 22:18
759e461

Note

🤖 Claude Opus 5.5 responding on behalf of beastyrabbit

The privacy policy now states the actual retention for usage analytics. Umami analytics data is deleted automatically after 25 months; before, the page said it was kept for up to 10 years.

Changed

  • Umami retention on /datenschutz and /privacy. Analytics data is deleted automatically after 25 months by a nightly deletion job on the homelab. Both languages also still state that no session recordings take place: replay and heatmaps are disabled for Infinitune.
  • GlitchTip unchanged. Error reports are still deleted after 90 days at the latest, matching the server's setting.

Full change: #80.

Infinitune 1.4.2: the app starts in the browser again

Choose a tag to compare

@beastyrabbit beastyrabbit released this 21 Oct 21:46
fec0a2d

Note

🤖 Claude Opus 5.5 responding on behalf of beastyrabbit

Infinitune starts in the browser again. Since 1.3.0, every client JavaScript chunk was delivered 358 bytes short. Pages rendered but stayed unresponsive, and browser analytics never started.

Fixed

  • Complete JavaScript chunks. The image build added GlitchTip debug IDs to the client files after the SSR server had already recorded their sizes, so the server kept sending the old, shorter lengths. The debug IDs are now added during the Vite build, before those sizes are recorded.
  • A build guard against this. The Docker build now starts the built frontend and fails if any served JavaScript file differs from the file on disk or doesn't parse.

Verified on the live deployment: the app hydrates without page errors, Umami receives page views, and a browser error in GlitchTip shows its original source file and line through the uploaded source maps.

1.4.1 and earlier back to 1.3.0 contain the broken build; upgrade to this version. Full change: #79.

Infinitune 1.4.1: playlists with / or % in their key open again

Choose a tag to compare

@beastyrabbit beastyrabbit released this 21 Oct 19:53
1296ea1

Note

🤖 Claude Opus 5.5 responding on behalf of beastyrabbit

Playlists whose key contains / or %, such as summer/2026 or 100% chill, open again. In 1.4.0 the server answered those requests with 400, from the web app and from the infi CLI alike.

Fixed

  • Encoded playlist keys work again. 1.4.0 added a path check because the legal pages were going to be reachable without signing in. They now stay behind the same sign-in as the rest of Infinitune, so the check had nothing left to protect and only broke URL-encoded keys. It is removed from the web server, the API and WebSocket connections; path and key handling match 1.3.0 again.
  • Playlist keys follow the 1.3.0 rules again. 1.4.0 also refused new keys containing /, \ or %; that restriction is gone.

The Impressum, privacy policy and footer links from 1.4.0 are unchanged.

Full change: #78.

Infinitune 1.4.0: legal pages anyone can open

Choose a tag to compare

@beastyrabbit beastyrabbit released this 21 Oct 16:15
6e14e5a

Note

🤖 Claude Opus 5.5 responding on behalf of beastyrabbit

Infinitune now has a German Impressum and Datenschutzerklärung, with English versions. Anyone can read them without signing in, and every page of the app links to them.

Datenschutzerklärung at desktop width

Legal pages anyone can open

  • Impressum and privacy policy at /impressum and /datenschutz, in English at /legal-notice and /privacy. They are standalone pages: they load no app code, make no API calls and set no cookies, so they work even for visitors who can't sign in. Search engines are told not to index them.
  • Footer links ("Legal notice", "Privacy") on every app page, including error and not-found pages. The embedded mini player stays clean.
  • The privacy policy describes what Infinitune actually does with data: sign-in through the homelab's SSO, stored playlists and songs, text generation with OpenAI, music generation on the operator's own hardware, the self-hosted Umami and GlitchTip, logs and browser storage. The full data-flow inventory is in docs/legal/privacy-inventory.md.

Footer links on the player

Impressum on a phone

Privacy and hardening

  • Server logs now expire. Entries in the server's own log files are deleted no later than 14 days after they were written. Before this, every log file was kept forever.
  • No session replay. The app no longer loads Umami's session recorder or heatmaps; only usage events and page views are counted.
  • Unusual encoded paths are rejected. The web server and the API answer 400 to request paths with encoded /, \, % or ., backslashes or ./.. segments, and WebSocket upgrades on such paths are refused. This keeps the public legal pages from becoming a way around sign-in.

Upgrade notes

  • Playlist keys containing /, \ or %, or equal to . or .., are now rejected when a playlist is created, because they could not be read back. Generated keys are unaffected.

Full change: #77.

Infinitune 1.3.0: usage analytics and error tracking

Choose a tag to compare

@beastyrabbit beastyrabbit released this 21 Oct 21:46
35874ac

Note

🤖 Claude Opus 5.5 responding on behalf of beastyrabbit

Infinitune now reports how it is used to the homelab's own Umami and its errors to the homelab's own GlitchTip, on every part of the app: the browser, the generation pipeline, the SSR frontend and the infi CLI. Both are self-hosted in Germany and configured at runtime, and they stay off when unconfigured, in local development and in tests.

Warning

This release's Docker build served every client JavaScript chunk 358 bytes short, so the app rendered but never started in the browser. Use 1.4.2 or later. 1.4.0 and 1.4.1 share the problem.

New

  • Usage analytics in Umami. Page views, including in-app navigation; Web Vitals; outbound links; and events for the main flows: playlists created, steered and closed; songs played, completed, skipped and rated; requests; room joins; settings changes; and playback or save failures. Properties pass through an allowlist: prompts become lengths, and no lyrics, identities, device names or share tokens are sent. There is no identify call.
  • Generation pipeline events. The server reports when a song starts, completes or fails generation, with stage, provider, model and duration. These reports never block or fail a song.
  • Error tracking in GlitchTip.
    • Browser: uncaught errors, rejections, console.error and the root error boundary. The SDK loads lazily, outside the main bundle.
    • Hono server, generation worker, Nitro SSR frontend: all report their errors.
    • infi CLI and daemon: report errors when configured.
    • Pipeline failures: reported with the original exception and with stage, provider and model tags.
    • Privacy: credentials, Pangolin identity headers, emails, tokens, query secrets and share links are scrubbed.
  • Readable stack traces. Each tagged release uploads hidden source maps to GlitchTip from CI. The maps are never served by the app.

Configuration

Both containers read UMAMI_URL, UMAMI_WEBSITE_ID, UMAMI_DOMAINS, GLITCHTIP_DSN, TELEMETRY_ENVIRONMENT and GLITCHTIP_TRACES_SAMPLE_RATE. The release value is built into the image. See docs/telemetry.md.

Full change: #76.

Infinitune 1.2.4: private CLI credentials and faster text cleanup

Choose a tag to compare

@beastyrabbit beastyrabbit released this 29 Sep 18:15
2c6a1e6

Note

🤖 GPT-6 responding on behalf of beastyrabbit

Infinitune 1.2.4 restricts saved CLI credentials to their owner and avoids slow text cleanup on malformed input.

Reviewed release build, shown in its empty radio state without a backend or AI calls:

Infinitune desktop radio

Mobile view

Credential handling

CLI configuration and systemd user-service files now use 0600 permissions before device tokens are written. Existing configuration files become private on their next save; existing service files are restricted when the service is installed again. The non-secret executable wrapper remains readable and executable with mode 0755.

New playlist keys use rejection-sampled cryptographic randomness while retaining their existing alphabet and length. Existing playlist keys remain valid.

Text processing and worker maintenance

HTML cleanup, URL normalization and worker-admin authorization parsing avoid unnecessary regex backtracking. The currently unused fenced-response utility received the same cleanup. Tests cover malformed text and long inputs. Worker callbacks no longer wrap void-returning actor dispatch in promises; actor processing and playback contracts are unchanged. Song-batch query keys use an explicit locale comparator, and the CLI preload contract marks its intentionally unused input.

Upgrade and verification

No database migration or new configuration is required. Token values can still be visible in process arguments. Restricting a file does not revoke access through a descriptor another process already opened. Seven CLI executable-lookup findings remain open because the application cannot prove every user's PATH is trusted.

Lint, type checks, the production build and 681 offline tests passed. The release candidate received an independent review by Claude Opus 5.5 at high effort. PR CI, SonarQube and Codex code/security reviews passed. No live AI provider was used for verification.

Changes since v1.2.3: #58 and #59. The two credential-file fixes are separate from SonarQube issue counts; the one wrapper false-positive classification is not a code fix.

The post-merge main analysis confirms 26 code findings fixed, one false-positive classification and zero new findings. Open findings fell from 221 to 194: 7 vulnerabilities, 0 bugs and 187 code smells remain. The new-code gate is green; this does not mean the backlog is clear.

v1.2.3

Choose a tag to compare

@beastyrabbit beastyrabbit released this 25 Sep 15:25
83862a1

Infinitune 1.2.3: crash leftovers of the silence trim are cleaned up

This release resolves the known issue listed for 1.2.2. A server crash during the silence trim could leave a hidden, full-size .trimmed-<timestamp>.mp3 copy of a song in its folder in the music library.

Song saving

  • Each save now removes both kinds of leftovers that a crash can strand in the song folder once they are older than 18 minutes: the save's private .audio-<uuid>.mp3 and the trim's .trimmed-<timestamp>.mp3. This also catches leftovers from earlier versions, which used the same trim file name.
  • Only these exact generated names are removed. Other files in the music library, including hidden ones, are left alone.

A test covers aged leftovers of both kinds, fresh files from a live save, and a similarly named file the save did not create. The test fails on 1.2.2.

Upgrade notes

  • No configuration or data changes. Leftovers are removed the next time a song is saved into the same folder. Folders that are never saved to again keep theirs.

Pull request: #57.

v1.2.2

Choose a tag to compare

@beastyrabbit beastyrabbit released this 25 Sep 14:57
35033e9

Infinitune 1.2.2: cancelled saves no longer overwrite songs

This release fixes the known issue from 1.2.0 and 1.2.1. A song worker that was cancelled while saving could overwrite the audio a replacement worker had already saved for the same song.

Song saving

  • The save now prepares the audio under a private name in the song folder. It moves the audio into place only after confirming that its worker is still active, and in the same step writes the lyrics, generation log, cover files and id link. A cancelled worker leaves the folder untouched, so the files and the database stay consistent.
  • The silence trim stops each ffmpeg pass after 2 minutes. A hung ffmpeg can no longer stall a song, and a timed-out trim keeps the untrimmed audio, as any trim failure already did.
  • If the server crashes during a save, the next save into the same folder removes the private audio file left behind once it is older than 18 minutes.

Tests cover each case against a temporary music folder: a worker cancelled during the trim, a normal save, a failed download, crash leftovers, and a timed-out trim. The tests for cancellation, crash leftovers and the trim timeout fail on 1.2.1.

Maintenance

  • GitHub Actions are updated: actions/checkout v7, the Docker login, Buildx, metadata and build-push actions v4 to v7, and the SonarQube scan 8.2.2. This release's image is the first one built with them.

Upgrade notes

  • No configuration or data changes. While a song is being saved, its folder briefly contains a hidden .audio-<id>.mp3 file.

Known issue

  • A crash during the second ffmpeg pass of the silence trim can leave a hidden .trimmed-*.mp3 file in the song folder. Earlier versions behave the same way.

Pull requests: #56 and #53.

v1.2.1

Choose a tag to compare

@beastyrabbit beastyrabbit released this 25 Sep 13:01
a22c14b

Infinitune 1.2.1: keyboard-operable oneshot sliders on Node 26

The seek and volume bars on the oneshot and reimagine pages now work with the keyboard, touch, and screen readers, and Infinitune runs on Node 26.

Real sliders for oneshot playback

  • The seek and volume bars were clickable areas: keyboard users could focus them but not move them, and screen readers announced them as buttons. Each bar is now a real slider with the same look.
  • Arrow keys, Page Up/Down, and Home/End seek or change the volume. Touch dragging works, and screen readers hear values such as "0:19 of 0:40" and "60%".
  • A click lands exactly where the bar was hit. Seeking is disabled until this song is the one playing, so clicking the bar no longer moves a different song.

Oneshot result with keyboard focus on the seek slider

Keyboard seeking and volume changes

Node 26

  • The container image now runs on Node 26 (node:26-slim), the newest release line, which becomes LTS on October 28, 2026. CI tests on Node 26 as well.
  • Node 25 and later no longer ship corepack. The image installs the pinned pnpm with npm, and CI uses pnpm/action-setup.

Development and maintenance

  • pnpm dev hydrates pages again. Since 1.2.0's dependency update, the app pinned an older TanStack Store than the router needs, and Vite's dev server served the router that older copy. Production builds were not affected.
  • Six unused player components, five icons that only they used, and the @dnd-kit packages are removed, about 3,600 lines in total.
  • The SonarQube scan skips Dependabot pull requests, which never receive the scanner token.

Oneshot result on mobile

Upgrade notes

  • The image base changes from node:22-slim to node:26-slim. The app still runs as node (uid 1000), and data and configuration stay compatible with 1.2.0.
  • Self-hosted CI runners need libatomic1 for Node 26. The CI workflow installs it when it is missing.
  • The known issue from 1.2.0 remains: a worker cancelled during a slow storage save can still overwrite its replacement's audio file.

Pull request: #55.