Repository navigation
Three small ones, none of which is a day's work #34
Closed
robert-dean
started this conversation in
Ideas
Replies: 2 comments
|
Status check, 2026-09-22 (main at 23b983e) None of the three is built: only |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Written: 2026-08-28, promoted out of comparable-stations's ranked
list, where they sat as entry 8 — "the small ones, in any order". They are here as one file rather
than three because what they have in common is the only thing worth saying about them together: each
is small, each is independent of the other two, and each has been costed against the real tree rather
than guessed at. Anything that grows past that should leave this file and get its own.
A second scrobble destination
Cheaper than it looks, and the reason is that most of it is already built for something else.
The
scrobblecapability,deadair.scrobble_queueand the send-after-commit design all exist. Onlyplugins/lastfmimplements the capability — andplugins/musicbrainzalready carries a ListenBrainzclient, its types, and its entry on the host's network allowlist, because enrichment needed them.
So the work is a manifest capability and a submit call, against a client that is already here and
already trusted.
The one rule: the two destinations must fail independently. A queue that drains to both and
retries the pair on one failure will double-submit to whichever succeeded, and a listening history is
exactly the kind of thing nobody notices is wrong until it is very wrong. Whether that is a row per
destination or a per-destination cursor on one row is the whole of the design question.
.plsand.m3uendpointsTwo static text routes naming the mount. Hardware players, car receivers and most desktop players
take a playlist file rather than a stream URL, and typing a URL into a car is not a thing anybody
does.
This was pointless while the mount was on the LAN and stopped being pointless when it went behind a
tunnel (listening-loop). That is the whole of why it is on the list: the
work did not change and the reason for it appeared.
Both files are a handful of lines built from
STREAM_KEYS.publicUrlandMOUNT_PATHS, the first ofwhich the console already edits and the second of which is fixed. They are public, so they name
the public URL and never the compose service name — the one way to get this wrong is to build them
from
icecastHost, which is the internal address and is right for Liquidsoap and wrong for everybodyelse.
An MCP surface
The other station serves one over HTTP off its own API, split into unauthenticated reads and admin
actions.
Here the contracts already generate a typed client, so the mechanical cost is low. What it actually
costs is a decision this tree has deferred once already: which verbs an outside agent may reach and
how it authenticates. That is service-actors's question wearing a different
hat — the station currently has one shared bridge secret and no actor kind for a non-human caller,
and an MCP surface is a second non-human caller with a much wider reach than Liquidsoap's.
So this one is not small until service-actors lands, and putting it in this file is arguably
wrong. It is here because that is where the ranked list left it, and because the correction is
worth recording: the mechanism is small and the authorization is not, and an MCP surface built before
the actor model would be a hole with a typed client in front of it.
A listener cap as a setting
stream/icecast.xml.tmplhardcodes<clients>100</clients>.STREAM_KEYShas no entry for it andstream.config.tssizes the queue and the burst from the bitrate but not the client count. Thefifth pass of comparable-stations called this the only thing both absent
and arguably wanted now that the mount is public behind a tunnel, and the seventh pass found it had
never been written down anywhere it would be built from. One
STREAM_KEYSentry and one templatesubstitution; the config watch already restarts Icecast when the rendered file changes, so nothing
else moves.
Moved from
docs/todo/small-wins.md. The file as it last stood: https://github.com/robert-dean/deadair/blob/71e431d45ce7b35a189c7d226832ec4a6247e9dc/docs/todo/small-wins.mdAll reactions