Skip to main content

Headphones

@magistr/headphonesv2026.08.19.1· 23d agoMODELS
01README

Headphones music-download automation API for swamp — manage artists, albums, and the wanted queue on a Headphones instance over its JSON API.

Model:

  • @magistr/headphones — artist CRUD (find/add/get/pause/resume/refresh/del), album operations (find/add/get/queue/unqueue), list views (wanted, snatched, upcoming, history), and system actions (force-search, force-process, version/update checks, logs, restart, update).

Bulk onboarding:

  • set-extras enables extra release types (EPs, singles, live, compilation, demo, …) for an artist via the web UI's getExtras form — the only surface Headphones exposes for it — then re-imports the discography from MusicBrainz.
  • onboard-artists is a single idempotent fan-out: for each MusicBrainz artist ID it adds the artist, enables extras, waits for the import to settle, and queues every not-yet-active release, leaving Wanted/Snatched/Downloaded ones untouched.

Includes an optional SSH-backed audit-library method that cross-checks the Headphones database (Status=Downloaded) against the music filesystem to report albums marked downloaded but absent from disk.

02Models1
@magistr/headphonesv2026.08.19.1extensions/models/headphones.ts
fn restart()
Restart Headphones
fn update()
Trigger Headphones application update

Resources

artists(infinite)— Artist listing
onboarding(infinite)— Result of onboarding artists: extras enabled and discographies queued
artist(infinite)— Single artist detail with albums
album(infinite)— Album detail with tracks
albums(infinite)— Album listing (wanted/upcoming/snatched)
history(infinite)— Download history
search(infinite)— Search results
version(infinite)— Version information
task(infinite)— Task/action result
logs(infinite)— Application logs
audit(infinite)— Library audit: albums marked Downloaded in headphones DB but absent from filesystem
03Previous Versions4
2026.08.01.1

2026.08.01.1

Fixes two HIGH latent bugs characterized (pinned, not fixed) by the wave-2b test backfill below, tracked and resolved via the local headphones-apikey-hardening issue-lifecycle model:

  • Credential leak (apikey-in-URL-query through an unwrapped fetch rejection): api() and webUi() called fetch() with no surrounding try/catch, so a network-layer rejection (DNS/TLS/reset, or the AbortSignal.timeout) threw a Deno error embedding the full request URL — which carries ?apikey=<KEY> on 27/29 methods — verbatim into the thrown message. A hostile/misconfigured server echoing the request URL in its error body leaked the same way through the !response.ok path. Added a pure redactSecrets(message) mapper (strips apikey=/api_key=<value>, case-insensitive, up to the next &/whitespace/quote/paren, replacing only the value with REDACTED) and wrapped both api()'s and webUi()'s fetch() calls in try/catch via a shared rethrowRedacted() helper, rethrowing redactSecrets(message) with diagnostics preserved through a REDACTED single-level cause — never the raw original error — so the secret cannot resurface via a default Error/cause-chain inspection (e.g. Deno's own console formatting, which recurses into .cause) either; routed both !response.ok throw messages through the same redactor. Strict no-op on messages without apikey=/api_key=, so the existing 429 - quota exceeded behavior is unchanged.
  • get-artist/get-album array non-unwrap: get-artist wrote artist: data.artist || data with no array unwrap, but the real Headphones wire returns artist as a single-element array (confirmed against rembo10/headphones's api.py _dic_from_query) — the same shape onboard-artists already unwraps via Array.isArray(data.artist) ? data.artist[0] : data.artist. Applied the identical unwrap to get-artist (preserving the || data whole-envelope fallback), and to get-album's album: data.album || data (same defect class, same _dic_from_query mechanism, same fix — a free-rider fixed alongside the two named HIGHs).
  • Bumped manifest.yaml and model.version to CalVer 2026.08.01.1.
  • Flipped the corresponding characterization pins across headphones_adversarial_test.ts (the two HONEST-GAP sentinel-propagation pins and the RESIDUAL reflected-body pin — all three now assert redaction, and the two sentinel-propagation tests walk the full .cause chain via a fullErrorChainText() helper to prove the redacted apikey never resurfaces through cause, not just .message), headphones_test.ts, headphones_methods_test.ts, and headphones_coverage_test.ts (the get-artist/get-album unwrap pins) to assert the corrected behavior. The GREEN 429 - quota exceeded pin and the artist/album-key-ABSENT whole-envelope-fallback pins stay green unchanged, as does the property suite (including the apiKey-sentinel-never-leaks invariant).
  • Out of scope, deferred (unchanged by this fix): the unqueue-albumonboard-artists Skipped-requeue clobber, audit-library's unvalidated maxDepth/musicDir/dbPath trusted-config-boundary gaps, and apiKey's missing .meta({ sensitive: true }) annotation — all still tracked by the local headphones-apikey-hardening issue-lifecycle model.
2026.07.27.1

Modified 1 models

2026.07.16.2

Release 2026.07.16.2 — align model versions with manifests

Maintenance release across the @magistr extensions. For most packages this carries no functional change: the only edit is the model's version: field, brought back in line with its manifest version so the published model type version and the package version no longer drift.

Functional changes in this release are limited to:

  • anime-cron: normalizeTitle now strips a ": subtitle" suffix and a trailing parenthesized year before comparison, fixing dedup false-misses where the torrent title carries a subtitle or year that the AniList romaji does not.

  • arckit: first publish. Standalone ArcKit port — a 12-phase architecture governance state machine with 65 bundled templates, driven by a bundled skill.

Also tracks three extensions (kaiten, observability-agent, music-library) that previously existed only as untracked working-tree directories, recovered from stashes.

Added 1, removed 1 models

2026.05.25.1

Merge pull request #5 from umag/extensions/jscad-stl-pair

extensions: add 15 more @magistr extensions + auto-discover CI

04Stats
A
100 / 100
Downloads
1
Archive size
18.8 KB
  • Has README or module doc2/2earned
  • README has a code example1/1earned
  • README is substantive1/1earned
  • Most symbols documented1/1earned
  • No slow types (deprecated)1/1earned
  • Dependencies pass trust audit2/2earned
  • Has description1/1earned
  • Platform support declared (or universal)2/2earned
  • License declared1/1earned
  • Verified public repository2/2earned
05Platforms
06Labels