Shellsharks Blogroll - BlogFlock https://blogflock.com/list/xJ8yq 2026-10-03T08:08:00.000Z BlogFlock shellsharks Weeknote #2020 - Robb Knight • Posts • Atom Feed https://rknight.me/blog/weeknote-2020/ 2026-10-03T08:08:00.000Z Robb Knight <p>Dave is doing important work here, <a href="https://heroes.daveliddament.co.uk">holding Cadbury Heroes to account</a>.</p> <p>MacOS 27 broke the drivers for my thermal printer but thankfully someone <a href="https://github.com/glaucusec/4barcode-macos-driver">made a new driver</a>.</p> <p>I'm on board with <a href="https://brand.io/article/spymarks/">Spymarks, not watermarks</a>.</p> <p>The <a href="https://www.thisiscolossal.com/2026/08/pure-street-photography-awards-2026-contest-winners/">winners of the street photography awards</a> are fantastic (obviously).</p> <p>Side-eyeing projects like <a href="https://unawatch.com">Una</a> to try and get away from my Apple Watch at some point.</p> <p><a href="https://www.youtube.com/watch?v=pV6MWmXo_Ss">Hannah Fry's favourite fountain pens</a>. Love this.</p> <p>There's no world in which I can watch <a href="https://www.youtube.com/watch?v=eY_8SyndC10">this documentary about Elon Musk</a> but I'm glad it exists.</p> <p>A <a href="https://www.flickr.com/groups/419512@N22/pool/with/55127153425">gallery of control rooms</a> on Flickr via <a href="https://simplebits.shop">SimpleBits</a>.</p> <p>While looking for an example of a Geordie accent, I came across <a href="https://www.youtube.com/watch?v=Ei1DnFdJrww">this supercut</a> of a "Geordie" character who has an accent that is so ridiculous I can't even work out what he thinks he's doing. They even brought in translator as a plot point. This whole thing is wild.</p> <p>This <a href="https://mastodon.social/@finnvoorhees/117360552143405957">monstrosity from Finn</a> for the iPhone Duo.</p> <p><a href="https://bastardica.mitpit.com">Barstardica</a> mixes different fonts into one for...reasons. I love and hate it.</p> <p><a href="https://github.com/Gissio/font_tiny5?ref=simplebits.com">This Tiny5 font</a> is amazing and I need somewhere to use it as soon as possible.</p> <p>Tyler has got me thinking about an old MacBook Pro we have at home with his post about <a href="https://tylersticka.com/journal/repurposing-a-15-year-old-macbook-air/">repurposing a 15-Year-Old MacBook Air</a>.</p> <p><a href="https://lazygit.app/#install">Lazygit</a> is very nice but not something I have a need for.</p> <p><a href="https://littlefedi.org/deploy.html">littleFedi</a> is a "<em>small ActivityPub server written in Go</em>". It's a single binary, designed to run on basically everything, and supports the Mastodon API.</p> 2026-10-03 09:04: Took the dogs out on the field this morning. All the dewey spider webs were... - Kev Quirk https://kevquirk.com/2026-10-03-0904 2026-10-03T08:04:00.000Z Kev Quirk <p>Took the dogs out on the field this morning. All the dewey spider webs were beautiful in the morning sun.</p> <p>I'm no Jack Baty, but they're good enough.</p> <p><img loading="lazy" src="https://kevquirk.com/content/images/2026-10-03-0904/1000012231.webp" alt="1000012231" /></p> <p><img loading="lazy" src="https://kevquirk.com/content/images/2026-10-03-0904/1000012228.webp" alt="1000012228" /></p> <p><img loading="lazy" src="https://kevquirk.com/content/images/2026-10-03-0904/1000012227.webp" alt="1000012227" /></p> <p><img loading="lazy" src="https://kevquirk.com/content/images/2026-10-03-0904/1000012233.webp" alt="1000012233" /></p> <div class="email-hidden"> <hr /> <p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p> <p>You can <a href="mailto:19gy@qrk.one?subject=2026-10-03%2009%3A04">reply to this post by email</a>, or <a href="https://kevquirk.com/2026-10-03-0904#comments">leave a comment</a>.</p> </div> Finished reading A Psalm for the Wild-Built - Molly White's activity feed 6ac052ad0db40ecf5ef7ebc4 2026-10-03T00:56:13.000Z Molly White <article class="entry h-entry hentry"><header><div class="description">Finished reading: </div></header><div class="content e-content"><div class="book h-entry hentry"><a class="book-cover-link" href="https://www.mollywhite.net/reading/books?search=A%20Psalm%20for%20the%20Wild-Built"><img class="u-photo book-cover" src="https://m.media-amazon.com/images/S/compressed.photo.goodreads.com/books/1708515061i/208944365.jpg" alt="Cover image of A Psalm for the Wild-Built" style="max-width: 300px;"/></a><div class="book-details"><div class="top"><div class="series-info"><i>Monk & Robot</i> series, book <span class="series-number">1</span>. </div><div class="title-and-byline"><div class="title"><i class="p-name">A Psalm for the Wild-Built</i> </div><div class="byline">by <span class="p-author h-card">Becky Chambers</span>. </div></div><div class="book-info">Published <time class="dt-published published" datetime="2021">2021</time>. 151 pages. </div></div><div class="bottom"><div class="reading-info"><div class="reading-dates"> Started <time class="dt-accessed accessed" datetime="2026-09-30">September 30, 2026</time>; completed September 1, 2026. </div></div></div></div></div><img src="https://www.mollywhite.net/assets/images/placeholder_social.png" alt="Illustration of Molly White sitting and typing on a laptop, on a purple background with 'Molly White' in white serif." style="display: none;"/></div><footer class="footer"><div class="flex-row post-meta"><div class="timestamp">Posted: <time class="dt-published" datetime="2026-10-03T00:56:13+00:00" title="October 3, 2026 at 12:56 AM UTC">October 3, 2026 at 12:56 AM UTC</time>. </div></div><div class="bottomRow"><div class="tags">Tagged: <a class="tag p-category" href="https://www.mollywhite.net/reading/books?tags=cozy" title="See all books tagged "cozy"" rel="category tag">cozy</a>, <a class="tag p-category" href="https://www.mollywhite.net/reading/books?tags=hopepunk" title="See all books tagged "hopepunk"" rel="category tag">hopepunk</a>, <a class="tag p-category" href="https://www.mollywhite.net/reading/books?tags=science_fiction" title="See all books tagged "science fiction"" rel="category tag">science fiction</a>. </div></div></footer></article> September 2026 Summary - Joel's Log Files https://joelchrono.xyz/blog/september-2026-summary 2026-10-02T22:59:27.000Z joelchrono <p>At last, another month we say good bye to, and all of a sudden, the year is on its final stretch, the days go by faster and faster, and I am getting old with everyone around me!</p> <p>In any case, there’s plenty of stuff to go through here, media, movies, videogames, podcasts. You Know the usual stuff! I have decided I would highlight the best things on this little intro, in case you are bored or looking to just skim through.</p> <ul> <li><strong>Podcasts</strong>: The Play Station Episode of <em>Into The Aether</em>, The Wolf 359 podcast as a whole</li> <li><strong>Manga</strong>: <em>Blame!</em> is simply awesome and terrifying.</li> <li><strong>Movies</strong>: Ad Astra, Artificial Intelligence, Catch Me If You Can, War of the Worlds, Coyote vs. ACME.</li> <li><strong>Videogames</strong>: <em>Final Fantasy IV</em> was a definite surprisei to return to. <em>Emio and the Smiling Man</em> was engagn</li> <li><strong>TV Shows</strong>: <em>Lanterns</em> was pretty refreshing for a super hero show, if a bit too adult for my taste.</li> <li><strong>Books</strong>: <em>The Left Hand of Darkness</em> and <em>The House on the Borderland</em> are still halfway through but I’m committed to both.</li> </ul> <figure> <img src="/assets/img/blogs/2026-10-01-month.webp" /> <figcaption>Some artwork of my favorite media that showed up during the month! </figcaption> </figure> <h2 id="podcasts">Podcasts</h2> <ul> <li> <p><strong>Into The Aether</strong> - With the release of the Play Station episode, my listening time for this podcast skyrocketed to a whooping 19 hours throughout the month! Fantastic set of episodes this time around.</p> </li> <li> <p><strong>The Ten Minute Bible Hour</strong> - I listened to a dozen or so episodes of this one again, but they are like ten minutes each so it doesn’t amount to a lot compared to the rest of stuff here. Extremely interesting as always though.</p> </li> <li> <p><strong>Dungeons and Daddies</strong> - A Dungeons & Dragons podcast. On a surprising turn of events, I finally returned to this podcast! I was able to pickup on the overall story again, thankfuly, so I plan to resume this crazy season 3, soon enough.</p> </li> <li> <p><strong>The Rest is History</strong> - Some good stuff here, still all about the Great War, it was early in the month and I’m not I recall all of it though.</p> </li> <li> <p><strong>Wonders of Web Weaving</strong> - I listened to a few episodes of this podcast by <a href="https://jamesg.blog">James</a> featuring different bloggers and stuff. Including me!</p> </li> <li> <p><strong>Wold 359</strong> - I made progress and went through a couple more episodes, the finale feels closer now! Really looking forward to that.</p> </li> </ul> <h2 id="manga">Manga</h2> <h3 id="started">Started</h3> <ul> <li><strong>Blame!</strong> - Chapter 1-9. This a dystopian sci-fi story that happens inside some sort of mega-structure. We met one guy who is looking for a human with a special gene, which should be able to control the mega-structure itself. Each chapter is full of incredible architechture and a very intriguing atmosphere. Lots of questions lack answers right now, but I am kind of hooked by it. The chapters are a little long though, but they don’t have a lot of dialogue so, it’s all good.</li> </ul> <h3 id="ongoing">Ongoing</h3> <ul> <li> <p><strong>Centuria</strong> - Chapter 48-80. A lot of pretty cool action and great moments happened, but I have kind of realized that this manga, while entertaining and still promising, is taking its time to deliver actually interesting plot points. I still enjoy it, because it lets me fill about ten minutes of my time with neat drawings to look at.</p> </li> <li> <p><strong>Smoking Behind the Supermarket with You</strong> Chapter 63-64. Now this is still going to some interesting places. A lot of introspection during these couple chapters, after a pretty heavy and difficult situation, a conflict in need of resolution, which I’m looking forward to see. I love these characters!</p> </li> <li> <p><strong>Blue Lock</strong> - Chapter 357-359. I was reading this with great interest, but decided to wait at least until I’m sure the England vs Japan match is completed, so I can enjoy it all in one go. Fun stuff!</p> </li> <li> <p><strong>My Wife is from a Thousand Years Ago</strong> - Chapters 287-288. This is just a fun rom-com! No complaints, a nice pace and very fun moments, a little spicy but mostly wholesome, which I prefer.</p> </li> </ul> <h2 id="movies">Movies</h2> <p>I was going to like, write kinda proper reviews for these but, meh, they were all pretty decent except for <em>Mercy</em>, you can skip that one.</p> <ul> <li><strong>Avengers Endgame Encore</strong> - Fun to rewatch on the big screen at last! The extra scenes aren’t really worth it though.</li> <li><strong>The Day the Earth Stood Still</strong> - An alien tells humanity to chill out <em>or else</em>. Seriously impressive for the time.</li> <li><strong>War of the Worlds</strong> - Tom Cruise running from aliens from Mars. He also tries to be a good father at the same time.</li> <li><strong>By Any Means</strong> - A bunch of racists face the consequences of their actions. A bit of a weird casting choice though.</li> <li><strong>Mercy</strong> - Chris Pratt trapped by AI and staring at screens. The murder mystery was fine, the presentation not really.</li> <li><strong>Artificial Intelligence</strong> - A robot wants the be a real boy and earn a mother’s love. That ending is wild though.</li> <li><strong>Catch Me If You Can</strong> - Leonardo Di Caprio running from Tom Hanks. The movie is based on real events that turned out to be fake!</li> <li><strong>Ad Astra</strong> - Brad Pitt running from the world itself, looking for his father. Surprisingly Hard Sci-Fi stuff here.</li> <li><strong>Coyote vs. ACME</strong> - This one was funny and nostalgic and I loved it. No notes, it made me cry out laughing.</li> </ul> <h2 id="videogames">Videogames</h2> <h3 id="started-1">Started</h3> <ul> <li><strong>Kirby and the Forgotten Land</strong> - A friend came over one time and we decided to start this one in 2-player mode. I decided it would be a pretty fun title to add to the multiplayer pile of games I mostly play with other people! It is extremely fun. The artstyle, the level design, the Switch performance and everything combined make for a very pleasant gaming experience.</li> </ul> <h3 id="ongoing-1">Ongoing</h3> <ul> <li> <p><strong>Final Fantasy IV</strong> - This is the game that ended up being revisited the most, with about as much time played of it as <em>Emio</em>, but grinding and progressing through the last few challenges this game has to offer, and the final dungeon which is at my grasp at last. Final Fantasy IV may be the first ever Final Fantasy I complete, and I’m looking forward to it.</p> </li> <li><strong>Hollow Knight: Silksong</strong> - This game started strong in the month, playing it for about five hours in four days. I got into Act 3 and defeated some new bosses, I upgraded my needle and got more stuff from all that.</li> <li> <p><strong>Fire Emblem Awakening</strong> - I made significant progress completing chapters 19 and 20 without a lot of issues, after some grinding throughout many days. Loving the support scenes as well! Waiting for its time to shine some more.</p> </li> <li> <p><strong>The Legend of Zelda: Ocarina of Time 3D</strong> - I only played this one time, but I made some initial progress as Adult Link, reaching the Forst Temple. I only need to focus and complete the dungeon itself and continue the story some more!</p> </li> <li> <p><strong>Tomodachi Life: Living the Dream</strong> - Revisited my island a couple of times, but I haven’t really made a lot more with it. I should try to like, remodel everything or do something more creative, but the spark isn’t quite there for me right now.</p> </li> <li><strong>Super Smash Bros Ultimate</strong> - I had some very epic moments playing with friends this time around, it was awesome. <h3 id="completed">Completed</h3> </li> <li><strong>Emio: The Smiling Man</strong> - I am yet to review this, a detective story with visual novel mechanics that really caught me for three days straight. Pretty much only paused to eat and sleep as soon as I started it! Amazing artwork, great music, intriguing plotline, fun characters, so many suspects! Loved it.</li> </ul> <h2 id="tv-shows">TV Shows</h2> <ul> <li><strong>Lanterns</strong> - I watched like four episodes of this in a single day and it was a pretty good detective story kinda thing. I wasn’t expecting to like it as much, although I kinda abandoned it halfway through. Will probably finish the season soon.</li> </ul> <h2 id="books">Books</h2> <ul> <li> <p><strong>The House on the Borderland</strong> by William Hope Hodgson. Up to chapter 14. This is a very interesting horror novel, that deals with the existential, multiple dimensions, entities beyond our understanding, and whatever else. In the form of a diary written by an old man from long ago. It has been very gripping so far, but I paused it for the sake of the next book.</p> </li> <li> <p><strong>The Left Hand of Darkness</strong> by Ursula K. Le Guin. Up to chapter 7. This was chosen for the TWGLK Book Club for September and… I didn’t manage to finish it, started too late. Anyway, I am enjoying it as is, and without the time pressure. This is a very interesting book featuring a couple points of view, but mostly focused on an envoy sent by an interplanetary force</p> </li> </ul> <h2 id="finishing-thoughts">Finishing thoughts</h2> <p>I wonder what the reading retention was on this one giving you a summary of summary of the month at the very beginning. I guess we’ll see over time.</p> <p>It’s not like I should care about this stuff being read, it’s always more of a log for myself so I can lock down when some interesting movie or videogame showed up on my radar with a simple <code class="language-plaintext highlighter-rouge">grep</code> command on my terminal.</p> <p>In any case. This year is flying by, and it’s pretty clear that the yearly recaps will require quite a lot of effort! Looking forward to that.</p> <p>This is day 46 of <a href="https://100daystooffload.com">#100DaysToOffload</a></p> <p> <a href="mailto:me@joelchrono.xyz?subject=September 2026 Summary">Reply to this post via email</a> | <a href="https://fosstodon.org/@joel/117374199881890755">Reply on Fediverse</a> </p> Published on Citation Needed: "Issue 110 – The Clarity Act collapses" - Molly White's activity feed 6ac0512b52b01ca28c3ff883 2026-10-02T20:29:05.000Z Molly White <article class="entry h-entry hentry"><header><div class="description">Published an issue of <a href="https://www.citationneeded.news/"><i>Citation Needed</i></a>: </div><h2 class="p-name"><a class="u-syndication" href="https://www.citationneeded.news/issue-110" rel="syndication">Issue 110 – The Clarity Act collapses </a></h2></header><div class="content e-content"><div class="media-wrapper"><a href="https://www.citationneeded.news/issue-110"><img src="https://www.citationneeded.news/content/images/size/w2000/format/webp/2026/10/gillibrand-clarity-1.png" alt="Senator Gillibrand votes “no” on the motion to invoke cloture for the Clarity Act"/></a></div><div class="p-summary"><p>Regulators race to reassure the crypto industry as the industry’s flagship legislation collapses, SBF tries his luck with the Supreme Court, and crypto PACs unleash $30 million against Sherrod Brown</p></div></div><footer class="footer"><div class="flex-row post-meta"><div class="timestamp">Posted: <a class="u-url" href="https://www.citationneeded.news/issue-110"><time class="dt-published" datetime="2026-10-02T20:29:05+00:00" title="October 2, 2026 at 8:29 PM UTC">October 2, 2026 at 8:29 PM UTC</time>. </a></div><div class="social-links"> <span>Also posted to:</span><a class="social-link u-syndication mastodon" href="https://hachyderm.io/@molly0xfff/117374132542933307" title="Mastodon" rel="syndication">Mastodon</a><a class="social-link u-syndication bluesky" href="https://bsky.app/profile/molly.wiki/post/3mwwlnys7e227" title="Bluesky" rel="syndication">Bluesky</a></div></div><div class="bottomRow"><div class="tags">Tagged: <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/coinbase" title="See all feed posts tagged "Coinbase"" rel="category tag">Coinbase</a>, <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/crypto" title="See all feed posts tagged "crypto"" rel="category tag">crypto</a>, <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/crypto_lobby" title="See all feed posts tagged "crypto lobby"" rel="category tag">crypto lobby</a>, <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/law" title="See all feed posts tagged "law"" rel="category tag">law</a>, <a class="tag p-category" href="https://www.mollywhite.net/feed/tag/us_politics" title="See all feed posts tagged "US politics"" rel="category tag">US politics</a>.</div></div></footer></article> Gadget Review: Una Watch ★★★★☆ - Terence Eden’s Blog https://shkspr.mobi/blog/?p=76031 2026-10-02T11:34:48.000Z Terence Eden’s Blog <p>I've never been a huge fan of smart watches. My <a href="https://shkspr.mobi/blog/2025/08/i-bought-a-16-smartwatch-just-because-it-used-usb-c/">£16 smartwatch</a> is basically fine, but the OS is closed source and there's no way to add new functionality. Previously I had the <a href="https://shkspr.mobi/blog/2023/06/review-watchy-an-eink-watch-full-of-interesting-compromises/">eInk Watchy</a> which was a pain to use and really poorly designed. Even back in 2014 I was bemoaning the design compromises in the <a href="https://shkspr.mobi/blog/2014/11/disassembling-the-mykronoz-zewatch-smart-watch/">MyKronoz ZeWatch Smart Watch</a>.</p> <p>So why did I pick up the Una Watch?</p> <p>Firstly, the Una Watch is designed in Scotland <del>from girders</del>, and it's always nice to support local businesses.</p> <p>Secondly, as a <a href="https://shkspr.mobi/blog/2026/07/im-a-usb-c-maximalist/">USB-C Maximalist</a> I want gadgets which can plug in to the same cables as all my other toys. No magnetic pucks here!</p> <p>Thirdly, it is (almost) <a href="https://unawatch.com/pages/open-source">completely open source</a>.</p> <p>Finally, it is repairable. You can easily unscrew it to replace the components. As my cheap smartwatch's dial has died after 12 months of use, that's a pretty compelling proposition!</p> <p>Let's put it through its paces!</p> <h2 id="first-impressions"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#first-impressions">First Impressions</a></h2> <p>I bought mine second hand (yay for sustainability) and it arrived with a flat battery. The first charge from 0-100% took a little over an hour. My USB-C power monitor showed it taking in about 5V and 0.17 amps.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/09/Charging.webp" alt="Power monitor showing 0.84W." width="1024" height="576" class="aligncenter"> <p>It happily charged from a PD plug, but didn't get any faster than about 0.84W. Basically, I can fully charge it on most public transport in London.</p> <p>The time seemed accurate, there were options to play about with, the vibrations for notifications were easy to feel. There is an option to make it beep with every button press - I turned that off sharpish!</p> <h2 id="disclaimer"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#disclaimer">Disclaimer</a></h2> <p>I am <em>not</em> <a href="https://shkspr.mobi/blog/2026/09/are-you-a-smartwatch-power-user/">a smartwatch power user</a>. I'm not using this to minutely track all my exercise or calculate if my heart is going to explode. I don't need cm level precision of my GPS. I didn't sync this with Strava or anything else.</p> <h2 id="apps"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#apps">Apps</a></h2> <p>The official Android app (which, sadly, isn't Open Source) worked fine on GrapheneOS. It found the watch, updated its GPS almanac, and let me browse the app store & install apps. Obviously early days, but there are a variety of community developed apps to play with.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/09/apps.webp" alt="List of apps." width="504" height="728" class="aligncenter"> <p>Annoyingly the watch needs to be restarted after every app is installed - but that only take a handful of seconds.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/09/Restart-watch.webp" alt="Message telling me the watch needs to restart." width="504" height="640" class="aligncenter"> <p>There are some <em>strange</em> error messages.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/09/error-message.webp" alt="birthday must be a valid ISO 8601 date string country must be a valid ISO31661 Alpha2 code." width="504" height="426" class="aligncenter"> <p>That isn't the sort of message which should be shown to users.</p> <p>But, on the plus side, you can install Doom!</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/09/Doom.webp" alt="App store listing showing Doom on the watch." width="504" height="550" class="aligncenter"> <h2 id="the-screen"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#the-screen">The Screen</a></h2> <p>Oddly for a modern smartwatch, the screen stays on <em>all the time!</em> But this isn't some power-hungry OLED, nor is it static eInk. Instead it is a <a href="https://www.andersdx.com/memory-in-pixel-displays/">memory in pixel</a> display - black background with orange, blue, and white pixels. The backlight remains off most of the time and is easy enough to see in daylight. It is <em>slightly</em> reflective - but not too bad.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/09/Reflective.webp" alt="Watch showing notifications, there is a bit of a reflection." width="1024" height="576" class="aligncenter"> <p>Note the <code>??</code> on the notifications - more on that later.</p> <p>Annoyingly, there's no "raise wrist to light" option. You have to interact with the watch to get the screen on. The accelerometer should allow this functionality - so perhaps it just needs to be activated in the firmware? It is bright enough to see in the dark, but not so bright it will dazzle you or people nearby.</p> <p>There's no touchscreen - instead there are four buttons around the face. Up, down, select, back. I did find myself repeatedly jabbing at the screen to no avail.</p> <p>So, to light it, press the back button or hold one of the other buttons.</p> <p>The colour scheme is pleasant enough. I miss having a full colour display so I can see a photo of my wife whenever I glance at the screen. But the low power usage can't be argued with.</p> <h2 id="notifications"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#notifications">Notifications</a></h2> <p>I couldn't get notifications working at first. The app just refused to let me toggle them on. Eventually I found an app in the app-store which claimed to enable them. That didn't work either.</p> <p>Unpairing, repairing, and reinstalling the app made them spring to life.</p> <p>There's no notification history. Once you've clicked to read it, that's it. Gone forever. Considering this has 4GB storage, that's an odd decision.</p> <p>Some of the notifications were slightly corrupt - showing question marks in place of (I assume) esoteric Unicode.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/09/Question-Mark-notification.webp" alt="A notification on screen with a question mark before the user's name." width="1024" height="768" class="aligncenter"> <p>There's no way to customise the vibrate pattern - so everything "feels" the same on your wrist.</p> <p>At the moment, the Una Watch sends <em>every</em> notification to your phone. You can't tell it to ignore certain WhatsApp groups, or only allow text messages from your spouse. The only way to get fine-grained notifications is with a third-party app like…</p> <h2 id="gadgetbridge"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#gadgetbridge">Gadgetbridge</a></h2> <p>You're not tied to the official app. <a href="https://gadgetbridge.org/gadgets/wearables/una/">Gadgetbridge support is excellent</a>. There are a few things missing (you can't install apps or set alarms) - but if you want to measure your heart rate, send notifications, etc you'll be fine.</p> <h2 id="linux-compatibility"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#linux-compatibility">Linux Compatibility</a></h2> <p>The Una Watch plugs in to USB-C and shows up as 3.5GB of exFAT formatted storage.</p> <img src="https://shkspr.mobi/blog/wp-content/uploads/2026/10/Una-Filesystem.webp" alt="Filesystem view showing various JSON files." width="500" height="649" class="aligncenter"> <p>You can manually edit the JSON files if you like. I think you can copy off your workout data. Or you can just use it as portable storage.</p> <p>Under <code>lsusb</code> it describes itself as <code>0483:52a4 STMicroelectronics UNA Watch</code></p> <h2 id="battery-life"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#battery-life">Battery Life</a></h2> <p>After a full day of use the battery was at around 95% - that was with a bit of GPS, several notifications, heart rate monitoring, step counting, and a bunch of fiddling. With more GPS use, that's going to be heavier on the battery.</p> <p>But the joy of USB-C is that I can thwack in the same cable as I use for all my other gadgets. I can even plug it into my phone and leach a bit of power from there.</p> <h2 id="development"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#development">Development</a></h2> <p>The watch comes will a full <a href="https://github.com/UNAWatch/una-sdk">Open Source SDK</a> including lots of assets. There are several tutorials and a friendly community board.</p> <p>Of course, everything has to be done in C++ - an accurs'd language which I learned in the last century and wish I'd forgotten.</p> <p>Annoyingly, the <a href="https://github.com/UNAWatch/una-sdk/blob/main/Docs/sdk-setup.md">TouchGFX GUI designer</a> only works in Windows.</p> <p>I'm going to try to build my own watch faces and a few niche apps.</p> <h2 id="downsides"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#downsides">Downsides</a></h2> <p>There are a few things this watch <em>doesn't</em> do - some of these may be deal-breakers for you, but weren't for me.</p> <ul> <li>No payments. There's no tap-to-pay, NFC, or anything like that.</li> <li>No microphone. You cannot speak into your Una Watch or take calls on it.</li> <li>No speaker. There's a little buzzer which can make squeaks and squawks - but you won't be playing your music through it.</li> <li>While the apps and SDK are fully open, the firmware isn't (yet).</li> <li>Can't reply to notifications.</li> <li>No maps or directions (yet).</li> <li>Step counter only shows the full day - no hour-by-hour view.</li> </ul> <p>Some of these things can and will be fixed in software. Others are limitations of the hardware.</p> <h2 id="final-thoughts"><a href="https://shkspr.mobi/blog/2026/10/gadget-review-una-watch/#final-thoughts">Final Thoughts</a></h2> <p>The Una Watch has dropped in price to £180. I grabbed mine 2nd hand from eBay for £120. At either price, it's decent value <em>if</em> you're happy to play with alpha / beta quality technology.</p> <p>If you're a serious athlete, you'll probably want a more expensive and polished experience. If you are tied into the Apple or Google ecosystems, you'll probably want one of their watches.</p> <p>If you like tinkering, want to experiment with new technology, or simply want to support a British company trying to build something open - then this is the watch for you. Yes, there are some rough edges, but I fundamentally believe that technology should be Open Source, repairable, and give control to its users.</p> <img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=76031&HTTP_REFERER=Atom" alt width="1" height="1" loading="eager"> SequenceHash: multihashing for the rest of us - Trail of Bits Blog https://blog.trailofbits.com/2026/10/02/sequencehash-multihashing-for-the-rest-of-us/ 2026-10-02T11:00:00.000Z Trail of Bits Blog <p>Multihashing is one of those cryptographic tasks that’s easy not to think about too much. This is unfortunate, because multihashing is a <a href="https://blog.trailofbits.com/2024/08/21/yolo-is-not-a-valid-hash-construction/#yolomultihash">common stumbling point</a> when cryptographers try to use hashes.</p> <p>As part of our goal to “fix software, not bugs,” Trail of Bits is introducing <a href="https://github.com/C2SP/C2SP/blob/main/sequencehash.md">SequenceHash and its sister function SequenceMAC</a>, a pair of related hash constructions that bring secure multihashing to developers using hash functions other than Keccak. We hope SequenceHash and SequenceMAC will help cryptographers avoid attacks that take advantage of ambiguous input encodings. The specification is open source, and is now a <a href="https://github.com/C2SP/C2SP/blob/main/sequencehash.md">part</a> of the Community Cryptography Specification Project (C2SP).</p> <p>SequenceHash and SequenceMAC behave similarly to NIST’s <a href="https://csrc.nist.gov/pubs/sp/800/185/final">TupleHash</a>, but have the advantage of not being tied to a single hash function. They also don’t require developers to implement fiddly computations that aren’t byte-aligned. Instead, SequenceHash and SequenceMAC work out of the box with nearly any secure cryptographic hash function you care to use, including SHA256/384/512, BLAKE, and RIPEMD. SequenceMAC supports keys 32 bytes or longer (up to the ridiculous limit of ${2}^{128}-1$ bytes).</p> <p>(It’s worth noting: SequenceHash and SequenceMAC rely on the security of the underlying hash for their own security. SequenceHash and SequenceMAC can’t magically make MD4 or SHA0 secure again. For the purposes of this document, it’s assumed that you have chosen a reasonable hash function like SHA256, not CRC32.)</p> <p>To make SequenceHash and SequenceMAC easy to use, we’re releasing three initial implementations of SequenceHash and SequenceMAC: one each in Rust, Go, and Python. We’re also releasing a large set of test vectors that cover multiple hash functions and include intermediate values to help developers debug and verify their implementations.</p> <h2 id="wait-multihashing">Wait, “multihashing”?</h2> <p>Yeah, it’s a weird term, but the idea is pretty simple. “Multihashing” means “hashing a bunch of values together.” If you’ve ever read a cryptography paper, and there’s a step that says something like “compute the shared authenticator <code>N=Hash(X, Y, Z, A, B)</code>,” that’s multihashing. You need to create a hash that incorporates the inputs <code>X, Y, Z, A</code>, and <code>B</code>. Unfortunately, the simple “solution” of concatenating the inputs and hashing the result can lead to serious security problems.</p> <p>For example, consider what happens when you hash three inputs using “raw” SHA256:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-py" data-lang="py"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">hashlib</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 1'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 2'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">())</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0Test 1'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 2'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">())</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="sa">b</span><span class="s1">''</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 1Test 2'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">())</span></span></span></code></pre> </figure> <p>This produces the following output:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">4fce0a9940a42b5c9d1bcbfc9a6ddd6de20d731d584a0acf5bda6de86483641c </span></span><span class="line"><span class="cl">4fce0a9940a42b5c9d1bcbfc9a6ddd6de20d731d584a0acf5bda6de86483641c </span></span><span class="line"><span class="cl">4fce0a9940a42b5c9d1bcbfc9a6ddd6de20d731d584a0acf5bda6de86483641c</span></span></code></pre> </figure> <p>Even though inputs are fed in through separate calls, they’re not separated from the perspective of the hash function—under the hood, the inputs are just concatenated.</p> <p>As with many things in cryptography, multihashing is harder than you think. That’s a big problem because multihashing is a critical component of one of the most important tools in zero-knowledge proofs: the <a href="https://blog.trailofbits.com/2021/02/19/serving-up-zero-knowledge-proofs/">Fiat-Shamir transform</a>. When you get multihashing wrong, you introduce the risk of forgeries into your zero-knowledge proofs. Given that zero-knowledge proofs play a major role in cryptocurrency nowadays, that sort of mistake is sometimes measured in millions of dollars.</p> <p>But Fiat-Shamir transforms aren’t the only place where you might want to use multihashing. It’s not uncommon to need to hash a collection of related objects, where both the objects <em>and</em> the collection are variable in size. Think of authenticating the files in an archive, grouping multiple cryptocurrency transactions into a single hash, or hashing something as <a href="https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/">“simple” as somebody’s name</a>.</p> <p>Multihashing is also used when generating cryptographic commitments to values. In some protocols, one party must perform calculations using secret values, only to reveal them to other parties for later verification. Often, this is done by hashing the secret value along with a random “blinding” value and broadcasting the result to other parties as the commitment. If the boundary between the secret value and the blinding value isn’t clear, a “commitment” can sometimes be opened several different ways.</p> <p>Unfortunately, nobody seems to have landed on a consistent, standard solution to this problem. Instead, across the open-source ecosystem and in our private audits, we find developers solving the problem in wildly different ways. Some of these solutions are insecure, like using separator characters that can also appear in the inputs. Others encode their data in a way that makes their separators unambiguous, but the encoding is unnecessarily complex and introduces subtle timing risks. Think of stuff like Base64-encoding byte strings and separating the results with dollar signs. We often see situations where <em>some</em> hash inputs are length-encoded, but not <em>all</em>. It’s the wild west out there.</p> <p>There are tools specific to Fiat-Shamir transforms, like <a href="https://merlin.cool/">Merlin</a> and our own <a href="https://github.com/trailofbits/decree">decree</a>, but they don’t work so well for <em>general</em> multihashing.</p> <p>The most widely known standard for multihashing is TupleHash, defined in <a href="https://csrc.nist.gov/pubs/sp/800/185/final">NIST SP 800-185</a>. To be clear, TupleHash is great. It solves the multihashing problem in a straightforward way (length-prefix encoding), and it handles inputs of <em>effectively</em> unlimited size (if you’re regularly hashing more than ${2}^{2040}-1$ bits of input, Trail of Bits wants to party with you and your disrespect for physics). As a bonus, it naturally operates as an XOF. If TupleHash is available for you, it’s a <em>great</em> tool.</p> <p>TupleHash has a downside, though: it’s only defined to work with Keccak, the function that underpins SHA3. If you replace Keccak with another hash function, several of the important security features (like length-extension resistance) can go away. If you don’t have a Keccak implementation handy, you’re out of luck. Given that SHA3 and Keccak adoption have been pretty lackluster over the last decade, that leaves a lot of cryptographers out in the cold. This is especially true in the government contracting sector, where <a href="https://media.defense.gov/2025/May/30/2003728741/-1/-1/0/CSA_CNSA_2.0_ALGORITHMS.PDF">CNSA 2.0</a> has mandated SHA384 and SHA512 for nearly everything.</p> <p>This is a problem that cries out for a standardized solution. It calls for a complete specification. It begs for ready-to-use implementations available in multiple languages.</p> <h2 id="enter-sequencehash">Enter SequenceHash</h2> <p>SequenceHash is a hash-agnostic multihashing construct, similar to the way HMAC is a hash-agnostic MAC construct. You can use SequenceHash with your favorite hash functions, including the entire SHA2 family, BLAKE, RIPEMD, and more.</p> <h2 id="what-does-sequencehash-offer">What does SequenceHash offer?</h2> <p>SequenceHash offers four key features that prevent your hashed values from being mixed, extended, or replayed across contexts.</p> <h3 id="unambiguous-input-encoding">Unambiguous input encoding</h3> <p>Given two inputs $\left({A,\ B}\right)$, you are guaranteed that there is no other sequence of inputs $\left({{I}_{1},\ldots ,{I}_{t}}\right)$, for any length $t$, that will result in the same input to the underlying hash function.</p> <p>In other words, the values you hash are guaranteed to be “semantically distinct.” There’s no chance of playing games with the beginnings and endings of inputs, and there’s no opportunity to mix up parts of $A$ with $B$ or vice versa.</p> <p>SequenceHash helps cryptographers follow <a href="https://en.wikipedia.org/wiki/Horton_principle">the Horton principle</a>: you are hashing what you mean, and meaning what you hash.</p> <h3 id="length-extension-prevention">Length-extension prevention</h3> <p>Several popular hash functions, including SHA256 and SHA512, are vulnerable to length extension attacks. If Alice has a secret value $A$ and sends $H\left({A}\right)$ to Bob, then Bob can craft a value $B$ such that he can compute $H\left({A||B}\right)$, even though he doesn’t know $A$.</p> <p>SequenceHash doesn’t have that issue. It uses a double-hash construction that prevents Bob from learning the information he needs to compute $H\left({A||B}\right)$.</p> <h3 id="built-in-customization-strings">Built-in customization strings</h3> <p>If you’re developing cryptographic protocols, it’s often important to bind hashed values to a particular step in the protocol, or to a specific <em>instance</em> of the protocol, in order to prevent replay attacks or other problems related to reusing values.</p> <p>SequenceHash makes this easy with built-in customization strings. Assuming you’re using a good hash function, applying SequenceHash or SequenceMAC to the same inputs with different customization strings will lead to unrelated outputs, allowing you to easily and predictably bind your hashes to particular uses. If you don’t need a customization string, don’t worry. They’re completely optional.</p> <p>As an added bonus, the customization strings are incorporated only into the outer layer of the double-hash construction. If you need to hash the same value with multiple customization strings, the inner hash can be reused!</p> <h3 id="mac-mode">MAC mode</h3> <p>One final cool feature of SequenceHash is that it has a keyed mode, SequenceMAC. SequenceMAC is structurally similar to HMAC, and offers the same features as SequenceHash: unambiguous encoding, customization strings, and length-extension protection. It also incorporates metadata about the key and customization strings to prevent the key pseudocollision issues present in HMAC.</p> <h2 id="how-does-sequencehash-work">How does SequenceHash work?</h2> <p>Like TupleHash, SequenceHash uses length encoding to unambiguously encode its inputs. However, SequenceHash uses a simplified encoding. Instead of writing the number of bits to be hashed as a variable-length integer, SequenceHash encodes the number of bytes into a fixed-length, 128-bit integer. SequenceHash uses a length-suffix encoding for inputs. Like the length-prefix encoding system used by TupleHash, length-suffix encoding is unambiguous; however, suffix encoding allows implementers to develop streaming APIs when they need to support hashing data with length that isn’t known ahead of time.</p> <p>We chose a 128-bit length encoding for simplicity of implementation on 32- and 64-bit systems (padding with zeroes is easy), and because a ${2}^{128}-1$ byte limit exceeds all practical considerations for the time being <em>and</em> the foreseeable future. Two of the most popular hash functions in use today, SHA256 and SHA512, limit their inputs to ${2}^{61}$ and ${2}^{125}$ bytes, respectively, meaning that a ${2}^{128}-1$-byte limit exceeds the specified limits of the most popular underlying hash functions, anyway. If you’re pushing the edges of SequenceHash, you’ve already blown past the limits of SHA256 and SHA512.</p> <p>We use byte counts for simplicity. Nearly all hashing today is performed in software on strings of 8-, 16-, 32-, or 64-bit values. Systems using non-byte-length strings are very rare nowadays, and we believe it should be up to implementers of such systems to provide their own byte padding if they want to use SequenceHash.</p> <p>Like HMAC, SequenceHash uses a double-hash construction to prevent length extension attacks. This structure also allows us to support a keyed variant, SequenceMAC, which accepts keys up to ${2}^{128}-1$ bytes in length.</p> <p>One downside of the original HMAC construction is that it’s subject to what are known as “key pseudocollisions.” HMAC keys can be any length, but if they’re longer than a certain cutoff value (that depends on the hash), they get hashed before use. This means that every “long” key has a “short” representation that produces the exact same outputs. If you’re careful about specifying and enforcing key lengths in protocols, you can guard against this sort of problem, but if you’re not careful, somebody could present two versions of the “same” key in different contexts, allowing them to engage in shenanigans.</p> <p>Another form of key pseudocollision is key extension. As far as HMAC is concerned, the 8-bit key <code>0xff</code> is the same as the 16-bit key <code>0xff00</code> and the 128-bit key <code>0xff000000000000000000000000000000</code>. Appending zeroes to a key doesn’t actually change it (unless it goes beyond the length cutoff, at least). This sort of pseudocollision is a bit more insidious, because it’s the sort of thing that can show up accidentally; it’s not hard to imagine unintentionally passing a 128-bit key instead of a 256-bit key, or incorrectly setting a length indicator somewhere.</p> <p>The keyed variant of SequenceHash, SequenceMAC, incorporates key lengths into a header block that is part of the hash. As a result, HMAC-style long-key pseudocollisions are hard to find: if a key needs to be preprocessed by hashing, supplying the hash of the raw key is <em>not</em> the same as supplying the raw key. Trailing zeroes in a SequenceMAC key are semantically significant.</p> <p>SequenceHash and SequenceMAC support customization strings for domain separation, similar to TupleHash’s customization strings. Customization strings can be up to ${2}^{128}-1$ bytes in length, and they’re only integrated into the <em>outer</em> hash function, allowing developers to derive multiple hashes from the same set of inputs <em>without</em> rehashing everything.</p> <h2 id="how-do-i-use-it">How do I use it?</h2> <p>Glad you asked! We already have three implementations available: <a href="https://github.com/trailofbits/sequencehash-rs">Rust</a>, <a href="https://github.com/trailofbits/sequencehash-go">Go</a>, and <a href="https://github.com/trailofbits/sequencehash-py">Python</a>. We also have a <a href="https://c2sp.org/sequencehash">specification</a> available as part of the C2SP, with <a href="https://github.com/C2SP/CCTV/tree/main/sequencehash">test vectors</a> available in case you want to write your own implementation.</p> <p>The main feature that distinguishes the SequenceHash API from other APIs is that all updates to SequenceHash and SequenceMAC objects are <em>atomic</em>. That is, each time you write a value to a hashing object, it will be added to the hash as an independent, length-encoded object.</p> <p>We have worked to make sure that the SequenceHash and SequenceMAC APIs are similar, but not identical, to the standard APIs for each language. The Go cryptographic library’s <code>hash.Hash</code> interface incorporates the <code>io.Writer</code> interface, which guarantees that writing two values in sequence is the same as writing their concatenation. The Python hash library makes similar guarantees for the PEP 247 <code>update</code> function.</p> <p>Let’s see what happens when we hash our example values above using SequenceHash:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-py" data-lang="py"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">sequencehash</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">sequencehash</span><span class="o">.</span><span class="n">SequenceHash</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 1'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 2'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">result</span><span class="p">()</span><span class="o">.</span><span class="n">hex</span><span class="p">())</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">sequencehash</span><span class="o">.</span><span class="n">SequenceHash</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0Test 1Test 2'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">result</span><span class="p">()</span><span class="o">.</span><span class="n">hex</span><span class="p">())</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">sequencehash</span><span class="o">.</span><span class="n">SequenceHash</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 1Test 2'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">result</span><span class="p">()</span><span class="o">.</span><span class="n">hex</span><span class="p">())</span></span></span></code></pre> </figure> <p>We get the following output:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">6eea7264b266d35bd5e483ef042189d2cebe51f9e8b764b90b0f9c82185de7ca </span></span><span class="line"><span class="cl">1469d91e90c1d9c6189f576822e900f5cc8c3cdbd2ec51256df649d37c1688f7 </span></span><span class="line"><span class="cl">1800a2188e126c79dac8f7cf7e38a66e3f797654c15a5e49248a94d4e99bcaae</span></span></code></pre> </figure> <p>The three outputs are all unrelated. That’s because each of the inputs is length-encoded, meaning that feeding <code>Test 0</code> and <code>Test 1</code> into consecutive calls to SequenceHash is <em>not</em> the same as feeding <code>Test 0Test 1</code> into a single call.</p> <p>We can also try hashing identical inputs with different customization strings:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-py" data-lang="py"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">sequencehash</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">sequencehash</span><span class="o">.</span><span class="n">SequenceHash</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">result_with_customizer</span><span class="p">(</span><span class="sa">b</span><span class="s1">'CUST 0'</span><span class="p">)</span><span class="o">.</span><span class="n">hex</span><span class="p">())</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">sequencehash</span><span class="o">.</span><span class="n">SequenceHash</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">result_with_customizer</span><span class="p">(</span><span class="sa">b</span><span class="s1">'CUST 1'</span><span class="p">)</span><span class="o">.</span><span class="n">hex</span><span class="p">())</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">sequencehash</span><span class="o">.</span><span class="n">SequenceHash</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">result_with_customizer</span><span class="p">(</span><span class="sa">b</span><span class="s1">'CUST 2'</span><span class="p">)</span><span class="o">.</span><span class="n">hex</span><span class="p">())</span></span></span></code></pre> </figure> <p>Again, we have three unrelated outputs:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">3e54b5cd60ef78773dcf14c5f65ed593726a981f2c80045db7fac03015cc07ad </span></span><span class="line"><span class="cl">3c5b12ea6952714fed499796a743b103de97575fc938aab7d154cc6c605984a9 </span></span><span class="line"><span class="cl">706af798b32b12c9f508c16c3411b594227f79936a3cc521e6e1f362b1ef3a38</span></span></code></pre> </figure> <h2 id="sounds-cool-what-about-sequencemac">Sounds cool. What about SequenceMAC?</h2> <p>SequenceMAC works like SequenceHash, but with a 32-byte or longer key. As with SequenceHash, we can see that shifting the boundaries between our inputs leads to different results:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-py" data-lang="py"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">sequencehash</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">KEY</span> <span class="o">=</span> <span class="nb">bytes</span><span class="o">.</span><span class="n">fromhex</span><span class="p">(</span><span class="s2">"c5d6670f20adad622292a404dc5496cd6692fee636b5935a18451c985b7277bc9cacbc26e5473f85cfc6a64e96d0b98e7b9b604eaebc8899971e1a97dc3caa3a"</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">sequencehash</span><span class="o">.</span><span class="n">SequenceMAC</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">KEY</span><span class="p">,</span> <span class="n">digestmod</span><span class="o">=</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 1'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">result</span><span class="p">()</span><span class="o">.</span><span class="n">hex</span><span class="p">())</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">sequencehash</span><span class="o">.</span><span class="n">SequenceMAC</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">KEY</span><span class="p">,</span> <span class="n">digestmod</span><span class="o">=</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0Test 1'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">result</span><span class="p">()</span><span class="o">.</span><span class="n">hex</span><span class="p">())</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="n">hasher</span> <span class="o">=</span> <span class="n">sequencehash</span><span class="o">.</span><span class="n">SequenceMAC</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">KEY</span><span class="p">,</span> <span class="n">digestmod</span><span class="o">=</span><span class="s1">'sha256'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 0'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">''</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="n">hasher</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">b</span><span class="s1">'Test 1'</span><span class="p">)</span> </span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">hasher</span><span class="o">.</span><span class="n">result</span><span class="p">()</span><span class="o">.</span><span class="n">hex</span><span class="p">())</span></span></span></code></pre> </figure> <p>This gives us the following output:</p> <figure class="highlight"> <pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">9a24e4209dad98d2e1f1eecd62aa2908234f1eed2963395292fd9718129fe258 </span></span><span class="line"><span class="cl">4e4b71b8bb7b2c80e9f9ca89cb8bff43cd77cc5b530fc5f163069e5dda2876cb </span></span><span class="line"><span class="cl">6faf7818842f5a208dc306afe83ed7bea5b3fadc2a617c2208e836709f925889</span></span></code></pre> </figure> <p>Changing the key, or using <code>result_with_customizer</code> with different customization values, will also provide different outputs.</p> <h3 id="some-notes-on-key-size">Some notes on key size</h3> <p>One important point is that SequenceMAC has a <em>minimum</em> key size of 32 bytes (256 bits). Coupled with a good 256-bit hash function, this corresponds to about a 128-bit security level against forgery attacks. As with HMAC, key sizes should generally be at least as long as the output of the hash.</p> <p>Additionally, while SequenceMAC supports keys up to ${2}^{128}-1$ bytes in length, it’s important to remember that “longer key” is not the same as “higher security.” The underlying hash function and the key-preprocessing step (which hashes keys longer than the underlying hash function’s block size) impose a hard cap on the total security SequenceMAC can provide. Using keys longer than the length of the hash output is generally not a good idea.</p> <p>For hash functions with outputs smaller than 256 bits (such as SHA224 or RIPEMD160), the security level should be equal to about half the hash length (112 bits for SHA224 and 80 bits for RIPEMD160), which does not match the security of the minimum key size. While SequenceMAC can be used with such hash functions, the SequenceMAC specification only <em>prohibits</em> short keys and <em>strongly discourages</em> the use of hash functions with short outputs.</p> <h2 id="what-about-extensible-output-functions-xofs">What about extensible output functions (XOFs)?</h2> <p>Excellent question! We don’t have an answer yet!</p> <p>We haven’t specified SequenceXOF, but it’s definitely something we’re thinking about. Right now, XOFs aren’t as widely used as hashes, so the APIs are a little less stable. We want to proceed carefully to ensure we cover all the relevant use cases.</p> <h2 id="what-if-i-want-to-write-my-own-implementation">What if I want to write my own implementation?</h2> <p>We love to see high-quality implementations! There are many languages where someone might find SequenceHash and SequenceMAC useful, and there are certainly ways to customize the current APIs to better fit your needs!</p> <p>First, <a href="https://github.com/C2SP/C2SP/blob/main/sequencehash.md">check out the specification</a>. The document is kinda long, but the structure is straightforward. If you’ve implemented HMAC before, SequenceHash and SequenceMAC will feel like fancy versions of that.</p> <p>Second, if your target language is similar to Rust, Go, or Python, consider porting over our initial implementations. We’ve tried to keep these implementations as clean as we can, so they’re easy to audit and other cryptographers can learn from them.</p> <p>Finally, whatever you do, don’t forget to check your implementation against the <a href="https://github.com/C2SP/CCTV/tree/main/sequencehash">test vectors</a>. The test vectors aren’t simple known-answer tests, either: they include intermediate values that can be used to help debug and validate your implementation.</p> <h2 id="some-minor-caveats">Some minor caveats</h2> <p>SequenceHash provides for a specific set of needs: customization and domain separation, preventing length extension attacks where applicable, and—most importantly—ensuring that your inputs don’t get mixed together in a dangerous way. It’s a tool, not a panacea.</p> <p>You still need to make sure you’re hashing <em>the right</em> inputs. Being able to decode a value doesn’t mean that two pieces of software will encode that value in <em>the same way</em>, and that can lead to compatibility issues among different servers, clients, and libraries. JSON and XML, for instance, don’t always guarantee field orderings. Even for strings, it’s important to make sure you’re using a consistent encoding method (“all the world is ASCII” isn’t true and never has been).</p> <p>In the case of Fiat-Shamir transforms, you still have to be careful about <a href="https://eprint.iacr.org/2023/691">including <em>all</em> your inputs</a>. Schnorr proofs should always include the group descriptor (whether as individual values or named parameter sets), the generator element, etc. When the output is supposed to be interpreted as an integer modulo some other value, it’s also important to make sure that you select a hash with an output large enough to avoid modulo bias. Cryptography is subtle; there are always intricacies to consider.</p> <p>Still, as long as you’re careful to keep your inputs consistent and include all your values, SequenceHash and SequenceMAC make it easy to ensure nobody can pretend your inputs mean something other than what they’re supposed to mean.</p> <p>The specification is live at C2SP, and our Rust, Go, and Python implementations are ready to use today, with test vectors available if you want to write your own. Try it out and let us know what you think!</p> Sunrise - James' Coffee Blog https://jamesg.blog/2026/10/02/sunrise 2026-10-02T00:00:00.000Z James' Coffee Blog <p>At this time of year, the sun begins to rise around the time I wake up. This means I can see the colours of the sunrise; how the sunlight changes the sky. While autumn and winter can be cold, the colours bring the seasons to life. Lately, I have been motivated not only to start my day, but to start writing by the later-rising sun. <em>I can always write about the colours.</em></p> <p>Standing by the window, I started writing.</p> <p><em>When the sun first shines through the clouds and illuminates the tops of trees with a soft glow; small planes of light shine on the field nearby. The clouds in the other distance are glowing orange with a faint lavender; you can see the blue sky behind the light clouds. It is as if the world is saying hello.</em></p> <p>The soft yellow light cast on the fields and trees was short-lived, only present at precisely the moment when there must have been a gap between the light grey clouds, one allowing the intense light to shine in the glowing way that it does. I haven’t seen enough cloudy sunrises to know whether when the clouds are glowing it means the sun is rising over the horizon, or whether the sun has already risen. I have a feeling it may be the former; I will have to study more sunsets to know for sure. Writing this brought to mind the feeling of being up early on a trip three years ago; so magnetic in memory is bright energy.</p> <p>I am looking forward to the day ahead.</p> <script>(function(){function c(){var b=a.contentDocument||(a.contentWindow&&a.contentWindow.document);if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a4420a281bcfaa8f',t:'MTc5MDkyNjYyNA=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script> I Was a Guest on The Pen Addict - Robb Knight • Posts • Atom Feed https://rknight.me/blog/i-was-a-guest-on-the-pen-addict-736/ 2026-10-01T13:08:15.000Z Robb Knight <p>Brad is walking in Memphis this week for the <a href="https://www.youtube.com/live/y4PRZ4WanVI?si=tnMX2ZuL31LMfoCl">podcastathon</a> so we recorded this episode a couple of weeks ago.</p> <p>We talked about the incentives we're both offering for St Jude and the work that goes into those as well as my progress as an "artist", and <a href="https://jimothy.rknight.me">Jimothy</a>. Then we discussed finishing notebooks and inks, and finished off with <a href="https://rknight.me/blog/analog-defaults/">my analog defaults</a>. There's still a few days to <a href="/stjude">donate to St Jude</a>.</p> <p><a href="https://relay.fm/penaddict/689">Listen to The Pen Addict 736: I’ll Keep You All Knight</a></p> My Inktober Setup - Robb Knight • Posts • Atom Feed https://rknight.me/blog/my-inktober-setup/ 2026-10-01T12:41:59.000Z Robb Knight <p>It's <a href="https://inktober.com/">Inktober</a> again which means I'm drawing one thing a day, in ink, from the official<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup> prompt list. I'm tagging my posts with <a href="/blog/tags/inktober">#Inktober</a> and <a href="/blog/tags/inktober2026">#Inktober2026</a> — these tag pages are flagged to render the images in a gallery instead of the usual notes pages. My <a href="https://rknight.me/notes/202610010735/">first drawing is up</a> as of this morning.</p> <p>As much as I love Jeff the dinosaur from <a href="/blog/tags/inktober2025">last year</a><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup> it's too easy to fall back on "Jeff does/interacts with whatever the prompt is" so this year will be mostly Jeff-free. Last year my drawings were all over the place in terms of size so this year I bought a 12x12 Sakura sketchbook — I'll be using this exclusively for Inktober for the next few years. Unlike last year when I used Uni Pins, I'm a big Sakura Micron boy now. I talk more about this on <a href="https://relay.fm/penaddict/736">this week's episode of The Pen Addict</a> which will be out in a few hours.</p> <figure><img src="https://cdn.rknight.me/site/2026/inktober-setup.jpg" alt="A pink cutting board with a black square notebook on it. Next to it is a mechanical pencil with Pikachu on it and a Sakura micron fineliner" /><figcaption>I love my Pikachu Kuru Toga</figcaption></figure> <p>One of the things with projects like this is I want to be consistent with how I'm posting stuff. Last year I would have to go back to the previous days post to see if I did a full stop or colon after the day number, did I put the prompt in quotes, what about the filename? So I set up two Alfred snippets — one for the filename and one for the post itself. Snippets is a feature <a href="https://rknight.me/blog/snippets-i-use-regularly/">I use a lot</a> for other things.</p> <pre class="language-bash"><code class="language-bash"><span class="token comment"># INKtober Filename</span><br /><span class="token punctuation">;</span>inkf<br /><span class="token comment"># raw</span><br />inktober-2026-<span class="token punctuation">{</span>date:dd<span class="token punctuation">}</span>-<br /><span class="token comment"># becomes</span><br />inktober-2026-01-<br /><br /><span class="token comment"># INKtober Post</span><br /><span class="token punctuation">;</span>inkp<br /><span class="token comment"># raw</span><br />Day <span class="token punctuation">{</span>date:dd<span class="token punctuation">}</span> - <span class="token punctuation">{</span>cursor<span class="token punctuation">}</span><br /><br /><span class="token operator">!</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">(</span>https://cdn.rknight.me/site/2026/inktober-2026-<span class="token punctuation">{</span>date:dd<span class="token punctuation">}</span>-.jpg<span class="token punctuation">)</span><br /><span class="token comment">#becomes</span><br />Day 01 - <br /><br /><span class="token operator">!</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">(</span>https://cdn.rknight.me/site/2026/inktober-2026-01-.jpg<span class="token punctuation">)</span></code></pre> <hr class="footnotes-sep" /> <section class="footnotes"> <ol class="footnotes-list"> <li id="fn1" class="footnote-item"><p>I've heard some not great things about the official folks and "licensing" the name but nothing substantial so I'm sticking with it <a href="#fnref1" class="footnote-backref">⤾</a></p> </li> <li id="fn2" class="footnote-item"><p>And let's not even talk about <a href="https://rknight.me/blog/doodle-scan/">Knobgate</a> <a href="#fnref2" class="footnote-backref">⤾</a></p> </li> </ol> </section> I Don’t Remember the Last Time I Checked Mastodon - Kev Quirk https://kevquirk.com/i-dont-remember-the-last-time-i-checked-mastodon 2026-10-01T11:11:00.000Z Kev Quirk <p>My relationship with Mastodon has been somewhat tumultuous over the years, until I eventually <a href="https://kevquirk.com/goodbye-fosstodon">stepped down from Fosstodon</a> around 18 months ago. I have to say, it was the right decision. I don't miss running Fosstodon one bit.</p> <p>But since then, I've found myself less and less engaged in the Fediverse. Mainly because there's so much outrage over there. It's so tiring.</p> <p>The majority of my timeline is fun, but the outraged minority have ruined for me. To the point where I don't want to be there, and I'm much happier having not checked the timeline for the last month or so.</p> <p>I'm not off the Fedi, however. What I've done is build features into this site that allow me to automatically cross-post to the Fedi. I even have a custom page that only I can access, which allows me to create a note as simply as posting to Mastodon:</p> <p><img loading="lazy" src="https://kevquirk.com/content/images/i-dont-remember-the-last-time-i-checked-mastodon/social-page.webp" alt="social-page" /></p> <p>As well as this, I've <a href="https://docs.purecomments.org/changelog/#v1.7.0---07-september-2026" rel="noopener noreferrer">implemented Webmentions in Pure Comments</a> as of earlier this month. So I can reply to any comments from afar too.</p> <p>It's nice. I can see still engage with people on the Fedi, all while not having to put up with the checking the timelines.</p> <h2>What Now?</h2> <p>I have around 12,000 followers on <a href="https://fosstodon.org/@kev" rel="noopener noreferrer">my Mastodon account</a>. Because Mastodon <a href="https://kevquirk.com/ama-do-i-see-a-future-for-the-federated-web">really doesn't scale well</a>, those 12k followers take a fair amount of Fosstodon's resources. Which I don't think is fair if I'm not really using the service (I do donate every month).</p> <p>So I'm thinking about spinning up a single user <a href="https://gotosocial.org/" rel="noopener noreferrer">GoToSocial</a> instance that I can live on. That way I'm not using any of Fosstodon's resources and I can do my own thing, on my own server.</p> <p>I own <code>thefedi.uk</code> and <code>thefediverse.uk</code> so something like <code>@kev@thefedi.uk</code> would be quite cool, I think. I could even provide accounts to friends in the future then too. On the other hand, I'm not sure I want the headache of managing a federated server again.</p> <p>Maybe I should stop overthinking it and just stay on Fosstodon. What would you do in my position?</p> <div class="email-hidden"> <hr /> <p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p> <p>You can <a href="mailto:19gy@qrk.one?subject=I%20Don%E2%80%99t%20Remember%20the%20Last%20Time%20I%20Checked%20Mastodon">reply to this post by email</a>, or <a href="https://kevquirk.com/i-dont-remember-the-last-time-i-checked-mastodon#comments">leave a comment</a>.</p> </div> 2026-10-01 10:35: This site is the most fun I've had in a while. Destroy any website! https://destroy.spritefusion.com/ - Kev Quirk https://kevquirk.com/2026-10-01-1035 2026-10-01T09:35:00.000Z Kev Quirk <p>This site is the most fun I've had in a while. Destroy any website!</p> <p><a href="https://destroy.spritefusion.com/" rel="noopener noreferrer">https://destroy.spritefusion.com/</a></p> <div class="email-hidden"> <hr /> <p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p> <p>You can <a href="mailto:19gy@qrk.one?subject=2026-10-01%2010%3A35">reply to this post by email</a>, or <a href="https://kevquirk.com/2026-10-01-1035#comments">leave a comment</a>.</p> </div> IndieWeb Fiction Carnival September 2026 - Moonlight - Joel's Log Files https://joelchrono.xyz/blog/fiction-carnival 2026-10-01T04:55:00.000Z joelchrono <p>Here is my late entry for the IndieWeb Fiction Carnival for September!</p> <p>The theme was: <strong>Moonlight</strong>, hosted by <a href="https://jamesg.blog/2026/09/01/iwfc-moonlight">James.</a></p> <h2 id="we-are-always-three">We are always three</h2> <p>I was told about the astral bodies in the sky, of how the darkness used to be full of dots of light. I don’t understand the stories, there is no sky outside.</p> <p>We are going to a new sun now, Dad says this one is younger, but still older than me! The other one was the moon, a big rock that shone at night, how can it be dark when there’s a light above?</p> <p>We used to be able to find all sorts of things in the feeds, like shows and cartoons, but storage is needed for new planet stuff, and some of the archives had to be taken out… Mom saved a couple of them locally though.</p> <p>Some were shows by magicians, my favorite ones. They could multiply, or change, or make objects dissapear! With a wave of the hand or under a cloth, Dad told me it’s “sleight of hand”, I can’t figure it out.</p> <p>The man was wearing some weird suit, in the middle of a table, the expectator had colorful clothes and her hair was long, he was a little bald. We cut ours to keep the place tidy. Maybe hygiene wasn’t too important back then?</p> <p>He took three little pieces of bread, put two of them inside a tea cup, flicked the last one towards the audience, and started to talk about an ancient poet.</p> <p>The man let the cup spill on the mat, the three balls of bread rolled out from it…</p> <p>He shared a poem while he did it again…</p> <blockquote> <p>Once the party is over, <br /> the guests have to leave. <br /> I don’t know that sadness.</p> <p>As I walk back home,<br /> we are always three:<br /> The moon is my partner,<br /> my shadow follows suit.</p> </blockquote> <p>Once our trip is over, us passengers have to leave, I look forward for that day.</p> <p>I will have a new home, friends to play with, a new moon above me, and a shadow to follow me!</p> <h2 id="afterword">Afterword</h2> <p>Well, I rarely do fiction! This is definitely a first for the blog, but I wanted to try my hand at it. Where does this come from? Why do I write about it? Feel free to share your thoughts before reading this, or afterwards too, hehe.</p> <p>Well, first, I wanted to try doing this for the sake of it. I enjoyed the theme and wanted to explore it.</p> <p>At first I thought about writing from the point of the view of a certain character from <a href="/blog/outer-wilds/">Outer Wilds</a>, but I won’t share much spoilers about that game or the context of all that. Play it yourself, please.</p> <p>Anyway, I also wanted to write from the perspective of a kid with an untainted sense of wonder. I had read some fiction like <em>Strange Dogs</em> by James S.A. Corey, and of course, <em>The Indomitable Captain Holli</em> by . Completely different stories, but both from the perspective of kids who are yet to understand the world. I thought I could try it out. My inner child is still alive and kicking but maybe I used a couple terms that were too much? Like, “storage”?</p> <p>And of course, the magic. This talks about a real magician doing a real performance, the wonderful René Lavand is one of my main inspirations in close-up magic. His presentation was absolutely unique. Poetry, classical music, and an elegant presence at the table—performing all of his illusions with a single hand.</p> <p>The effect can be seen <a href="https://youtu.be/eL7VKEkpXhg">on YouTube</a> but the language is in Spanish. I did my best to translate the main lines of the here, it still doesn’t compare to the original which is a bit longer.</p> <p>I hope you enjoyed this little piece of fiction, perhaps I’ll try some more.</p> <p>This is day 45 of <a href="https://100DaysToOffload.com">#100DaysToOffload</a></p> <p> <a href="mailto:me@joelchrono.xyz?subject=IndieWeb Fiction Carnival September 2026 - Moonlight">Reply to this post via email</a> | <a href="https://fosstodon.org/@joel/117366495373879933">Reply on Fediverse</a> </p> AI as trebuchet - destructured https://destructured.net/ai-as-trebuchet 2026-10-01T04:00:00.000Z destructured <p>By now, you’ve no doubt heard reports of rogue AI escaping containment and performing tasks they shouldn’t have, like the time <a href="https://www.wired.com/story/openai-models-escaped-containment-and-hacked-huggingface/">OpenAI hacked Hugging Face</a>. How do these escapes occur? My understanding is that LLM-type AI uses statistical data about past sequences to predict what should appear next in the sequence, and if you give them a prompt that points them down a given sequence, there’s a good chance they’ll follow through on that sequence, even if you’ve tried to steer them away from certain outcomes, because following the probabilities provided by their training is the closest they can get to deciding anything.</p> <p>That is to say: They’re escaping containment the same way a boulder escapes a trebuchet.</p> <p>In fact, “siege engine” may be a solid metaphor for conceptualizing LLMs in general. Training a model is a process of feeding huge amounts of linguistic material into the system, which it then breaks down into “tokens,” analyzing the relationships that connect them in order to produce a set of statistics about how often one token follows another. Those statistics result in a kind of map of the probabilities inherent in the entire model. In principle, it would be possible to represent that map as a multi-dimensional grid of linguistic tokens ordered by their probabilistic relationships to one another.</p> <p>Just as a trebuchet is a physical structure that harnesses kinetic energy to direct a mass along a desired trajectory, you can conceptualize an LLM as a system for plotting trajectories through linguistic probability space of the model. When you prompt the LLM it uses those probabilities to chart a path through that space. If you’ve fed it Hamlet, then “Though this be madness, yet there is method in’t” is one such path. And if you give it a prompt that leads along that path, it will tend to produce Hamlet.</p> <p>The metaphor isn’t perfect, of course — no metaphor is — and actually representing training in a visual grid like that may not be feasible, but the benefit to reducing LLMs to a physical metaphor is that it helps you avoid anthropomorphizing them unnecessarily. It lets you look past the illusion of coherent thought and see them as machines for drawing consistent lines along trajectories set by historical linguistic examples. It’s a complicated and clever system, but it’s not agency.</p> <p>Siege engines aren’t just about moving mass, of course; the purpose of tossing boulders is to knock down walls. Similarly, LLMs aren’t just about tracing lines through a statistical map of linguistic relations, but about overcoming some obstacle by means of that trajectory. In a way, they’re also designed to knock down walls — it’s just that most of the walls they target are psychological.</p> Expanding my music pipeline - Posts feed https://www.coryd.dev/posts/2026/expanding-my-music-pipeline 2026-09-30T21:19:00.000Z Posts feed <div class="e-content block-subcanvas"><p><a href="https://www.coryd.dev/posts/2024/building-a-scrobbler-using-plex-webhooks-edge-functions-and-blob-storage">I've</a> <a href="https://www.coryd.dev/snippets/navidrome-scrobbling-plugin-2026-02-18-15-37-35">written</a> <a href="https://www.coryd.dev/posts/2025/evolving-my-personal-music-scrobbler">at</a> <a href="https://www.coryd.dev/posts/2024/improving-my-self-hosted-scrobbling-implementation">length</a> <a href="https://www.coryd.dev/posts/2025/tracking-listens-from-navidrome">about</a> <a href="https://www.coryd.dev/posts/2026/building-a-navidrome-scrobbling-plugin">my</a> scrobbling implementation on my site. Until now I'd managed the metadata for my music manually, editing it on macOS before adding it to <a href="https://www.navidrome.org/">Navidrome</a>. That gave me direct control, ate time and came with quite a bit of tedium.</p> <p>I'd seen <a href="https://beets.io">beets</a> mentioned a few times as a tool to programmatically manage and apply metadata. I've wanted to use it, but cutting over a collection with nearly 800 artists and over 5,000 albums was a lot. But, as with most bad ideas I have, this one stuck with me.</p> <p>One habit I'd gotten into while managing music was to assign splits to a single artist. If I had both artists in my collection, I'd split them into two albums, one for each artist. For collaborative albums I'd have either a unique artist for the collaboration or (incorrectly) assign it to whichever artist I preferred.</p> <p>Fixing this meant, for starters, a database migration. My schema supported only a 1:1 relationship between artists and albums. Now an album like <em><a href="https://www.coryd.dev/music/albums/splits/full-of-hell-nothing/when-no-birds-sang">When No Birds Sang</a></em> can be properly associated with both <a href="https://www.coryd.dev/music/artists/nothing-united-states">Nothing</a> and <a href="https://www.coryd.dev/music/artists/full-of-hell-united-states">Full of Hell</a>. So I have artists in my Navidrome library whose only release is a split for which I may or may not have included their tracks—this makes my teeth itch, but I can live with it. I can't do anything about these artists in Navidrome, but I've filled out the album data on my site with ghost tracks. I pull the full tracklist from MusicBrainz to populate these releases and highlight them as missing.</p> <aside> <p>Listens on collaboration albums have one primary artist assigned. The other artist's page shows those listens separately. Counting the listens in both totals would inflate my overall play counts.</p> </aside> <figure class="drawing"><button type="button" class="lightbox-trigger bare" data-lightbox="lb-a9ce532" aria-haspopup="dialog"><img src="https://cdn.coryd.dev/music-pipeline-svg-f5f8d3c9.svg" alt="Diagram of the music pipeline between coryd.dev and my Navidrome server. 1: an album uploaded in Library's Inbox goes to an S3 inbox, which the server pulls; beets matches and tags it, or provides options if a match isn't exact. The server converts FLAC to MP3 for Navidrome and sends the originals to an archive. Then, the retag batch rewrites existing tags based on decisions and tag edits from Library's Retag tab. 2: the site syncs artists, albums and tracks from Navidrome by ID, nightly or manually. 3: Navidrome's plugin sends scrobbles, which resolve by track ID. MusicBrainz sends ghost tracks to the site." width="874" height="606" loading="lazy"/></button><dialog id="lb-a9ce532" class="lightbox-dialog" aria-label="Diagram of the music pipeline between coryd.dev and my Navidrome server. 1: an album uploaded in Library's Inbox goes to an S3 inbox, which the server pulls; beets matches and tags it, or provides options if a match isn't exact. The server converts FLAC to MP3 for Navidrome and sends the originals to an archive. Then, the retag batch rewrites existing tags based on decisions and tag edits from Library's Retag tab. 2: the site syncs artists, albums and tracks from Navidrome by ID, nightly or manually. 3: Navidrome's plugin sends scrobbles, which resolve by track ID. MusicBrainz sends ghost tracks to the site."><img src="https://cdn.coryd.dev/music-pipeline-svg-f5f8d3c9.svg" alt="Diagram of the music pipeline between coryd.dev and my Navidrome server. 1: an album uploaded in Library's Inbox goes to an S3 inbox, which the server pulls; beets matches and tags it, or provides options if a match isn't exact. The server converts FLAC to MP3 for Navidrome and sends the originals to an archive. Then, the retag batch rewrites existing tags based on decisions and tag edits from Library's Retag tab. 2: the site syncs artists, albums and tracks from Navidrome by ID, nightly or manually. 3: Navidrome's plugin sends scrobbles, which resolve by track ID. MusicBrainz sends ghost tracks to the site." width="874" height="606" loading="lazy"/><div class="lightbox-chrome"><div class="lightbox-chrome-group"><button type="button" class="lightbox-close lightbox-chrome-btn" aria-label="Close"></button></div></div></dialog><figcaption>Diagram of the music pipeline between coryd.dev and my Navidrome server. 1: an album uploaded in Library's Inbox goes to an S3 inbox, which the server pulls; beets matches and tags it, or provides options if a match isn't exact. The server converts FLAC to MP3 for Navidrome and sends the originals to an archive. Then, the retag batch rewrites existing tags based on decisions and tag edits from Library's Retag tab. 2: the site syncs artists, albums and tracks from Navidrome by ID, nightly or manually. 3: Navidrome's plugin sends scrobbles, which resolve by track ID. MusicBrainz sends ghost tracks to the site.</figcaption></figure><h1 id="connecting-things">Connecting things</h1> <p>My music files sit in Navidrome, my listening data and scrobbles sit in my site's database. Scrobbles are sent from the former to the latter. Previously, I'd matched listens based on name alone. I've updated my artist, album and track schema to store their respective Navidrome IDs. For about 90% of my library, Navidrome derives that ID from the release's MusicBrainz ID and the rest are built from the tags.</p> <h1 id="aligning-metadata">Aligning metadata</h1> <p>I've added a <code>Library</code> section to the music portion of my custom CMS.<sup id="fnref:1" class="footnote-ref">1</sup> There are <code>Inbox</code>, <code>Sync</code> and <code>Retag</code> tabs. New music is uploaded in the <code>Inbox</code> tab. It's routed to an inbox directory on my Navidrome server. A scan is run against the inbox content. Exact matches are applied automatically; otherwise I pick from a list of likely releases. Once a release is picked, the album is tagged and scanned into Navidrome.</p> <p>Once Navidrome has picked up the album, I move to the <code>Sync</code> tab and run a check job which looks for an existing match in my site's database. If there's no existing record and no errors from the check job, I can sync the new release to my site. Plays are then tied to the album by ID.</p> <p>The <code>Retag</code> tab is where I manage music metadata. When I initially moved my tag management to beets, I spent much of my time here. The actual music scans run on my Navidrome server and report matches and misses back. Artists that need attention are flagged here for me to review. Again, with hundreds of artists and thousands of albums, <em>this took a while</em>. If I want to change the match for an album, I can revert to the previously selected release or edit the metadata manually. If I edit the album record, I can choose to write the edits to the tags on the audio and, when the tags are rewritten, I sync the updates back to my site.</p> <h1 id="edge-cases">Edge cases</h1> <p>Before storing IDs with albums, I'd hit edge cases when scrobbling plays for artists who had multiple albums with the same title (looking at you <a href="https://www.coryd.dev/music/artists/american-football-united-states">American Football</a>). This generally worked in practice, but the absence of mismatches was more luck than proper implementation. Now, if a scrobble arrives without an ID and its title matches none of the artist's albums, or more than one, the site creates a new record I can merge into the right one.</p> <hr/> <p>This was one of those projects with a ton of up-front work that should pay off over time. Previously, everything I added I would download, tag manually, upload to the S3 bucket where I keep my music using rclone, and then it would get backed up to an archive, scanned in and synced. Now, I upload FLAC files once, beets tags them, converts them to MP3 and imports them, then copies the originals to my archive. I tend to run metadata syncs manually when I import or retag something, but those run nightly as well. Imports are easier, tags are correct and scrobbles are more reliable.</p> <div class="footnotes" role="doc-endnotes"><hr/><ol><li id="fn:1"><p>More on this eventually. ↩︎</p> </li></ol></div></div> One Year - Kev Quirk https://kevquirk.com/one-year-lisa 2026-09-30T13:25:00.000Z Kev Quirk <p>Today marks a year since my little sister, Lisa, took her own life. She was 34.</p> <p>It was an overdose, but we don't know if it was an accident or suicide. We’ll never get an answer, yet I lean toward believing it was by choice. As grim as it sounds, picturing her with some control over the end brings me a small measure of peace.</p> <p>I still think about her every day, and I still get upset regularly. Especially when I've been to visit my nephew and I see the sadness in his eyes.</p> <p>At first I was angry at the selfishness of it all, but I think that's gone now. These days I'm just sad.</p> <p>Mum blames herself, and has asked me numerous times where she went wrong. I never have an answer for that. What can I say? <em>"Well the rest of us turned out ok, Mum. So you did fine.</em>" That feels dismissive of her emotions. So I just give her a sad smile and ask her to not think those things.</p> <p>I miss her. I miss her laugh and dry sense of humour. I miss how she would <em>always</em> call people on their bullshit. Never afraid of speaking up.</p> <p>Hopefully next year it will be a little less raw...</p> <div class="email-hidden"> <hr /> <p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p> <p>You can <a href="mailto:19gy@qrk.one?subject=One%20Year">reply to this post by email</a>, or <a href="https://kevquirk.com/one-year-lisa#comments">leave a comment</a>.</p> </div> Are you a smartwatch "power user"? - Terence Eden’s Blog https://shkspr.mobi/blog/?p=74267 2026-09-30T11:34:26.000Z Terence Eden’s Blog <p>What do you use your smartwatch for?</p> <p>A few weeks ago, I overheard a conversation between someone on the Pixel Watch team and a woman I know. He was quizzing her at a party about her Pixel watch and what features she used. He'd ignored me when I said I had <a href="https://shkspr.mobi/blog/2025/08/i-bought-a-16-smartwatch-just-because-it-used-usb-c/">a non-Google watch</a>. She thought for a moment and said, other than telling the time, all she used were pretty much the step counter and contactless payments. He looked a bit crestfallen at his impromptu user-research participant and somewhat dismissively sneered, "Well, you're not exactly a power user, are you?"</p> <!-- 👋👋👋👋👋👋👋👋👋 Welcome to Comment Club! This content is only available to people who read my HTML comments. Honestly, this guy was *such* an arse. Really spoiled an otherwise lovely party. Like, I don't mind talking about people's work - but it seemed that was the only thing he was interested in talking about. He also seemed genuinely offended that I'd bought a non-Google watch and didn't want to hear why I liked it. Oh well, his loss! OK, the three rules of comment club are… 1. You must not tell anyone about Comment Club - let them find out about it themselves. 2. You *must* add some Comment Club Content to at least one of your blog posts. Doesn't have to be much, just a little note will do. 3. You should drop an email to anyone whose comments you've read. Start by sending me a friendly message at comment.club@shkspr.mobi Keep looking out for more comments in future blog posts 😃 TTFN. --> <p>I'm trying to imagine what being a "power user" of a watch is like. Can anyone enlighten me?</p> <p>I think smart-watches are much like Alexa. What the user <em>wants</em> to do with it is almost totally at odds with what the company is selling. Alexæ are mostly kitchen timers, song players, and light switches. No one is a "power user" constantly installing skills and using it for anything which increases the product team's engagement metrics.</p> <p>The same is probably true of watches. Alerts are nifty - but cumbersome for replies. The health stuff is useful - but only for a subset of users. Seeing the time is great - but if the battery lasts less than a week, who wants to keep that screen on?</p> <p>People use watches because they are moderately more convenient to carry than the giant phones we have nowadays.</p> <p>Back when mobile phones were new, exciting, and made a feature of being tiny, I was working for a network operator and trying to come up with reasons for people to use our brand-new 3G network. All the research we had showed that people used their phones for exactly three things:</p> <ol> <li>Voice calls</li> <li>Text messages</li> <li>A third thing</li> </ol> <p>That "3rd thing" was varied. For some it was playing snake, for others it was a calendar, and a few took photos. But almost no-one used their phone beyond the basics. They weren't investigating the sub-menus, nor were they using most of their device's capability unless it was heavily advertised to them (ringtones, basically).</p> <p>It took the industry a <em>huge</em> amount of effort to get people to actually use their phones for more than calls and texts. Part of that was bigger screens with enticing icons (<a href="https://shkspr.mobi/blog/2012/04/give-customers-an-elevator-pitch-for-your-app/">although users will always be reluctant to click mysterious icons</a>). Another part was that phones became genuinely useful. But perhaps the biggest change, I think, is that phones became <em>easy to use</em>.</p> <p>Watches have tiny screens. You can only get a few words of a message on there. Icons are tiny and hard to reliably tap. Swiping away at your wrist or fiddling with a crown is a faff. Talking into your wrist makes you look like a prat. Interacting with a smartwatch is <strong>annoying</strong>. Why would anyone want to spend more time using it than is strictly necessary?</p> <p>I'm sure there are some people out there browsing the web on their wrist, and sending endless voice-notes to their AI assistant, and setting up complex travel plans by tapping their nose on the screen, and installing new watch faces which always point to the nearest Dignitas clinic, and seeing what their heart-rate did during that last run, and tracking whether their menstrual cycle is synced to the phases of the moon, and hoping that tripping on the stairs didn't send an alert to the emergency services, and whatever else the team has cooked up to show that they're still innovating.</p> <p>But I'll bet those "power users" are vastly outnumbered by people who are using a smartwatch for the limited set of actions which are useful to them; not to the manufacturer.</p> <p>Perhaps the real power users have is the power to use a device on their own terms?</p> <img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=74267&HTTP_REFERER=Atom" alt width="1" height="1" loading="eager"> Negotiating the burden - destructured https://destructured.net/negotiating-the-burden 2026-09-30T04:00:00.000Z destructured <p>FOSS communities are currently undergoing a series of minor crises around the questions of what extent to accept LLM-generated contributions, and how to respond to would-be contributors who feel that a given policy (or lack thereof) unfairly impacts their ability and/or desire to contribute. As far as I can tell, the projects and orgs that institute decisive, clearcut policies <em>against</em> generative AI contributions rarely, if ever, receive anywhere near as much blowback or debate as those that try to stake some nuanced middle position, but projects nonetheless keep attempting to thread the needle. That predictably leads to disputes like the one that apparently flared-up around the game engine project Bevy, <a href="https:// blog.fallible.net/it-breaks-a-village/">as chronicled here</a>.</p> <p>On that account, part of the dispute centered on the issue of how to deal with cases that <em>appear</em> to violate a policy limiting LLM contributions, but that aren’t demonstrably LLM-generated. Does the contributor merit the benefit of the doubt? Or should any plausible accusation trigger closer scrutiny of the contribution? Recourse was quickly made to judicial metaphor:</p> <blockquote> <p>The burden of proof from this angle unfairly rested on an ‘accuser’, not ‘the accused’. This mirrors many justice systems, but a PR being rejected is not equivalent to imprisonment or a fine or death.</p> </blockquote> <p>That’s true, but the accuser/accused analogy is wrong not only as a matter of degree, but also as a category error. Judicial burden of proof is a principle for mitigating the potential harms of laws that are compulsory on a population. With software contributions, though, we’re talking not about a population bound by the laws imposed on them as an accident of geography or birth, but rather about candidates for inclusion in a social group — more like PhD candidates than courtroom defendants. As with PhD candidates, it’s entirely reasonable for the candidate to bear a burden for proving the suitability of their contribution.</p> <p>It’s also reasonable to expect these disputes to continue so long as projects attempt to stake out some purported “middle ground” on generative AI. The disputes are as logical as they are irresolvable. “No AI” is a clear policy signaling that the project will continue to operate as it did before. Anything else will be some variation on “AI will be accepted, subject to reasonable checks.” Those checks necessarily translate into more work for someone. The LLM-assisted contributors won’t be satisfied with such a policy because mitigating work was the point of bringing in AI tools in the first place. And non-users won’t be satisfied because now they’re responsible for making sure that work gets done.</p> <p>“No” remains the most reasonably policy.</p> SBS Zoom sessions cancelled - Johnny.Decimal https://johnnydecimal.com/blog/0253-sbs-zoom-cancelled/ 2026-09-30T02:16:53.000Z Johnny.Decimal <p>We've cancelled the Small Business System fortnightly Zoom sessions. Attendance was sparse, and for something that took so much mental energy they weren't earning their keep.</p> <p>If you're an SBS member you can always book a 1:1 session with me. <a href="mailto:hello@johnnydecimal.com">Email me</a> for the link to my calendar.</p> <p>I haven't given up on the idea of open/public Zoom sessions. We've tried a few formats over the years and nothing's quite stuck. We'll continue to experiment.</p> here, something - James' Coffee Blog https://jamesg.blog/2026/09/30/here-something 2026-09-30T00:00:00.000Z James' Coffee Blog <p>In Distance there is the sight of everything; here there is the presence of something.</p> <script>(function(){function c(){var b=a.contentDocument||(a.contentWindow&&a.contentWindow.document);if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a436283b79df60a9',t:'MTc5MDgwMjAyNg=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>