writing / 2026 / october
October 2026
Bosun v0.7.0 and v0.8.0, Nerve Media's station software, final year coursework, and this site
2026-10-31 / 5 min read / bosun, nerve-media
`,;-,''.
';-:+!*==~~-~-;,``.
,!l+~,,`''''`,:+lilcc:
.~;`+o~`''''`--;==;;;`'``-:.'' .'.
'+c=~K~,.,-`:~--;,``... ',,`=+iiiKXXKbK@@`
.;i0o,:Xl. -+,-:``.'`:;;*!lkX@Ob!, K00@libX@=
.;kdi* 'b+ ;~`:, ';:;:,;~c!+-:' -WOOi~bOX@Wx0@!
.cd!cl; '=l -~.`. ';:,*:+~' lK@!!Xo@KWMMM@b
=WO`:i;`'l; ,~`+`.,;';*i--;'.'``'`:,``~*k@McbboMX@@@M
:lkk-:o;*'~= ' *.-`':. ~-. .':;++X@Xbbl!lOiMX=OOx
:l*ci.;k+,';`' ,:., :. . .;i!00ol0Wc.:
,*i+`,O~ l!= . '` -, =x ~cxxi*`
.,~ll!!iii!=++!!lci+cili-,`,Ki;;d0di*'.; '. d@l '
.-ib0@@@@M@@@WM0K00MM@0ddXXbddxX@0KMdc@KOdkbMWXOx*x@XklokkdddbOo=,.
.+d@@@@@WbkbbOkokbdbOKXOi+xXbbOOxOMOxkd=+0boxlibbkkko+!KKokOdddKKOXXKOxo++=`,,.
-kM@@M0MOokdOOklkKOxdOKXi-c0bkdbc!lXXxccl~l0koli+!kxilll++kx!!cli!lcccccxbXOXXKKObc+:'.
.*0@@@WX0XllbXXdioX0dicObbi;d@o!ddol*bOoo!ii~xKxcci!*xxliiii!+oo**ili*+iiii!*icclllcxdOOOdoi=.
+@@@WXXbXx*kKXOo*d0XcioOXx*:bMxcxOxc*!Xoil!!!=oXocli!!cxli*!ii*+co!!!i!!*!lii!!*ici!***iclokdbk*,.
:X@@WbbbOb!iXKObl+X0dl!xbdx!:dWxolxxli+cbocll!*=oXxcll!*loll**ii!++coii!!i!!il!!!*+!li!!!+!l!*!lxkkdo;
i@@@0xbbOd*xObOkl+KXkc*lXkll;iMxllooci!*oboclii*=obxclli*iocc!!lii*=!oci!!!!!!*li!!!+*ii!!*=*li*!*!cokdc~
.b@@M0oXOdx~OOdXxl*XKooicbbl!=~0dcicxl!c!!kdllil!*+ldkiccl!!oll!*!!!!*+lcl!!!iii*!ii!!!+*li**!=+ii!**+!!lkkc=
,M@M@Xx0Xoc=O0bXxl*O0xxcldkcl*-dXociocill!*kocilli*+lbxcllii!lli!i!!ii!+!cli!*!!!i!!iiii!+*ll***+=il!*!+*!!lxdl`
=@@W@OcWXoc~bMdXoc!kMxollckxii~!Koollclcli*!kxillii*+lbociillilllli!!iii++ilii!!!!ii!!iiii*=!li**!++il**!++i!*cdo=
=@M0@0iM0kc-c@dXxoiiMkci*lxdl*+=dkccccllli!+lkcill!!!*lxcll!iiiiciii!!iii!*!i!iiii!ll!!!!li!*+!li*!**=il***++i*=ldx~
@@@@Mo0@kl=+@XKdol+OKli!lodoi*+lbdollclli!**oklliii!i!*coci!ii!iii!!i!!!ii!*iiilil!!ii!!!iiii*+ii!!!!==!i**!++i*=iko*
0@@@lO@bi*-K@Wblc+o@xliiccxll++dOciiollil!*!xxlliiiii*+lxliiii!ii!!i!!*iii*+iiiiiiiiii!!!!!ll!++i!!ii*+=ii**!+=!*+*kxi.
'@@@bd@Oci;i@@Xloi+Wbc!!occc!*~*Okl!loiilc!+ixcliii!ii**loliiii!ii!!!iiiiii!!*!!iiiliiiiii*!icl!++iil!**==i!**!++!*=!xxi.
.0@@Md@Xxk=:0@Moxc=xMcl!lklcl!!=cXoiillcici**!xllli!!!i!!lciii!i!!ii!!i!i!iii*!!!iiiliiiii!!*iili!=*i!l!*+~*l*+*!=+**+!ccl'
k@@@dWKcbl,i@@Ooo!~0dci!cxcil!!+kOol*icllli*=ixllii!i!i!*illiiiii!ii!!i!!i!il!!!iiiiiii!ii!i*i!ill+~iii!**=~!i**!!~+*++!col
i@@@kx@kcd+:0@Mkcl=!0xlcico!lli+!bdo!!lolll!*+lxlii!!iii*+iclc!i!i!!l!!ii!iiili!!!iiii!ii!iii!*llll!~+l!*!**=+i****+=+*+**coi
~@@@0!@0ckx:i@@Xocl~o0xiciciicl!=lbkl!lcclii!!+lxiii!iii!!*!cllii*i!!ii!i!!li!ii!!!iiiiiiiiiiii=*lilo=~li*i!*+=!!!+*!==!**+!ox-
K@@@lo@ocd!-0@Mbol*-X0ci!i!iooi*+cdxli!ccli!!*+ooili**i!ii*illiii!!ii!i!!i!*!i!li!!!!!ill!i!iil*+iiio*~!l!!i**=+i*+*!*=***=+ik!:
*@MMO*WMxko~!@@Oxci=+Wbl!l!lcxl!+=xkoii!lliii!*+ooiii!*!!l!*!liiiii!!!ii!!ii!!i!li*!!*!iiliiili!!=*icl!~*ci!!!*=~!!***!==+++=+cxc`
*OO@@MKko@Xckl-b@Wkxxi-iWxlll*ilki!+=dboi!cliii!!++xoiiii!!i*!*!ci!!!ii!!ii!*!ii**i!i!!*!!iliiii!il!*=!cll==cl!*!*+=+l**+*+~*++++*ooi
~@@@XM0Kxd@dxc=+M@Oxcc!~xXccl!*!ox!!==dbc*!cliill!=*xlll!!!!!!i*!ll!i!!iii!i!!ili!!!!i!*!*!ililll!lcii*+lli=~ll!!!**+=!!*+**~+*=+=+iki`
.@@@dO0OOoOKooi~cWWklcl!=ddlli!!ikcii++Oko!!lilill!+*olil*!!*!i!!!lc!i!*i!i!!*!ici!i!il+!!*!lilll!!iill*=ci!*=!c!*!**==*!*+!i==!+=+*!xc~
*@@@lW0Xk!Xdxli~xMMxoxo++dxolililoiil+ikdcilliiiii!**ccli!!i*!ii*!lli!l!iil!i+!!!l!!!ii*!!***!!!il!i!li*+i!!!=+ci****+~*i*+*!=-**=+++!kl'
d@@dxMObx!Obcc*=kWdcooi+ikkclilicciii~lkx*clliilll!=+llc!ii!!iii!*ooi*i!!!i!!*!!!!!*!l!**!*+*!!!*ii!!!ii*+i!*==!!**!**~+i*++!*-+*++=+*ol,
`W@@lb0kkklWboc++b0cccl!*ldolliiililii~loi!clillccc!+=lcooli+*!!!l*cxi!!!*ii*+*!!!!!!**!****!!!!i*!i!!*il*=!i*+=*!*!!+*~=i+++!*~=!+++=+lx*.
;M@Mld0OkilOool+ibboocl!ixdllliiillllc=!cillli!loxk!~+llccci++!!*!+ix!!!!!!!i!*!ii!*!i*!!*****!**!!*!*!!i!+!i!*~*i*****=~i*++*!~~*+*+=+!xi,
,K@O+dkckoobcol+ibXxoc!i!xoill!iicc!lc=!ociil!*oxox!-+oiocci!*i*!!+!ol!!!*+!!!**iii!*!*!*=+*+***!!!*i*******!**=+!!****=-i!++**=-**++=+*cc*
,0@b*xxoXcoboco*cObcxl!!ili!ciicicliil=*icloo**illx!~+cioxl!*!!***=!oi!!*!*!!!****!*i!*!+~+********!*!*!****i!*=~!i!*+*=-!!++++=-!*+==*!li~
,W@d+dxxx*okcol+cdxiii!il!!ii*il!i!ill=*ilixciiiilo*~*iioo!*++!*!*+!ci!!!!*!!i!*!!!!*****++****i!*!!*!*!!++*ii*+=******=~*!++=*~-=*===++lli.
,W@o=WdOo*ooooi=odi!!i*!o*!!!+*liiiiol=*!!ill!iiiili=*!!lcl+++!!!!**li!!i!i!!!*+**!!*+!**++****!ii**!!**+**!c!*+=+i****+~*i++=*+~=*+~+!+ico'
,W@o*xcc**cocl*=oxi!!i!ic*!!!!!ci!!ioi=!*!icc!iiiiic*+!iccl+*!!!!**+!ii*!!!!*****+*!!i*+*+******!i**!!****+i!+*+~+i!***+-+i++=*+~=++=+++il;
,WWo!l*l!=ooii!+loi!*!*io*!!!**il*!co!+**iilll!i!i!!=+*!lll**!!!*+++!!l**!!*!****!*!*ii*!++!!*******!**!**+!****~+i!+*++-!i*+=++~=!++++*ll;
,00o*klli*clii!+iclc!!*io*!!***!!!!ll*=**!ici!iliii!+*!!icc**!!i****!!i!!!!*=!!**!*!**i!!+=*!************+*!!*++=+!+++*=-*!++~+=~=*=**++il*
,MKo!lii!i!iii!+ililli*cc*i!!!!!*!*lc!+**!lli!*iilli+*!!l!l!!**!***+ili*!!!**!!****!*!!**+=+**!*!*****++*=**+**+=~*++!++~+**+~==-!++++*+ill
;0Oc!lli!!!ciii+il!ii!*ll*!!!!!!!*!il!=*!!*liiiill!!=+i*li!!***!*+*+ii!****!*!i*=+!+*!*!*+=+!*****!*+*++*+!+!**=~=****=+~++*+-==-!++=+=+l+:
~Wdc*il*i!iol!!*ilii***!!!!!!!*!i!*ill=+***icicliii**+*i!!!!**!!***+!i!+!!!**!*****+**+!**+=**!!*+!*+*+++**+!**==~!!*!+=~**++~==~+===+=+li`
'bXo!il!i!!o!!!+!l!i!!!!***!!*!!ii*!cc+++*!!li!*!i!!+=!!!lc!i!!i**!+!!l*+i!*+!*+*+*****++*=+*!i*+***+**++***!*++~+!*+==+~+*===*=~+++=++*i!.
kWxi!c!i!!l!!!+*iii!!!*!**!!!*iii!!!!+~+*!i!!!*!!!*==!*!l!!**!**+*=!il!=!***********+*+*+~+!**+=+****+++***!*=+~+++++++~=+==++=~++==+=!l!
xWkl*lii**ii!!**il!!!!*i****!**!!*!!**=*!!!!illi!!***!!i!*!*+***+*=i!ii**!*!i****+***++*+=+*+*+**=++++=+*++*+==~*!*+**~~=+=~=+~+++=++=ll*
=WOl+il!!*i!!!!+*i!i!!*!*+!!***!**!i!*=+*!i!*!!!!l!*++i!**!*+***+*+***i****!!****!++***++=+++++**++***++***+*+=~+!+=++~~=*~=+=~+++==+*ci`
-KXc*lc!i!i!i!!++l!!i!*****!!!!!!*!!!!++!!!!*!!!*!!+=+!*!**!!!*+++=**!!*+*!***++***+=*++==+!!+=++**!**++*!**++~=***=+===++==+=+++===+ll+
.Obxi!l!!!!l!!!++il!!!*!!**!!!!!**+****+!!!*!**!*****+!!!!*!***+*++*!!!!******+***++++++===*!!+=+*+**++++****+~=***~+~==**==+~+++===*c!:
xXoc!i!i!*ii!!!+*l!!!!!!+*!!!!!**+**+==!!!****!*****+*!!i!!****+++*!******+++!**++**+++*=+++*+++++*+**++!*+*===**+++=~+*++++~+*+==+lci
~Wdx!i!l!+!l!!*+*l!!i!!*+*!!!!!*!*!!*=~!!*!*+*!***++**!!!*!!*!!!+=*!*!!!+*******+*!**+*+++!*++++++*++++*++*+==+++=+=~~*!++==~++==+!cx-
.O0klcl!i**l!!!*+!i!!!*!**!!!!!!*!!!*+~*!*!!*!******+*!!**!!+***+=**i!!**+!***+=!*++*+++==!++*++*!*+=++!*+*===**==+=~~!+*=+==+=+**cxl
=0bkio!i!+il!!*+*i!i!*****!!**!!!i!!+=+**!!!!!+*****+****!!++**++*!i**!*!**++*+**++!*+++=+++=++=++++=*!=+*===*+=+++=~+=+++=++*+!iko'
c0Xlcl*l++lii+++iiii**!*!!****!*****++*!!!!*!******+*******+***=*!!****!+*****++=*!+**=+!*=+++==++==***++=~+!*++++==+=+*~=++!+!ox;
,K0bcx*!i*il!**+!l!!!!**!!******!!!*+=!*!!!***!!**+++**!i*+****++*!****++*!++*+*+++++*~+!+==+=++++~**+**==~*++++++-+++*+~++!+!ld!
*WWxkc*ii!li!!+*ii!!*!*!i***!!*!!**=~!!**+!!**!*****!*!i++*+*+=+***!****+**+****+++*+-++*=+==++++++!**+++~===+++~-+=**-~+!*+ixo'
kW0xx*!l!!l!!*~il!i!*+!i!****+!*+*==*i***++*******+*!*!+!i+**++***!+******!!**+++*+=~+++=++*+=*++**+++==~===+++-===!=~+=!+!od~
.kMKxc!ol=ic**-+c!i!!*+i!*******+*+~+!**!*!*****+=**!!*!i+*+++=!*!+**+!+***!+++++++==++++=*+==+**===+=+-~===+=+~+===~++**ild!
oMOx!lx!+ci*+~ll!l!+=ii*!*****+**~~!!!***+**+*+++**!**i*+!+==i!!+****++++===+=+*+~=*+=*=*==+==++++*+=-+==*++~~+==~==!**cxl
'XMbx*ix**o**~*o!l!*++i*********+~~*i!!*+***+*++***!!+*+=*+++!****+++!++=++=++++=~+!+=+==~=*+++~+===-==~+++=-+++~~=**+ox!
:bMOo=lc+ll+=-ccii!*+!***++***+++-=i*!*+****!++****!+*++++==!+*++++++++==+=*+=+~~*++==+==*++=~~===~~++=+==~~=++~=**+cxi
.oMXo!li*ci+~=kll!**+!!++++***++=-*****+*+***+*+*!!+***++++i+++*++++*++=++*+++~=+=====~++~~==+==~=*+=+==~+*+=-=*!!ok!
c0Xxcci+!!+-ixl!*!+=!*+*+=***==-+!***=**++++++*!**+*!+=++**++++++++++=+++=+~-*++++=~=+=+===~=~-==+==~-~+++;~=!cl!-
,oXkxki~ii+;ioli*+~=!+++++**===~!!+*++*+++*+=*+*++**++==+*+++++*+=+==+=+==~~+~=++===+=+===~~-===*=~~~==*~~+icc!.
~kdbdl=*x=:*ooi**=+!!+*+++!++~=!*+++*+++++++++++*++*==++++=++++=+==+~==~~==~==+==+===~~~=-=+=++==~=+*~~*cc*~
.!ddXx=+c=;+oo**+-=!++++++++=-!!*+=*+++=+=~*++=++==~=+++++==+++=+====+=~-~~~=====~==~==-~+*++=+===+-~ic!-.
:cxKX!*i=;~oo!*=~+!*+++~++=~~!++===++=~~~***+++==~++++===++**==+*+*==--~~===~=~~~==+-~++++~~=~==~+li*:
`~xXkll+--loi+=-+!=++~====;=!===+=====-+*+~*===-=++=+==*=======+==~-~~==~~~=~~=~=-~*====~=~~=+!ii;
';lbkol=;!oi+--~*+~=====-:**=~===++~-=*===+=~-=++=*==+=====~~===-;~-~~~--=~~==~~++==+~~~=+*!l*'
`~ixkc+*ll!~;~*+~~=+==;;*+~~+===-~~+==~==~-~=+~=~=~~~~~==~=~=:-~~~~~~~~~++-~====~=++***!-'
';*!!*+ic*=-==~-===-:;+=~~===~--=====~~;-===~~~~-~-==+~~=;:-~--~=~==+!;-+++++**=+~;`
'li*iil+~~~~----,`:~==+=~---==~=-;:-+~~--~---~=--~~;:---~~-~=+!*++i!+=~--,..
`,. .`---;--;--:,,;~=+==--=+~--;:-=~--;---;~~-~-:;+++===+!!+~;:`'.
`''''''. .''``'',;;--,;~~~-;~=~===~-:~=~:,:;:,'
.. .. '````' ... .'.
Bosun v0.7.0 went out on the 6th.1 It was aimed at filling gaps I'd written down last month and while working on things this month: app-wide middleware, panic recovery, CORS and graceful shutdown, typed routes that belong to each app instead of being shared globally, request validation with proper structured errors, and bosun gen registry, which writes the package registration code so I don't have to. It also has CI now, with the race detector on and integration tests that run against real message brokers instead of mocks.
v0.7.0 didn't stay finished for long. Using it every day on Nerve Center, the station manager for Nerve Media, showed up plenty of its rough edges. The main one was that some handlers couldn't return the errors we actually wanted the client to see. So I did a full audit of v0.7.0, and v0.8.0 went out on the 26th with 51 issues closed. Most of it is hardening: security holes, panics, lost or duplicated messages, and specs and generated clients that didn't match the server. Typed handlers can now set their own status codes, headers and cookies, events retry with backoff and a dead letter queue instead of forever, there's a testing package, and the OpenAPI spec is a lot richer. A lot of defaults now fail safe too, so webhooks without a verifier are rejected and request bodies are capped, which is why it comes with an upgrade guide.
While putting v0.8.0 together, I came across a video by Arjay McCandless where he was testing different languages against a mock social media platform with k6. That led me to want to do a proper test with k6 for 1.0 and find out where Bosun falls over before it should in theory, and why.
Most of my month, though, went on Nerve Media. With the site published, the station's software was now split into four pieces: Nerve Center (the station manager, Go on Bosun plus Next.js), Nerve Public (the website), Nerve Track (which tells the site what song is on air) and Nerve Waves (which records the shows and tells the public site where to stream past recordings from).
Nerve Center gained LDAP sign-in, but it isn't switched on yet. I wrote it before we'd set up AD on the network, and when we did, we changed how it was structured, so I need to rework it a bit. It also gained listener records from Icecast for the music licence returns, a migration from the old station manager and a new user import. Shows also no longer have a single lead host, so anyone presenting a show can edit its details or cancel it. The committee running the radio asked for that when we showed them the new system, and they corrected what I'd assumed about how shows worked.
The user import also gave me this month's least fun job. Admins and committee members had been changing users in the old system without telling us, and when the import ran, records ended up attached to the wrong accounts. We fixed the affected users and added checks so a change like that can't move records again.
The other two got smaller but nice changes. Nerve Track used to ask the playout system's API what was playing every five seconds. Now it reads the now-playing file the playout system writes on every change, so it needs no network access or API key on the playout PC. Nerve Waves now notices when a show is cancelled while it's recording, stops, and throws the audio away. I also spent a day bringing the 27 pages of Nerve Center docs back in line with the code, which is the kind of job that never feels urgent until somebody else has to take over.
Outside of projects, uni has properly started, and my final year units are Digital Forensics, Human Computer Interaction and Systems Development.
The Systems Development coursework is a scheduling app: hosts publish booking pages and their working hours, people book a slot without making an account and confirm it by email, and confirmed bookings turn into Google Calendar events. I got the unit leader to agree to a Go backend, with MySQL and Valkey alongside it. It's due on 21 January, and while there's no code yet, the auth pages are designed:




Then there's this site, which is new. It replaces my old, kinda crappy one from second year, which I kept putting off updating or writing posts for. Now I write everything in Obsidian, and a small Go build turns the notes into pages, renders the Mermaid diagrams at build time and generates the ASCII art from my photos.
I wanted a note to look the same in the vault as it does here, so I ended up writing three Obsidian plugins along the way: Code References, which links text to lines of a code block in both places, Projects System, and Figure Layouts, which draws image galleries like the one above while I'm writing. Code References 1.0.0 and 1.0.1 went out on the 15th.
Next month I want to start writing the code for the coursework, start on Bosun 1.0 with the k6 benchmarks and editor tooling, and finish planning a couple of new projects I'll say more about once they're real. That's it for October, see you in November!