writing / 2026 / september
September 2026
BluePortal moves from Fiber to Bosun and gets a full security audit, plus Bosun v0.6.0 and Gantry v0.5.0
2026-09-30 / 5 min read / blueportal, bosun, gantry
.`
' .` .
.:.
' ' ..
``'' .. '`..
.``,:`'``'',` .'
.',`,::,'' '` ..
`,```,,....``''. ..'` ..
...,,'.`. ..,,``..`,`,`,. ...,. '.
.`.'. ''.`. .'::''. '`,''`` . .`;` ....
.' . '. ``:` '`. ..;, .'''.'``,' ..,;;,' ..
. `. ',`..'`. ',`'`,.';. ''.'`',```` ,;``,'.. .'.
:.'::;'`` . .'`=;`,.`: '`'=-:' .`, '' .'`' . '.
, .= ,;:~,``..=:'-+-,'``''`;~!-,.,.'. ' . . '.. ','.
. + =~,--:-',:``;-`,:;-``,`.`+!i:`'``'' ''.''. .'..'``,''.
`i,-~-;,`;;:::;''`:!o,,;;,,~!,' .''' .`:::::`',,```'.'''''..
'' ++:=~-;-++=---~'.`:;l~`+='~~``':,`' '`;~~=;,;:+=::`'...'.
.,,-l~*+=-!*==-*;,;:.,;:=-;=+,~;`.'!;'. .`,,--;~;;-;**-,. .'.
,;~ll-ii*~+~+-=!~:,::---!=~+=;;'',`',' .,`'`,``::=ll=;` ...''.
.~*=ii=il!++++-!-;,`,:--;lo!i!*;:~!=;-' '`'.'''',:~io-::;l:.'. ......
:l!:=i!cci**l=*+~`;;:;;;;~ooldOl-~+=:``''`.'`''';+*=:```'~`'. .```,'''..
`+c=~*locll!li=c*--=-;-;-~;cxikOo++*~`,:,.'``''':-:~+;-,'.`:,. '`,,;-=,`''..
-l!~++loclcoc*xo~;~;,~-~~*~kbdOOkllko*;;,''',,:+=-;+=;+~;=*~,. .:-``,:,`,,`.
,!i!~!+lxxcoocox+-;-:;+++=*!cKbOWbocbOdi,`:;:;=;=:;=*~-+!!oo+:,;--:`,`'......
.~*c!*iiokdooicl!--;:~*++*l!**dkxKXddoxl=;;+*ii;::~~++--+lkkk*;=~;,,:``.
,=io*!iloxddoo*-~;:`;+--*li!iOkocckb0Ool+-~ioc!-~~-~=~-=!lXKKx*~,`,:`'.
.~+cc*icckdkxo!-~~-;;~;;-!!+ioOddxldKK0Xoi*+lc!~==;:~~==!cxd0MOl=:::'.
.:!ixlllixOkxll=;*~;~+;-;=*!libxbWWbOObdxocici**+~~;;=+*!lccxXdc=:-;`'
'.:=*icllicOdbxii~=*:+!==~=+oliiWbxKWX0KXXObdoc****===*!!+!*+=*+~-;-+=+=. .
.``=~*cooiobbbXo**~=~+l*+=**-~i=!OXkOK0MMMKKKOkcxcco!+il!*=~;;;;,`,:-~~!+'..,,.
`,`-~lxoocbbOXboi!++il*=*i!+:,~xbXKdW0KKWKWWOddkbdkbxoci!+-,`--``''',,,--,,,`
. .`,`-+ccloxOOObkoc!!loi=+il!!=:-ckK@X@@M0MW0KOObkbbxbMXk!=-,';-,'.... .';~:,.
. `:,:*lcoxkXdOkckl!iiil!llllll*-=*oW@@@@M0XdOKObdxkXKXki-::``:`'... ;;--:'
. ',`:!!ddbOOdOxoc!i!iilcxclccci*lxob0@@@@KWWW0XddkKWKbl+~;;;;,''.. .!x=:, ,'
. ,,::*cOkKbddOkociilccoxoocccocckkodKK@@WKW@@MMOOdKKObxl!+=~-;``''`iO+;''.. `;,
.' -;;-*xOdboxkbkxl!lclocooocllxkOdccdXX@@@WXO@@@MXdcxkObdli!!+;==~;`=x;' .,;::'
'' :,:~!kXXbokdbdcicclilxxlcccloOOkxxOKM@@@@KOOX@@Mdkkddxlli**ioK+;;'.,' :~:-:.
.'..'.. ,:;~ixXMbxobXkolccoccllilokxxOdkkkdOXXOkoxoodM@0dkdOdocc!*!odo;`:,'..--:*:
.``,`'..:-!lob@XkxbXxkol!ccllllcxdkdO0KdbXbdkcl!illx0@WK0Xdkbkllicc+-;;:,``;` .;'
',::,`'. -ioxK@0bbbxkXkoccclcoxxkdbOOWWbOXbdxxociiobbOM@@MOkbOkkxc!!i**~::-`
' .,;,,,,,':lob@@0k0dodOxdxoklcxxdddO0W00bkkkdddxloXbxxkdbbdkkxoli!==++=i~:`'
.,;,,,,:;;!x0@WKOMxokokxkdocxxkddbOObbdkdoxkkOdkbdcooxocodbxcobo+++-,''''
,-;;:,:~~+x@MWMMWdddddddkxxkbkkbbObbddddddkbXOOxkkxkkkkWbooxOO!;;;,''.,'
'.'. `---;--+*+lM@M@@0kbdbbddbbddbddkxkkkkdOKWXXM@W0W0W0OXX00ccoxo*=-::,`''''
..'. . :ko-~=;. .:~==!ioooc0@M@MOdbbXXbbOOOObbdkkxxkdO0W@W0W@@@@@@@MW0Xdooc!*+-:,,``.. ..
.... .' ..`;-~~,'.. `:=+~=+~;. ';~+lcoxkx0@@@0OdOX0KObOXXXbbbdddddbXW@@@MMMW@@M@@@@0OXdci+~-:,,``'```,=:`'
. ..`':-~ili*=~-:`,;=~~+=~cl-,``'.. ';:~!cooxkx0@@MXbbXK0X00KX0KOObdkdddbbbXKW@@@@@@M@MM@0XOo!+~--::,`,``,-=*:.
.` .,;-~~;```'';~~;;=!li!ldx+=~+;;:;~**=ixxxxkkK@WWObXOKKXXWW0W0XOXKK0XbbbbbbO0@@@@@W0KM@0Kdl!~---;;::;;;:::,' ,
'':' . .',`''''''`;~=~=icxxxbxi!!*+!*+*!lllxkkkkdd@0K0KOXOOObOM@WMW0W@@@@MM0KKXKW@@@@@@KW@WXdxol*+=~-;::,,,:,`'. .
. .,; . ...''',;-~*llcci===***iiiooxxxkkkdbdW@0X00MKXX0W@@@@@@@@@@@@M0KXKKW@@@@@@@MWKOxxcii!+=~--:`'.. .'.
. ' ;;` .```:;=-::;=+****!liicooxxkkkxkOKKM@@MKW@@00MM@@@MM@@@@@@@0KKXOXXK@@@@@@0OOkcl!+*=~~-:,`'... .''
. . `:,:!'.. .'.,::-++=+iillllcccokoxkkdbbbdkxdXW@@@@00@@@WW@@@MW0WM@MMMWWMKKObXW@@@@@Wbkxoc!=-~-;:,'' ...... .,.
. .,;:;:;!!*o*, .`````;~~*i!lxdObdddbOdbbKKKWW0KXKWKdloO0M@@@@@@@@@@@@MWWWWWM0XM@0M000KMK@@@@Xdkocil*=-;;:,''. .....
``'. .`,,,,:;*lili++c-::,`'`:~~=*loddkxkkdbdKWM@@@@MWWWM@@WkcxkbM@@@@@@@@@@@@M0MWWMMM@@M@KKWMWWWKKblocli!*=;,,,``' .. ..
. ... .:;`',:,=*,;==!c!=~~;;;:--;--=!icccooxkbXW@MMMMMW@@@@WK0Oxlkb0WK00W@@@@@@MMWMM@@@@@@MX0WKOXOddxol!l!=~=:,,,``'.'.....
. '''`'. :-;'`;-~!,;:;!-;-~-~;::,;:;=++!lcoooxkkOKWM0000W@@@@M0MW0OokkdxobWMM@@@@@M@@@@@MMM@@KXXXOOdkooxxli!*+~~-:,,```,'
.. ..'''' ..'``'''`--;,;,:,.':'',::;:,:::;:;--~+!illooookkbX0KKX00M@@@WM@@WKKKKKWdxlcookKM@@@@@@M0OdOKXdkkkkxooxddkcii!!++**!!+-;` .' '`'.
````'''''': `' .. .,:.. .`''``,:::;-~-~++!ilcoxocxxkdbOK0W0WW@@@WWMWMMMWMMMWMbl!===cKM@@MWKKKXbbkkxccllxkbbbxi++==+*icoc!--~;:`'.`''`,;;:'
`,;:,,```'.. ...'`,`.`:~*!!lllilcccooxxkddbW@M0MWWM@@WMM@@@@MM@@@KOc!lccokdXWM@MMM0XObdkkxkddbdkci+++=~=+**=-~+~:,'. .'```,:.
`:;;:,,`''., .'`'``,~+i!llcclcllcckdxkddbOKMK0WMWM@@@MMWM@@@@@MWKKdbkbbkol*!cdKWM@@@W00XOdkxkxcli!!*=~~~~=~-~~+=-' ''`,'. ..
'-~;:,`````.. .'`,,:;=+*ckklci!kddkoxdoxbOKK0XK00MW@@@@WW0MMMM0KXbKOW0bbdkoo!~--=*~*llcxkOK0WMWKObxci*=---;-;:-+lbc+-..' ',,-+=;`
';:,,,;`,'. '`,,;;~*!ibboccccdbxkkxokbOXXKK0WMWMM@@M0WWMM0XXKKKWbK0bbdkxoi*~-,'..',;-:;-~+!lodOdci*===~~~--=!ic+~~'. .,;-;:,
...'''=,,`. '`,=ii*xxxXbdooocd0dxkxookXK0W0WM@@@WM@@M0K0KKK000WM0W0ddkxocii+-,'.. ' '`'. ,:``'``,;-~++==-;:``. .```.
.`:,' ` .''`:-=lkdkkXWboxolcOXbxdbckxdXK0WM@@@@@@MMM0KKK000WWWWW@@kkxocli!*~,. .`~:`:`'. .. .
',;:,`.. , .`,,~~~=iOMMKM@klkocb0dxooolooxbbbXW@@@@@@@MXOKXKK000000WM@bcocli*++~:` .,''
';~-~:,`'. `=~=li!**cdX@@@XkcxO0dclccocoxkxdbdO0M@W@MW0XXXX0KKXKKK00M@Wli!!*===~:` '.
.,-+i*~;``,!' .,;=ioxxlixcodbX0@@0XWdkolclcooxxxxxxbkOKMM@@W0K000KKKKKXXKX0M@x**=--~~;,`. .
':-=i*=~-;=''... ..':-=icoxX@MxdkkbdbdXK@@Xcooclcoooocoookdxdb0MMWM@@MWW0KX0KOObXKKW0==-:-::,``.
..`-*!*~;:````:-;;-!!!xo!ccOMXXWMWobbd0@XccllodkOkcccoxoXbxdbOWKXXKWWWXXOOXXXbdOWX0Mo;-;:````'.
.,:~+*=~-::,``--::illbkllodbdbK@@dxXX@WxlicxxddKOoxxdbdkdb0WWKKK00KKXOObdkd0bbKMXKWki;'..''`'. ,`
.',;:,,,`''``'.,*iioo*iococxdXddb0MWdi!loxkkxbkxxxdkddO000KXXXXKXbbdddkkkbOOKKddWk!!, .'`''
. .'' `;=!oi*=coko***cdbb@WclbxlxkddkxxddOdkdkX0XXXK0KbkkkdxxxkxxkddkxkxbOc=* ....
..:~-~*c~-+lkb*,;~+cxdW@Od0@0bdkdbXkbM@WK@KO000XKKXKbbbxkoooxkkxxdooxcdXo++' ..
.':kc-=~::+lokd+`:=*loO0MWKOK@@@0MW0WMM@KW@MKWWKObbkdcooocoiiickocdcclob0x~=,
.';lxc!;:;=!lci**::=ilxb0MMW0K0W@@WM@MW@WKOXM0@0bkxocilxiiclli!!lxbc!c!xcbX!*'
,-*xdx!;~!*+!!==+`:*okOKW@@@M@@M@@M@@@0dxxoxbodkccccciiii!*+=*!iixkl*+liixb!=`
~!ccxi=+==*=iii~`,idoxO0MW00KKW@@@MWMMdxlcccko*llilli!*i!+~~-=!*icki~+i!*ok+=;
. ' .`-*c=!l*-;~*!i+=i=+iccbdb0KOKK0MWW0WWMKObllolxd*i*i!+icil*==*!*++!lol!!!+*oo~~-'
=di' `:-~+*lcc=`;+=~===--=*!xOdbKWXXM@WOObWWXKbOxlbl*xi*++=+!kxoxxxol++*lcOcll=*ixo;;-:
`-i+' .''`:=ii!!+-;;:-~*+~~~=!ckdkbbOW@@@0OXKOXdbKXXxi!!l!~~-~*cl*!lcci+=!lckd***+ioxl--:;
.. . ;=*++==;;-~===~--~-=!coxkK00W@@@WbObokk!xbXbc**i*--~~!i**!i*!+-~!iobo!=*+ll!!--;- '
. .*i!l+-=+=~++~~;;;;-*ioxdbO00XW@@Xcci!ll=oxkl!!*+~;-~+i*+****+=++!cbbd!~==!ii*---=
.. ;,=!iklii*~-;-;;:,;~*!lookdXWKOO@0oi*=*!==!!==+*+~-;;=ii+!!+*!+=*!ldXxi=;-+*!i+-:~+
'',~++~-;--;-~-;~!!*!!!llokWK0XX@Xo!==~~==++;~++*~;~!*++**==++*+iidKo*=;`;~~+*;;,~=
..' .,~=;:;~*+!iiii!!ilcdK0KOKObl*+-;-~~--:=+=*~~=!~=++-;;=*iilc0d*~~;`:--~*~`:;*,
':::;-~*!!*illillldOK00Okkdl+-~;;;:`,;-==*===+==~-;;-+*iliO0k+=~,,:;--+~`:,-~
.'',:-++++++*!lxdXKK0Wdxbx+-;=-:,,:,,;*il!*++=~~-;--=ll!xKbi+-~:::;~;~-,`,;+
. '.'`;;---~!xbXXW00WKdkdi-;;;-`'`,:--+ioi-;=~::-=-;*cickOo+~,,;:---:~~`'`;=
,=' '.`,:;-idWM@MMX0Wdood!~;::,,,:::-~~=i*-:--,`:---**ioxxl+:``:~~-;:=:..,-:
.~!: ..`,-ixbK0M@@WWMklok*~;,,,'`,:,,:;~~;:::=-:;;-~*+ickol~`',;~~-`--',',-; ,
'`=!lkOOXW@WM0xcok*=;,,,;,,,:-,;=~``,-;`,:;-+**ikx**-.',;+~,:=,'``:--
. . '-=+lccxdXKObooxxdic!:''-::::,`;:,.'::'`:;-++=!ic!*+:.,,-*-,,,`'``;~~
. `:-~+ciicodkl*!!ixo*=:,. .'',`':,:,.',''`:;+li*+i!=*+;``:*~~,`''''`-=' `
`,:~=oi!llxkc!*!!ic+=;`'.....',:::,```'. ':*c++++l!-+*;'`~+::: ....`-~
.`,-+lx*=!xki*!!*ii+::-,`..'',:,,'.,~,'. .',++~=+ll*=*!``,~~`,` ..'.`;~
'`;*ii+~~lkl+++*cxc=;;,;::'`,;:''.',:`.. .`:--;*l!+~=~~.`,*-',;...'.',~
. . .`;*!+=-=oxi*===+ok!i~;++==,:;``'.'''`.. .,;-~*c+~=*-`=:,:+,':; '':.`:
':;+**+-=cki+=====io-=*=!lc+:::''`'. . .',,;+l*~=*+;:=--,:,:': '':`.,
.,;-~+=;=ckx+===~==li;~**=*ci-,'. .'`~+*l=-=!:,;,-:.`.:''. ...` :
. .,;~+=;~cxbo*++~--=~;-=~:;=++-` `'`~+li==!~`,,,=''' '. .'''..
.'. .,;=+~-~iokOdo*~;;=:`,:;+;:~;;: .';==;=++l+,::::;,: .';' . .
'''.'',+i!;;!cxckObi~;~;```:-~;:~;,' . ..'.;~-::~x+;:::'':o:' `,`.. .
',.``,~+-:;=ockl*xx*=-;,,::;;''','.` .``',-----;-il-;:-`.,:.., ,`,,'. .
...``:~~:,,-ikxoi!ii*=:'',,:;;...' ' .:-+!**+~~:-++=`--..'`..' `' `,.
. '`,;;,,:;+odkc*!lccci:''`,:`.. -' .,,,-~!+~,'`=-:~; ''. .` `
.``,;::;;~=*xooxli!!il='''';-.. .` .: . .:::!*~:~:`:~-' :' ..'' ``.
.',,;;:;--~~*lcloi!+;,:'`:'.. .. `. . .-:``:~+~;:`,~' .,, . .`` .xc
.`',;:~!:;;-=+*!*++*-,'. .'. ... .' .','`:``+:''-=,''',:..
.`,,,::;:;~-;~+~=+-,`' .' .. . .'''.'`:, ~~:'`:,'''``.. .
'''````,;;,:-~;;~;;,` ..'` ','.'``'' `,:=:...', . ..
.'`````,:',:,`,:;=!=;,' .'':' -:..',. . ` '':, .. .
.'``'``'.'''..':;--~+*+' .,` :, '.. ,;,. .
.'`''`'..'.. ..,;--::;;' ''.. `. . ',`..
...''''.... '`,`''' .' . .. .'
...'... . ..'. .` ..
....... .. .`. `
...... ',.
.... . . . .. .'
. .
.
.
Short version first: September was mostly BluePortal. It was the busiest month that repo has had, around 450 commits on prod, and three big pieces landed: the developer workbench, every Go service moving from Fiber onto Bosun, and a security audit with a fix for every finding. Bosun got v0.6.0 along the way, and Gantry got v0.5.0 in the first week.
Uni started again too, for my final year. Most of that was getting to grips with my new units, but I also joined the university squash team and met a lot of people from other courses, and it was interesting hearing about what they study.
Gantry v0.5.0
The first week went on Gantry. v0.4.2 (2 September) was a Linux fix: the upstream webview binding links webkit2gtk-4.0, which Fedora doesn't ship, so Gantry now vendors a fork that links 4.1. The same release added a capture compatibility option for WebView2 on Windows and moved the module path to my own GitHub account.
v0.5.0 (5 September) added modules: separate Go modules with a manifest that can ship docs pages (mounted in gantry docs) and an importable Go package, with JSON schemas to check the manifest. The docs got a round of SVG diagrams as well.
The other half of v0.5.0 was performance: pprof hooks, better caching for embedded assets, lazy loading for page modules, and patch diffing. Instead of sending the whole UI tree to the webview on every change, the server diffs against the last tree it sent and only sends what changed. TestMeasureScaling checks it with a list of n rows where one row and a counter change. The patch frame stays at 167 bytes, against a full tree of 2.2 KB at 10 rows and 6.8 MB at 32,000 rows. Server CPU is about the same either way, because the diff costs about what a full marshal does, so the win is on the wire and in React on the client.
BluePortal: the developer workbench
The middle of the month (13 to 18 September) was product work. Developer order lifecycle controls, user bans, developer settings and an analytics page, then the developer workbench: API keys, a read API, webhooks with a dispatcher for commerce events, admin views, and end-to-end tests over the whole pipeline (PRs #101 to #106).
After that came a request monitor. Caddy writes JSON access logs, an ingester stores them, and there's an admin UI to look through them, with a retention setting (#107 to #111). GDPR data export (#133) and one-click unsubscribe (#140) also went in, which closes two of the gaps from July's GDPR review.
BluePortal: from Fiber to Bosun
Before the migration I restructured the API from one big internal/services package into vertical domains: legal, marketplace, catalog, orders, payments, accounts, developer, media, discounts, licensing and so on (#113 to #143).
Then the move itself, strangler style, one service converted in place at a time:
- the relay first, as a spike (#144, 18 September)
- the email, auth and payments workers (#145 to #148)
- build-api and protection-api (#150, #151, 21 September)
- the main API last (#152, 25 September)
Nothing about the move was especially hard. The hassle was moving each service across and redeploying it, then retesting every feature it touched to make sure nothing important had broken, especially in the core systems.
Additionally, late in the month the build pipeline changed too. Builds used to run developers' repo code inside build-api's own container. Now a runner on the host runs each job in a throwaway container (#176). CI also gates staging and prod releases now (#162).
BluePortal: security audit
On 29 September I did a security audit of the whole platform. It came out with 19 findings and 2 bugs. Each fix went on its own branch (#177 to #197), they were merged together in #198, and shipped on the 30th.
The classes of issue: MFA not bound to the password step, ownership checks on upgrades, licence routing for subscriptions, price and tier locking during checkout, invite takeover, RBAC on developer orders, SSRF through developer webhook URLs, symlink-safe writes in the build workspace, revoking sessions on password reset, open redirects, OAuth pre-hijack, and tokens not bound to the user's email address.
The lesson I'm keeping: several findings were gaps in earlier fixes, and one was introduced by another fix from the same audit. A fix is new code and needs the same review as everything else.
Bosun v0.6.0
Bosun had a quieter month in its own repo, since most of its use was inside BluePortal. v0.6.0 (16 September) moved the module path to github.com/bluebeard63/bosun, merged a reconnect supervisor for the AMQP events module (it reconnects and re-subscribes when the broker drops), and the CLI now works out its own version at runtime (cmd/bosun v0.6.1).
Next month
- Bosun v0.7.0
- Nerve Media
- Final year at uni