Shellsharks Blogroll - BlogFlock 2026-05-23T22:54:36.025Z BlogFlock Adepts of 0xCC, destructured, fLaMEd, Trail of Bits Blog, Aaron Parecki, James' Coffee Blog, gynvael.coldwind//vx.log (pl), Westenberg, joelchrono, Evan Boehs, cool-as-heck, Kev Quirk, Posts feed, Sophie Koonin, cmdr-nova@internet:~$, <span>Songs</span> on the Security of Networks, Werd I/O, Johnny.Decimal, Robb Knight, Molly White, Hey, it's Jason!, Terence Eden’s Blog Using Fountain Pens for Note Writing - Kev Quirk https://kevquirk.com/using-fountain-pens-for-note-writing 2026-05-23T13:44:00.000Z <p>My note taking process has evolved a lot over the years. Originally I used my iPad with the Apple pencil, but having to charge it every few days was a pain. Then I switched to the <a href="https://kevquirk.com/remarkable-2-thoughts">Remarkable 2</a>, which was great and I didn't need to charge the pen. But as I produced more and more notes, it became awkward to search for them. Unfortunately, handwriting to text, and handwriting search both require a monthly subscription.</p> <p>Screw that.</p> <p>So I switched to the <a href="https://supernote.com/products/supernote-nomad">Supernote Nomad</a>, which (in my opinion) has better tooling for finding notes than the Remarkable. I mentioned this in my <a href="https://kevquirk.com/how-do-you-take-notes">how do you take notes</a> post. I <a href="https://kevquirk.com/follow-up-on-notes">created a new system</a> for taking notes, and it worked well. It still had it's frustrations, but I could generally find what I was looking for on the Nomad.</p> <p>Then I started writing the occasional journal entry, and for that I decided I needed a physical book and fountain pen. I don't know why, it just felt more personal and more permanent doing it that way. Being left-handed, fountain pens can be difficult, so I got myself a <a href="https://www.lamy.com/en-gb/p/lamy-safari-fountain-pen">Lamy Safari</a> with a left-handed nib.</p> <p>It writes lovely, especially for the ~£25 ($30) price. So I got myself another one and put red ink in so I can "highlight" certain notes in my journal. It is a <em>really</em> nice experience, and as my journal entries mount up, I can easily flip between pages.</p> <p>And then it dawned on me...it's not the technology that I'm using for notes that's the problem. It's the fact that I'm <em>using technology</em> in the first place!</p> <h2>Going analogue</h2> <p>As a test, I dug out an old notebook that we got a freebie from work (it's a really nice one - I figured nice paper would help) and started using my Lamy for note taking in work too.</p> <p>Using a slightly adapted version of my note taking system, it's been glorious! Flipping back through physical pages and <em>easily</em> finding my notes for a particular day has been very refreshing. Everything is in my notebook now, and I rarely use OneNote as a result.</p> <p>I decided to go all in, I sold my Nomad back in January and haven't looked back since.</p> <h2>Pen upgrade</h2> <p>The Lamy is a nice pen, but I wanted something a bit more substantial (and made of metal) as the pen gets a lot of punishment being bashed around in my bag all day. I was happy to spend more money, but didn't want to go crazy, so I ended up buying a <a href="https://www.kaweco-pen.com/en/Kaweco-AL-SPORT-Fountain-Pen-Stonewashed-Blue-M/10000734/">Kaweco AL Sport</a> in a lovely stonewashed blue colour.</p> <p>Unfortunately Kaweco don't offer a specific left-handed nib, but I've found it to be nicer to write with than the Lamy anyway. It doesn't scratch as much - not that the Lamy is particularly scratchy, but the Kaweco is soooo smooth.</p> <p><img src="https://kevquirk.com/content/images/using-fountain-pens-for-note-writing/pens.webp" alt="Pens" /></p> <h2>So what was the problem with the tablets?</h2> <p>I realised that my main frustration with both the Nomad and the Remarkable is that there's a 1-2 second delay on <em>every</em> screen change, so if I need to flip back 10 pages, that's like half a minute of pissing about.</p> <p>Half a minute doesn't sound like a lot, but I can flip back 10, or even a hundred pages in my notebook in a second. It just feels smoother.</p> <h2>Final thoughts</h2> <p>My note taking system now surrounds the specific paper I have in this fancy notebook from work (wide ruled lines, and a side margin) and I can't find anything else that's the same. Everything I find is either shitty quality paper, narrower lines, or no margin.</p> <p>Luckily for me, I've been able to find some spares hang around the office, so I have a cache of half a dozen or so, which should last me a few years.</p> <p>I'm totally converted to analogue note taking at this point, and I really enjoy the process of writing with the fountain pens. I just need to force myself not succumb to my constant desire to start collecting things - as I don't need 50 fountain pens, just like I don't need 50 watches...<a href="https://kevquirk.com/i-m-selling-most-of-my-watches">but I have them</a>!</p> <p>This post kinda went all over the place, sorry about that. 🤷🏻‍♂️</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=Using%20Fountain%20Pens%20for%20Note%20Writing">reply to this post by email</a>, or <a href="https://kevquirk.com/using-fountain-pens-for-note-writing#comments">leave a comment</a>.</p> </div> Which age-gates should be skill-gates and vice-versa? - Terence Eden’s Blog https://shkspr.mobi/blog/?p=68406 2026-05-23T11:34:31.000Z <p>In the UK, <a href="https://www.gov.uk/alcohol-young-people-law">it is illegal to buy alcohol if you are under 18</a>.</p> <p>Similarly, in most countries, you cannot vote until you have reached a specific age.</p> <p>These are age-gates. You do not need to prove your competence to drink, vote, smoke, or get married; you just need to be old enough.</p> <p>Some things have skill-gates. If you want an amateur radio licence in the UK, you need to pass an exam. You can be any age<sup id="fnref:age"><a href="https://shkspr.mobi/blog/2026/05/which-age-gates-should-be-skill-gates-and-vice-versa/#fn:age" class="footnote-ref" title="OK, realistically you have to be old enough to read, write, and communicate. But there's no legal barrier to a precocious 3 year old taking and passing the exams." role="doc-noteref">0</a></sup>.</p> <p>Similarly, most jurisdictions allow you to get a medical licence once you have passed the requisite tests<sup id="fnref:doogie"><a href="https://shkspr.mobi/blog/2026/05/which-age-gates-should-be-skill-gates-and-vice-versa/#fn:doogie" class="footnote-ref" title="As seen in the insightful documentary series &quot;Doogie Howser, M.D.&quot;" role="doc-noteref">1</a></sup>.</p> <p>There are also activities which are dual-gated. You can only get a driving licence after passing a test, but you can only apply to take the test once you are a certain age.</p> <p>Where should society swap age-gates and skill-gates?</p> <p>Perhaps the big one is voting. The <a href="https://www.gov.uk/government/publications/representation-of-the-people-bill-policy-summaries/votes-at-16">UK is preparing to extend the franchise to all 16 and 17 year olds</a> - but why is there an age-gate at all?</p> <p>Children are affected by politics, they pay tax on the goods they buy, they exist in the world. Why shouldn't they vote?</p> <p>The <a href="https://shkspr.mobi/blog/2013/01/votes-for-children/">usual argument is that they are too immature</a>. But maturity isn't dependent on age. Idiots are allowed to vote. Centenarians with no stake in the consequences of their politics are allowed to vote. People who don't understand what powers a government has are allowed to vote.</p> <p>Would it <em>really</em> be so bad to introduce a voting licence? Make people take a short quiz to ensure they understand what they're voting for and why they're voting. Perhaps there are concerns about disenfranchising eligible adults (but not mature children) or that the state will rig the test (when they could rig the election) or whatever. But if we're sticking with the fiction that some people aren't mature enough to vote then we <em>must</em> give disenfranchised people a chance to prove their maturity.</p> <p>You could make the same argument about driving. If a 7 year old is able to demonstrate mastery and control of a vehicle, are they likely to be a better driver than a 90 year old who has never taken a modern test?</p> <p>Alcohol is different. We realise that the drug is harmful and <em>especially</em> harmful to developing humans. So we age-gate it. But do people really understand the health risks? Should you have to pass a test in order to imbibe? We make the people selling alcohol pass somewhat rigorous skills assessments. Perhaps the burden of proof should be reversed?</p> <h2 id="wait-do-you-really-believe-all-this"><a href="https://shkspr.mobi/blog/2026/05/which-age-gates-should-be-skill-gates-and-vice-versa/#wait-do-you-really-believe-all-this">Wait, do you really believe all this?</a></h2> <p>No, not necessarily.</p> <p>I find it fascinating that different cultures set different limits on people's activities. I wouldn't like to live somewhere that allowed anyone to drive on the public roads. Similarly, I don't particularly want governments restricting who can vote based on an arbitrary assessment.</p> <p>But where are the limits? Why is the <a href="https://en.wikipedia.org/wiki/List_of_minimum_driving_ages">legal driving age so variable</a>? Why are some <a href="https://www.jalopnik.com/1988281/hardest-easiest-countries-to-get-drivers-license/">driving tests easier than others</a>?</p> <p>Do you want a teenage doctor diagnosing you - even if they are legally certified? Should you be able to use a radio without passing a test if you're a legal adult?</p> <p>Which age-gates and skill-gates do <em>you</em> think should be flipped?</p> <div id="footnotes" role="doc-endnotes"> <hr aria-label="Footnotes"> <ol start="0"> <li id="fn:age"> <p>OK, realistically you have to be old enough to read, write, and communicate. But there's no legal barrier to a precocious 3 year old taking and passing the exams.&nbsp;<a href="https://shkspr.mobi/blog/2026/05/which-age-gates-should-be-skill-gates-and-vice-versa/#fnref:age" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> <li id="fn:doogie"> <p>As seen in the insightful documentary series "Doogie Howser, M.D."&nbsp;<a href="https://shkspr.mobi/blog/2026/05/which-age-gates-should-be-skill-gates-and-vice-versa/#fnref:doogie" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> <img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=68406&HTTP_REFERER=Atom" alt width="1" height="1" loading="eager"> Riding a bike - Joel's Log Files https://joelchrono.xyz/blog/riding-a-bike 2026-05-23T03:49:26.000Z <p>So I got my bicycle from the shop and used it to return home!</p> <p>That first trip was definitely an experience. I had never rode a bicycle on the road alongside other moving vehicles. When I was a child I had a rather big patio, and even though I went through the streets a few times, there were not a lot of cars—I didn’t live in a busy place.</p> <p>Going from there to riding in the middle of downtown traffic afte almost ten years was definitely a change of pace.</p> <p>Not to worry though. I live in a pretty small city, which is alos quite used to motorcycles and bikes as part of traffic.</p> <p>The one who wasn’t used to such things was me of course, so when I tried to get ahead of a car by going on the sidewalk and realized there was no ramp ahead to return to the street, I ended up braking rather carelessly, the momentum carried me forward and well, that hurt.</p> <p>Alas, the traffic was slow so there was no real danger, I got back on track and pedaled away. The rest of the trip was painless! although my saddle was misaligned and I didn’t bother to correct it until I got home. I avoided big streets for the most part and everything was fine.</p> <p>For a couple of days I resigned myself to cycling around the patio and the neighborhood, just like I did as a child, nothing much happened, although I was interested on maybe commuting to work by bike, but I wasn’t sure I would be able to do it.</p> <hr /> <p>On Friday I had the day off, and thought it would be a good time to go for an early morning ride! My original plan was to do the whole trip to work and then return, without the time pressure. But I ended up just roaming around downtown without any real direction, just embracing the freedom of commuting by bike. The initial route was the reverse to what I did to get home.</p> <p>One of the things I focused on was looking for other people commuting on a bike. It wasn’t hard to find someone. As soon as I got to the main street I had to ride through, a commuter was a few dozen meters ahead. I decided to stay behind him for most of the main road, it was cool to follow someone with a path defined already. He turned towards a quieter street parallel to the main one, but I kept following the guy. He was older than me and we didn’t exchange any words, I stayed behind until I decided to go past him, his bike was rather old, and ugly.</p> <p>That’s something I noticed, most bikes I saw were for commuting, they are barely maintained and often look rusty, with the paint peeling off and dust all over them. I didn’t stop to ask anyone about it, but my assumption is that they either don’t care about the looks, or they simply do it on purpose to discourage bike theft.</p> <p>My bike was the only one I came across that had mechanical disc brakes. Everyone else had v-brakes, which are the most common especially on older bikes and budget-friendly models.</p> <p>I made it downtown and started to see more of that traffic. Nothing to worry about, streets are still compact and cars go slow. I end up arriving to the riverside—yes my city has a river—and I realize that there’s actually a little bike lane there! They are one-way and on opposite directions of the street. This is a very touristy area so it makes sense, I have no idea why I had never noticed it before… oh, I know why.</p> <p><em>The only bike lane in my city is like, a meter wide.</em></p> <p>One might think that’s just sad but I honestly found it hilarious. Why did they even bother? Well, I can’t complain that much, because I tried it for a bit and kind of enjoyed it! Going at my own pace without worrying about cars behind or in front of me, I was able to pick up some speed, although I had to be mindful of intersections.</p> <p>Having made such a discovery, I decided to head back home, going uphill on a lot of areas. I ended up riding for about 13 kilometers in an hour of time, not bad for a first try!</p> <hr /> <p>Next day on Saturday, I went cycling again and decided to ride towards a nearby neighborhood. This one felt a bit more dangerous at first, because I would have to ride through a main road. Not a highway per se, but still big. Once again I avoided most of it by using parallel streets and ended up making it there in one piece!</p> <p>The reason I wanted to ride around this neighborhood is because my own only has dirt roads. This was nearby and had proper paviment, so I wanted to bike around the place without much pressure. I didn’t stumble upon any cars, and there was one super long straight downhill that was very fun to take, although I still was not great at using my brakes, it wasn’t super difficult to go back up either.</p> <p>From there, I went towards a nearby high school, because I wanted to see if they had bike parking! The school was closed—it was a weekend after all–but I could see some infrastructure in place. The building itself was built recently, so the surroundings are pretty much just mountainous terrain…</p> <p>So of course I had to give that a go.</p> <p>I rode behind the high school and ended up going downhill between some dirt and rocks! I went rather slowly—It’s a hybrid, not a proper mountain bike—but it was cool to feel the suspension at work, as well as manouvering through the big rocks and trying to stay in balance. I tried to find an exit to go back to civilization, but it was a dead end and had to walk along my bike all the way up. It was worth it nonetheless.</p> <p>On my way back I took the big street again all the way, and felt cool to do so without taking a side street this time. I went once again downtown, through the same route until I got to the riverside again.</p> <p>I wanted to go in the opposite direction of the bike lane I took yesterday. I ended up in a small park. Just a social spot with lots of trees and walking paths, with a slightly wider path all around the park for bikes to ride around. I saw another person riding on one, and a few older men parked with theirs as well. The one cycling was the first bike with disc brakes I’ve seen on my rides so far. He also had a very wide saddle, I guess for comfort due to age.</p> <p>Trying to ride into one of the smaller pathways, I ended up almost crashing with the root of a tree, so I had my second suddent stop that ended up with some… pain…</p> <p>Alas, I cycled back downtown following a different road than before. There was a bit of a scary moment when one of the public transport buses was right behind me, but I managed to pedal away just fine. I had another encounter with another bike that I thought looked <em>awesome</em>, I followed it for a bit, the brand was <em>Green Plus</em>, and although I didn’t ask they seem to be at least double the price of mine! The shape looked a lot more unique than everything I had seen so far.</p> <p>As I made it to the main road downtown, there was once again a bit of slow traffic. I was feeling bold and decided to ride in between the cars (it’s a single line, so it was between moving and parked cars, not between two moving vehicles). This is apparently legal in my city, from what I read online, but I was still careful about it to avoid opened doors in front of me.</p> <p>Eventually I made it back to the usual quiet route home. I rode about 20 kilometers this time, for about 1 hour 40 minutes. I even stopped at little shop in the neighborhood (a <em>tiendita de la esquina</em> in Mexico) and bought myself some juice. I was feeling pretty cool.</p> <hr /> <p>During these trips I kept looking for bikes and what people used them for. Actually most of the people were older adults which didn’t seem to have a lot of income. I wondered where they were going, what their work was, what was the reason for them to bike, how long have they done it. How often do they do maintenance to them, and lots of other things.</p> <p>Honestly given the state of some of those bikes I was amused by it all. How would those bikes feel to ride? Maybe I spend way more money than I needed to? I think my bike was worth the money, it’s not that expensive after all, but it still felt weird to see the difference between the people in my small city and the cycling and bike commuting community online.</p> <p>I will keep going on my weekly rides, and I am still thinking about trying a proper commute to work. I need to ask how to access the bike parking space in my work (yes, there are some spots available!) and to buy a proper rack and locks. But well, that’s a blog post for another day.</p> <figure class="img"> <picture> <source srcset="/assets/img/blogs/2026-05-22-bike.webp" type="image/webp" /> <source srcset="/assets/img/blogs/2026-05-22-bike.png" type="image/png" /> <img class="mx-auto" src="/assets/img/blogs/2026-05-22-bike.png" alt="A collage of lo-fi pics of some spots around the city!" /> </picture> <figcaption class="caption">A collage of lo-fi pics of some spots around the city!</figcaption></figure> <p>This is day 69 of <a href="https://100daystooffload.com">#100DaysToOffload</a></p> <p> <a href="mailto:me@joelchrono.xyz?subject=Riding a bike">Reply to this post via email</a> | <a href="https://fosstodon.org/@joel/116622063288480696">Reply on Fediverse</a> </p> Affordances for me, but not for thee - Werd I/O 6a1061872862270001fd4b84 2026-05-22T14:00:39.000Z <p>Link: <a href="https://www.techpolicy.press/the-web-is-being-made-accessible-for-ai-not-people/?ref=werd.io"><em>The Web Is Being Made Accessible for AI, Not People, by Jonathan Zong and Frank Elavsky in Tech Policy Press</em></a></p><p>This is worth sitting with:</p><blockquote>&#x201C;The modern web, originally built for sighted humans using browsers, is now being redesigned for a new kind of user.<br><br>What these developers are offering their AI visitors is essentially an accessibility accommodation. [&#x2026;] But when the audience is a disabled person, it has historically been treated as an afterthought. Structured, concise text-based representations of complex content are almost exactly the kind of accommodation that blind and low-vision screen reader users have spent decades requesting from web developers, largely in vain.&#x201D;</blockquote><p>One of the oddest parts of the AI shift is that people are much more willing to do things for LLMs that they should have been doing for human beings all along. Accessibility is clearly an important one: 95% of websites have accessibility flaws, and convincing teams to allocate time for accessibility concerns can be like pulling teeth. But now that similar affordances are required for LLM use, people are leaping over themselves to implement them.</p><p>The same goes for specifications and documentation. Often, these have been afterthoughts; policies have been hand-waved rather than concretely written down in ways that people can point to. Sometimes it&#x2019;s even made explicit that this is to preserve manager optionality. But now that LLMs need more concrete instructions in order to behave well, specifications, documents, plans, and policies have rocketed up the priority list.</p><p>It would be beautiful if these needs converged, but as the article notes, the affordances needed by screen readers and LLMs are different. Similarly, documentation and planning documents aimed at an LLM are coercive in nature: they&#x2019;re designed to force the software to do the right thing, rather than to provide background as to why something is the case.</p><p>The simple truth is that there is clearly a perception, in some quarters, that there is a stronger productivity gain from doing this work to serve AI than doing it to serve real human people. That&#x2019;s quite a dystopian idea, particularly as, even if you don&#x2019;t care about people with disabilities or your own colleagues, <em>doing those things for humans clearly actually has a real benefit</em>. Making your site more usable allows more people to interact with your work and improves your search engine performance. Writing clear documentation and policies allows your colleagues to spend less time figuring out what to do.</p><p>But you can&#x2019;t measure those things neatly. The cause and effect aren&#x2019;t immediately tethered; managers don&#x2019;t see a boost they can cleanly ascribe to this work. In contrast, you know pretty instantly whether the AI you&#x2019;ve trained on your documentation is doing the right thing.</p><p>More importantly, whereas accessibility affordances provide new abilities for vulnerable people, an AI affordance provides new abilities for people with power. And that&#x2019;s probably the heart of it.</p> We hardened zizmor's GitHub Actions static analyzer - Trail of Bits Blog https://blog.trailofbits.com/2026/05/22/we-hardened-zizmors-github-actions-static-analyzer/ 2026-05-22T11:00:00.000Z &lt;p&gt;In March 2026, attackers exploited a &lt;code&gt;pull_request_target&lt;/code&gt; misconfiguration in the &lt;a href="https://github.com/aquasecurity/trivy-action"&gt;&lt;code&gt;aquasecurity/trivy-action&lt;/code&gt;&lt;/a&gt; GitHub Action to exfiltrate organization and repository secrets, then used those credentials to backdoor &lt;a href="https://github.com/BerriAI/litellm"&gt;LiteLLM&lt;/a&gt; on PyPI (see &lt;a href="https://github.com/aquasecurity/trivy/discussions/10462"&gt;Trivy&amp;rsquo;s post-mortem&lt;/a&gt; for the full timeline). &lt;a href="https://github.com/zizmorcore/zizmor"&gt;&lt;code&gt;zizmor&lt;/code&gt;&lt;/a&gt; is a static analyzer that GitHub Actions users run to catch exactly these misconfigurations before they ship. When GitHub Actions &lt;a href="https://github.blog/changelog/2025-09-18-actions-yaml-anchors-and-non-public-workflow-templates/"&gt;added support for YAML anchors&lt;/a&gt; in September 2025, a small but high-value slice of the ecosystem started writing workflows that &lt;code&gt;zizmor&lt;/code&gt; could only analyze on a best-effort basis.&lt;/p&gt; &lt;p&gt;Over the past three months, Trail of Bits collaborated with the &lt;code&gt;zizmor&lt;/code&gt; maintainers to bring &lt;code&gt;zizmor&lt;/code&gt;&amp;rsquo;s anchor support up to full coverage. First, we fixed parsing bugs that caused crashes, produced wrong-location findings, and silently mishandled aliased values. Second, we surfaced deserialization edge cases that broke zizmor on otherwise valid workflows. Finally, we helped align &lt;code&gt;zizmor&lt;/code&gt;’s expression evaluator with GitHub’s own &lt;a href="https://github.com/actions/languageservices"&gt;Known Answer Tests&lt;/a&gt;. We validated all of this against a new corpus of 41,253 workflows from 6,612 high-value open-source repositories. The result: 20 filed issues, 15 merged pull requests.&lt;/p&gt; &lt;h2 id="building-the-test-corpus"&gt;Building the test corpus&lt;/h2&gt; &lt;p&gt;To understand how anchors are used in CI today and to stress-test &lt;code&gt;zizmor&lt;/code&gt; against the full variety of YAML it encounters in the wild, we built a corpus of real workflows. We used &lt;a href="https://cloud.google.com/blog/topics/public-datasets/github-on-bigquery-analyze-all-the-open-source-code"&gt;BigQuery&amp;rsquo;s GitHub dataset&lt;/a&gt; to identify the 10,000 most-starred repositories created between 2022 and 2025, filtered to the 6,612 that use GitHub Actions, and downloaded every workflow file. That gave us 41,253 YAML files.&lt;/p&gt; &lt;p&gt; &lt;figure&gt; &lt;img src="https://blog.trailofbits.com/2026/05/22/we-hardened-zizmors-github-actions-static-analyzer/pipeline_hu_50937b9976f313d5.webp" alt="Pipeline diagram showing repository selection from BigQuery, filtering for GitHub Actions usage, and workflow download feeding into the zizmor scan stage" width="680" height="390" loading="lazy" decoding="async" /&gt; &lt;figcaption&gt;Figure 1: Building a testing corpus&lt;/figcaption&gt; &lt;/figure&gt; &lt;/p&gt; &lt;p&gt;When we ran &lt;code&gt;zizmor&lt;/code&gt; against the corpus, it crashed on 45 of the 41,253 workflows. That&amp;rsquo;s a low rate, but each crash means a bug in &lt;code&gt;zizmor&lt;/code&gt;.&lt;/p&gt; &lt;h2 id="how-anchors-are-used-in-the-wild"&gt;How anchors are used in the wild&lt;/h2&gt; &lt;p&gt;&lt;code&gt;zizmor&lt;/code&gt;&amp;rsquo;s anchor support was deliberately limited, and for good reason. YAML anchors make workflows non-local: an alias defined in one place changes behavior elsewhere in the file. This complicated &lt;code&gt;zizmor&lt;/code&gt;&amp;rsquo;s parsing model, and adoption was rare enough that the &lt;code&gt;zizmor&lt;/code&gt; maintainers reasonably &lt;a href="https://blog.yossarian.net/2025/09/22/dear-github-no-yaml-anchors"&gt;discouraged&lt;/a&gt; anchor use. In our corpus, only 43 of the 41,253 workflows use YAML anchors (roughly 0.1%), but those 43 include some of the most foundational projects in open source:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="https://github.com/bitcoin/bitcoin"&gt;Bitcoin Core&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/php/php-src"&gt;PHP&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="https://github.com/openssl/openssl"&gt;OpenSSL&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;However, anchors are a supported feature, and their use will likely grow over time.&lt;/p&gt; &lt;p&gt;We found two common patterns. The first is &lt;strong&gt;reusing steps across jobs&lt;/strong&gt;, as Bitcoin Core&amp;rsquo;s CI does:&lt;/p&gt; &lt;figure class="highlight"&gt; &lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runners&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="cp"&gt;&amp;amp;ANNOTATION_PR_NUMBER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Annotate with pull request number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; if [ &amp;#34;${{ github.event_name }}&amp;#34; = &amp;#34;pull_request&amp;#34; ]; then &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo &amp;#34;::notice ...&amp;#34; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; fi&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test-each-commit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="cp"&gt;*ANNOTATION_PR_NUMBER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v6&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt; &lt;figcaption&gt;&lt;span&gt;Figure 2: Reuse step definition&lt;/span&gt;&lt;/figcaption&gt; &lt;/figure&gt; &lt;p&gt;The second pattern is &lt;strong&gt;pinning action versions once&lt;/strong&gt;. For instance, &lt;a href="https://github.com/home-assistant/core"&gt;Home Assistant&amp;rsquo;s CI&lt;/a&gt; defines the action reference (with its SHA hash) using an anchor, then reuses it wherever the same action appears:&lt;/p&gt; &lt;figure class="highlight"&gt; &lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;lint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;&amp;amp;actions-setup-python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/setup-python@a309ff8b42...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# later in the same workflow:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;*actions-setup-python&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt; &lt;figcaption&gt;&lt;span&gt;Figure 3: Reuse action definition&lt;/span&gt;&lt;/figcaption&gt; &lt;/figure&gt; &lt;h2 id="four-anchor-handling-bugs-found-and-fixed"&gt;Four anchor handling bugs found and fixed&lt;/h2&gt; &lt;p&gt;When we started, four anchor patterns from these workflows broke &lt;code&gt;zizmor&lt;/code&gt;.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Aliases in sequences were incorrectly flattened.&lt;/strong&gt; When a YAML alias appeared inside a sequence (like a list of steps), &lt;code&gt;zizmor&lt;/code&gt;&amp;rsquo;s internal path representation spread the alias contents rather than treating it as a single element. This caused &lt;code&gt;zizmor&lt;/code&gt; to crash or produce findings pointing at the wrong location in the file. (Fixed in &lt;a href="https://github.com/zizmorcore/zizmor/pull/1557"&gt;#1557&lt;/a&gt;)&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Anchor prefixes leaked into values.&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;a id="figure-4"&gt;&lt;/a&gt;&lt;/p&gt; &lt;figure class="highlight"&gt; &lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="cp"&gt;&amp;amp;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v, *x]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt; &lt;figcaption&gt;&lt;span&gt;Figure 4: Anchor prefix leak&lt;/span&gt;&lt;/figcaption&gt; &lt;/figure&gt; &lt;p&gt;In YAML flow sequences, anchor prefixes like &lt;code&gt;&amp;amp;name&lt;/code&gt; weren&amp;rsquo;t stripped from resolved values. Given the snippet in &lt;a href="#figure-4"&gt;Figure 4&lt;/a&gt;, looking up the first element of &lt;code&gt;foo&lt;/code&gt; would return &lt;code&gt;&amp;amp;name v&lt;/code&gt; instead of &lt;code&gt;v&lt;/code&gt;, causing any step that consumed the node value to fail. (Fixed in &lt;a href="https://github.com/zizmorcore/zizmor/pull/1562"&gt;#1562&lt;/a&gt;)&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Duplicate anchors caused a crash.&lt;/strong&gt; The YAML spec allows redefining an anchor name (the last definition wins). &lt;code&gt;zizmor&lt;/code&gt;&amp;rsquo;s YAML layer assumed anchor names were unique and panicked on duplicates. (Fixed in &lt;a href="https://github.com/zizmorcore/zizmor/pull/1575"&gt;#1575&lt;/a&gt;)&lt;/p&gt; &lt;p&gt;&lt;strong&gt;The &lt;code&gt;template-injection&lt;/code&gt; audit crashed on aliased &lt;code&gt;run&lt;/code&gt; values.&lt;/strong&gt; When a YAML alias was used as a scalar &lt;code&gt;run:&lt;/code&gt; value, the audit didn&amp;rsquo;t expect the indirection and failed. (Fixed in &lt;a href="https://github.com/zizmorcore/zizmor/pull/1732"&gt;#1732&lt;/a&gt;)&lt;/p&gt; &lt;p&gt;To prevent future regressions, we also added integration tests covering anchor patterns found in real workflows (&lt;a href="https://github.com/zizmorcore/zizmor/pull/1682"&gt;#1682&lt;/a&gt;) and updated the anchor documentation (&lt;a href="https://github.com/zizmorcore/zizmor/pull/1788"&gt;#1788&lt;/a&gt;).&lt;/p&gt; &lt;h2 id="what-else-the-corpus-surfaced"&gt;What else the corpus surfaced&lt;/h2&gt; &lt;p&gt;Running &lt;code&gt;zizmor&lt;/code&gt; against the full test corpus also surfaced bugs that had nothing to do with anchors.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Deserialization edge cases.&lt;/strong&gt; GitHub Actions accepts YAML constructs that &lt;code&gt;zizmor&lt;/code&gt;&amp;rsquo;s workflow model didn&amp;rsquo;t anticipate: &lt;code&gt;if: 0&lt;/code&gt; (an integer where a string is expected), &lt;code&gt;timeout-minutes: 0.5&lt;/code&gt; (a float where an integer is expected), &lt;code&gt;secrets: inherit&lt;/code&gt; (a string where a mapping is expected). Each one caused &lt;code&gt;zizmor&lt;/code&gt; to reject the entire workflow. We reported these as individual issues (&lt;a href="https://github.com/zizmorcore/zizmor/issues/1670"&gt;#1670&lt;/a&gt;, &lt;a href="https://github.com/zizmorcore/zizmor/issues/1672"&gt;#1672&lt;/a&gt;, &lt;a href="https://github.com/zizmorcore/zizmor/issues/1674"&gt;#1674&lt;/a&gt;), and the maintainers fixed them quickly.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Expression evaluator bugs.&lt;/strong&gt; &lt;code&gt;zizmor&lt;/code&gt; evaluates GitHub Actions expressions to determine whether user-controlled data flows into dangerous sinks. We validated the evaluator against GitHub&amp;rsquo;s own &lt;a href="https://github.com/actions/languageservices"&gt;Known Answer Tests&lt;/a&gt; and helped the maintainers align &lt;code&gt;zizmor&lt;/code&gt;&amp;rsquo;s behavior with the official test suite (&lt;a href="https://github.com/zizmorcore/zizmor/issues/1694"&gt;#1694&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Upstream issues.&lt;/strong&gt; We also traced some crashes to bugs in an upstream dependency, &lt;a href="https://github.com/tree-sitter-grammars/tree-sitter-yaml"&gt;tree-sitter-yaml&lt;/a&gt;, and filed issues and PRs there (&lt;a href="https://github.com/tree-sitter-grammars/tree-sitter-yaml/issues/39"&gt;tree-sitter-yaml#39&lt;/a&gt;, &lt;a href="https://github.com/tree-sitter-grammars/tree-sitter-yaml/issues/43"&gt;tree-sitter-yaml#43&lt;/a&gt;). Even the YAML 1.2 test suite doesn&amp;rsquo;t cover every edge case the spec permits.&lt;/p&gt; &lt;h2 id="securing-ci-where-it-matters-most"&gt;Securing CI where it matters most&lt;/h2&gt; &lt;p&gt;Supply-chain attacks like the Trivy compromise begin with a single misconfigured workflow. GitHub Actions is by far the most popular CI system for open-source projects, and &lt;code&gt;zizmor&lt;/code&gt; plays an important role in helping maintainers catch risky configurations before attackers do.&lt;/p&gt; &lt;p&gt;By gathering 41,253 real-world workflows and running &lt;code&gt;zizmor&lt;/code&gt; against all of them, we tested its robustness against the full variety of YAML patterns that projects actually use. We fixed several anchor-handling bugs, reported deserialization and expression-evaluator issues, and broadened the set of workflows &lt;code&gt;zizmor&lt;/code&gt; can analyze cleanly. The methodology is straightforward: download real inputs, run the tool, triage the failures. Any static analysis tool can benefit from the same approach.&lt;/p&gt; &lt;p&gt;We&amp;rsquo;d like to thank the &lt;code&gt;zizmor&lt;/code&gt; maintainers, in particular &lt;a href="https://github.com/woodruffw"&gt;@woodruffw&lt;/a&gt;, for their responsiveness and thorough code review throughout this work. We&amp;rsquo;d also like to thank the &lt;a href="https://www.sovereign.tech/"&gt;Sovereign Tech Agency&lt;/a&gt;, whose vision for OSS security and funding made this work possible.&lt;/p&gt; New miniseries: 'Online security essentials' - Johnny.Decimal https://johnnydecimal.com/support/updates/2026-05-22-online-security/ 2026-05-22T06:57:10.000Z <p>We added the first episodes in a new JDU miniseries: <a href="https://johnnydecimal.com/jdu/online-security/">Online security essentials</a>.</p> <p>We&#39;ve been wanting to do this one for a while. This is the basics of staying safe online, and is something we hope you can send to your non-nerd loved ones. We&#39;re each recording it with our dad in mind.</p> <p>This one will also be posted on <a href="https://youtube.com/@johnny.decimal">the YouTube channel</a> for maximum reach.</p> Background; foreground - James' Coffee Blog https://jamesg.blog/2026/05/22/background-foreground 2026-05-22T00:00:00.000Z <p>In a way, I carry my website with me wherever I go. Technically, my website is a few keystrokes away on my phone, but I think the presence of my website extends beyond the technical. Having a website encourages me to write, I think, because I know I have a place to put and share my writing. I take notes as I go throughout the world because I love writing, then I come home and ask “could I craft this into an essay?” <sup class="footnote-reference" id="f-1"><a href="https://jamesg.blog/longform-feed#1">1</a></sup> And so over time my website has accrued stories of <a href="https://jamesg.blog/2025/05/30/things-around-me">bird song</a> and <a href="https://jamesg.blog/2025/04/10/the-evening-coffee-shop">coffee shops</a> and <a href="https://jamesg.blog/2025/04/05/tesco-ice-cream">ice cream in Tesco</a>.</p><p>My cadence for writing ebbs and flows. I often write in bursts; several days may pass where I mainly take notes, and then I start coalescing ideas into blog posts. In this way my blog moves from the background to the foreground and back – I take notes in the background, write for my blog, and then go back to taking notes. </p><p>Days may pass where I don’t do anything with my blog because I’m working on another project, or am otherwise preoccupied. This has been true of late where much of my creative energy has been focused on Wonders of Web Weaving. I want the conversations I have to be the best they can be so my mind has been more on “what questions can I ask?” than “what do I have to write?”</p><p>Hearing others’ perspectives on the web gives me so much energy, but right now I want to sit with that energy and let it propel the interviews rather than coming back to my blog. My blog is always here for me when I’m ready, like I am this Friday lunch time when I have connected enough dots to start writing.</p><p>This week and last I have also been reading Charlotte Brönte’s Jane Eyre for school. I am almost two thirds of the way through the book and it is already one of my favourites; the contrast between realism and the Gothic in the book is terrific, and my ability to appreciate this contrast has been much aided by reading about the book while I read the book itself. The book is long and gripping, and so my blog has been more in the background – it’s here when I am ready to write, but Jane Eyre has more of my attention at the moment.</p><p>I love that my website can sit in the background for a little while. It’s here for everyone who comes to read, and it’s here for me, too, both as a reference – I visit my website basically every day, often to look something up I have written – and as a creative space. Maybe I’ll make a web page. Or write a blog post. Or find a link to share with a friend. And then I keep doing all the other things I do: reading and thinking and walking and dreaming and chatting.</p> <div class="footnote-definition" id="1"><sup class="footnote-definition-label" id="f-2">1</sup> <p>Maybe I overestimate the extent to which having a website and writing are intertwined. Would I write as much if I didn’t have a website? The way to find out would be to not have a website, and that’s not a world I want to live in. Indeed, my passion for the web is so great that despite all of the problematic parts, I am still excited about the future of the web. I want to keep making websites and show other people what is possible with websites because I know first hand how much having a little space to call your own on the World Wide Web can make a big difference.</p> <a href="https://jamesg.blog/longform-feed#f-1">[↩]</a></div> <script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'9ffba2c5ce9a4608',t:'MTc3OTQ1MDk2Nw=='};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&amp;&amp;(document.onreadystatechange=e,c())}}}})();</script> <a class="tag" href="https://jamesg.blog/2025/04/05/tesco-ice-cream">ice cream in Tesco</a> <a class="tag" href="https://jamesg.blog/2025/04/10/the-evening-coffee-shop">coffee shops</a> <a class="tag" href="https://jamesg.blog/2025/05/30/things-around-me">bird song</a> <a class="tag" href="https://jamesg.blog/longform-feed#1">1</a> <a class="tag" href="https://jamesg.blog/longform-feed#f-1">[↩]</a> Like sunrise over a sink - Werd I/O 6a0f8ad42862270001fd4b7d 2026-05-21T22:44:36.000Z <p>Link: <a href="https://www.the-independent.com/arts-entertainment/books/news/commonwealth-short-story-winner-ai-generated-jamir-nazir-granta-b2980039.html?ref=werd.io"><em>AI scandal engulfs prestigious short story prize after multiple entrants accused, by Shahana Yasmin for the Associated Press</em></a></p><p>So I want to be a bit careful about this, because a false positive would be harmful, but it certainly <em>looks</em> like the short story that won the <a href="https://commonwealthfoundation.com/short-story-prize/?ref=werd.io">Commonwealth Fund Short Story Prize</a> was <a href="https://bsky.app/profile/emollick.bsky.social/post/3mm5gtrlvpk27?ref=werd.io">generated with AI</a>.</p><p>A lot has been said of the writing, which includes sentences like:</p><blockquote>&#x201C;She had the kind of walking that made benches become men.&#x201D;</blockquote><p>And:</p><blockquote>&#x201C;The girl smiled like sunrise over a sink.&#x201D;</blockquote><p>The author has no digital footprint except for an AI-shilling LinkedIn account. While he is a verified real person, his author photo <a href="https://x.com/JSweetLI/status/2056743816426562001?ref=werd.io">has very clearly also been AI-generated</a>.</p><p>Here&#x2019;s the thing I haven&#x2019;t seen anyone mention yet: we know that <a href="https://arxiv.org/abs/2509.00462?ref=werd.io">when AI is used in hiring, it preferences AI-generated resum&#xE9;s</a>. And <a href="https://www.linkedin.com/pulse/does-ai-self-preferencing-create-more-bias-than-ever-luiza-hnl3f/?ref=werd.io">not by a small amount</a>:</p><blockquote>&#x201C;The preference rate for models evaluating their own outputs over human-written alternatives reached a staggering 67% to 82% across major commercial and open-source systems.&#x201D;</blockquote><p>There were well over seven thousand submissions for the short story prize. Is it really outside of the realm of possibilities that the prize itself used AI to sift through them?</p><p>I&#x2019;m not saying any of this is definitely what actually happened, but it certainly makes for an interesting Turing test &#x2014; and it&#x2019;s worth making note of this moment as a marker as AI continues to ingrain itself culturally.</p> Nothing deserves brand royalty - Joel's Log Files https://joelchrono.xyz/blog/nothing-deserves-brand-loyalty 2026-05-21T22:20:00.000Z <p>I don’t like to think of myself as someone with “brand loyalty”, but it’s undeniable that I have preferences for the tools I use hardware and software-wise.</p> <p>When it comes to brands for any product, I like to think that I do my research and often go for the most budget-friendly options. I used Xiaomi devices for a long time because they were easy to jailbreak and install custom Android versions on them that allowed me to customize my device however I wanted.</p> <p>I chose my Kobo Clara 2E because it’s not Kindle and it was easy to install KOReader on it. If it were any other brand, if it lacked a built-in store and if its default OS were bad. I wouldn’t mind, the hardware allowed me to do what I wanted, it was the most practical choice. The XTEINK X4 showed up much later to fill a different niche, but I still would have gone Kobo for a proper-sized reader, Amazon is just evil.</p> <p>I went with Anbernic and Miyoo handhelds since they simply had the most community support around them and I knew the hardware was plenty for my needs. I could have gone with even cheaper no-brand options too but the amount of information available would not have been as big.</p> <p>Built-in features are almost never what I care about, a pretty logo does not matter to me, I don’t need some comfy walled garden either, when it costs me my freedom.</p> <p>However, I am weak when it comes to one brand: <a href="https://nothing.tech/">Nothing</a></p> <p>Or at least, that design language of theirs.</p> <p><em>Yep, the title had a double meaning, I apologize</em></p> <p>I don’t think this warrants a super long blogpost, you can just look up what they sell and you’ll clearly see how incredibly unique they are.</p> <p>I own one of their phones—<em>Nothing Phone (3a)</em>—one of their wireless earphones—<em>Nothing Ear (a)</em>—and I just purchased their of open earphones too—<em>Nothing Ear (open)</em>—that I’ve been testing for a couple of days and plan to use while cycling around my city.</p> <p>For the price, the brand is well placed, offering affordable devices with some compromises that I don’t really care about. But when I purchased these earbuds (and the ones I already had, to be honest) I realized that I completely ignored my “budget-friendly” ideals of before. I would usually go for something like SoundCore or Haylou back in the day.</p> <p>I got them because they were competitive, sure—any more expensive and I would not have bothered—but the design is what won me over. They look unique, they say something about you. And as much as I don’t want a brand to represent me or seem superficial, I just can’t help but love it.</p> <p>There are better products for better prices, but the creativity just won me over, their phones’ bootloader is also unlockable so that’s a plus for the day I finally decide to get into rooting and installing a rom on my phone again.</p> <p>Now, if it’s not obvious. Nothing (the brand) doesn’t actually deserve brand loyalty. They have done some sketchy moves too. I am not a fan of the pathetic AI button on my phone that can’t be reprogrammed by default. There are also some updates that have shown some notifications with ads for app recommendations and the like. Definitely not perfect at all.</p> <p>I just love that their phones and products are more than just boring rectangles and Apple clones, okay?</p> <p>Oh, actually, I am also weak to Nintendo, they suck, they do terrible stuff sometimes, but those games are just so goood…</p> <p>Sorry, <a href="/blog/more-confessions-from-a-foss-enthusiast/">I am just a hypocrite</a>. Enough.</p> <p>This is day 68 of <a href="https://100daystooffload.com">#100DaysToOffload</a>)</p> <p><img src="/assets/img/blogs/2026-05-21-nothing.webp" alt="My phone and earbuds from Nothing" /> <em>All of my Nothing products, very aesthetic!</em></p> <p> <a href="mailto:me@joelchrono.xyz?subject=Nothing deserves brand royalty">Reply to this post via email</a> | <a href="https://fosstodon.org/@joel/116614926058332931">Reply on Fediverse</a> </p> Why micropayments can't save news - Werd I/O 6a0f15982862270001fd4747 2026-05-21T14:29:00.000Z <img src="https://storage.ghost.io/c/18/7c/187cc681-d3f3-49fc-87de-b01d06b76821/content/images/2026/05/evelyn-clement-TjvEfjXIb_s-unsplash.jpg" alt="Why micropayments can&apos;t save news"><p>In an interview with Nicholas Thompson last month, <a href="https://www.niemanlab.org/2026/05/sam-altman-backs-micropayment-model-for-ai-agents-to-compensate-publishers/?ref=werd.io">OpenAI CEO Sam Altman backed a micropayments strategy for news</a>:</p><blockquote>&#x201C;What really makes sense in a world of agents is we try a sort of micropayment-based approach. [&#x2026;] My agent can read it, pay $0.17, and give me a summary of that. If I want to go read the whole article, pay $1, or however that works. If my agent wants to calculate something for me that&#x2019;s really difficult to do, it can go rent some cloud compute somewhere and pay for that, but I think there will be need to be a new economic model for these agents doing lots of small transactions and exchanges of value with each other on behalf of their human controllers or whatever, all of the time.&#x201D;</blockquote><p>What he describes is a combination of pay-per-view and a utility model. In pay-per-view, you&#x2019;re paying a custom price set by the publisher in order to access a resource; you as the user might get a prompt asking whether you approve the transaction, or you might just give it an approved budget. When he talks about an agent renting cloud compute, it would likely be paying based on usage like a utility, with financial transactions similarly carried out behind the scenes. It&#x2019;s not really different from the Spotify model in the sense that artists are paid per stream; there it&#x2019;s a percentage of your total listens, whereas here it&#x2019;s probably a total budget that you preload into a wallet.</p><p>This keeps coming up in software circles: I&#x2019;ve heard, again and again, that an approach like Altman describes would help provide revenue for publishers in an AI-intermediated information ecosystem. I disagree; while I think there&#x2019;s certainly value for utility-style pricing on the web, proposals to use it for news are based on a misunderstanding of how journalism is valued and paid for today, set up the wrong incentives for publishers, and conflate every kind of publisher into one very flat model.</p><p>So, let&#x2019;s talk about it.</p><p>First, it&#x2019;s important to understand what a micropayment actually <em>is</em>. Then I&#x2019;ll discuss the incentives micropayments create, how they might apply to different kinds of publishers, where micropayments <em>might</em> be useful, and how platform owners might embrace the needs of publishers more directly in an agentic ecosystem.</p><h3 id="what-is-a-micropayment">What is a micropayment?</h3><p>Micropayments are small payments &#x2014; sometimes a fraction of a cent &#x2014; that are charged to access digital goods or services. Usually, this happens more or less automatically: you load a wallet connected to your web browser or AI agent, and then when you or your agent visit a resource, a small payment is made. This could be a flat fee or it could be charged as a percentage of your total browsing for the month.</p><p>There have been a number of attempts to make micropayments work on the web. <a href="https://en.wikipedia.org/wiki/Flattr?ref=werd.io">Flattr</a> was an early example: a browser extension that paid for content on your behalf. It struggled with getting enough people to fund their wallets and was faced with the high underlying transaction fees associated with credit card payments. It ultimately shut down in 2023. The Brave browser <a href="https://brave.com/blog/introducing-brave-payments/?ref=werd.io">attempts something similar through cryptocurrency</a>.</p><p>Today, the <a href="https://interledger.org/?ref=werd.io">Interledger Foundation</a> is working on creating an open protocol that can be used for micropayments, among other kinds of compensation. The protocol is intended to overcome the kinds of financial friction that Flattr experienced. The Foundation is working hard on the problems I&#x2019;ll raise here in the rest of the piece.</p><h3 id="we%E2%80%99ll-make-it-up-in-volume">We&#x2019;ll make it up in volume</h3><p>Clickbait is enabled at scale on the web by display advertising. Because the revenue received by a publisher is directly connected to the number of pageviews they receive, publishers that are entirely tethered to this model have two incentives:</p><ol><li>To drive as much traffic as possible to their articles</li><li>To lower the cost of each individual article as much as possible</li></ol><p>That&#x2019;s led to an information ecosystem where many publishers produce low-quality content with misleading headlines in an effort to get as many people as possible to look at them. For many, it doesn&#x2019;t even matter if the article is true; the reader doesn&#x2019;t build a long-term trust relationship with the publisher and likely won&#x2019;t come back unless they&#x2019;ve been hoodwinked into looking at another one. These publishers are the tourist traps of the internet. There&#x2019;s no ongoing relationship, so there&#x2019;s no duty of care.</p><p>Micropayments are effectively this model, with the difference that nobody has to look at an ad. Revenue is directly tethered to traffic, like a display ad model; the difference is that the money for a publisher comes from the reader&#x2019;s pocket instead of the advertiser&#x2019;s.</p><p>Not only does this continue to incentivize clickbait, but these publishers are now competing for the checkbooks of millions of people rather than a few well-funded advertisers. In an advertising-based world, every visitor is highly likely (ad blockers excepted) to produce a small amount of revenue; in a distributed wallet world, we&#x2019;re relying on individuals to be well-funded.</p><p>It&#x2019;s also worth considering the full user journey. For a reader to arrive at a particular article, one of two things is happening:</p><ol><li>The reader has discovered the article off-platform, perhaps through a social media post or a search engine result</li><li>The reader already trusts the publication and is seeking out their information specifically</li></ol><p>In the first case, the publisher is incentivized to find ways to surface their work. That will be through a combination of tried and tested methods like social media audience work, paid acquisition, and SEO. But they have to do this work <em>for every single article, for every single reader</em>. The most efficient thing they can do is try to build an ongoing relationship with that reader so they don&#x2019;t have to work as hard for that reader&#x2019;s second pageview. In other words, the most desirable end state for a cold interaction with a reader is some kind of trusted relationship: they want the reader to sign up for a membership.</p><p>In the second case, a trust relationship has already been established. Here, too, the most desirable end state is for the reader to have a membership. Because the reader already trusts the publication, it&#x2019;s the most desirable end state for <em>them</em>, too: they likely want to prioritize this publication over other sources that are less trusted by them.</p><h3 id="okay-but-what-about-agents">Okay, but what about agents?</h3><p>There&#x2019;s an argument to be made that, in an agentic world, the relationship isn&#x2019;t between the publication and the reader; instead, the AI vendor sits in the middle as an intermediary. That&#x2019;s much worse. Rather than allowing every reader to build their own information landscape, the decisions made by companies like OpenAI about which sources are trustworthy will affect the information that <em>everybody</em> receives. If agents build their own trust relationships with publications, the underlying assumptions that dictate how those agents select sources and process their information govern how everybody learns about the world around them.</p><p>Micropayments probably <em>are</em> the financial backbone of that world, but I&#x2019;d argue that it&#x2019;s not a world we want to live in. On the other hand, if agents act based on human reader preferences, then the relationship returns to being between the publication and the reader, and we&#x2019;re back to the incentives <em>for both readers and publishers</em> tending towards membership.</p><p>If an agent-first world really is coming &#x2014; and, to be clear, the jury&#x2019;s still out &#x2014; then finding ways to encode memberships into the underlying protocols and mechanisms is important. Micropayments are ephemeral.</p><h3 id="publishers-are-not-monolithic">Publishers are not monolithic</h3><p>When we talk about &#x201C;publishers&#x201D; we miss a ton of nuance. What works for a local for-profit paper is not the same as what works for a non-profit national news website is not the same as what works for a premium international newspaper. These businesses all try to serve their communities with information, but they have different financial dynamics, communities, and needs. There are multiple overlapping spectra of business models, information types, communities served, publishing surfaces, and more.</p><p>At some intersections, micropayments might make more sense than others. For example, if a local for-profit paper is serving event listings for the area, it might quite reasonably charge an agent to access it as a dataset on a utility basis. In general, micropayments do make sense as a way to access raw datasets or lists of facts; you don&#x2019;t establish a trust relationship with a spreadsheet.</p><p>But even then, it&#x2019;s heavily dependent on the nature of the publisher. If it&#x2019;s a non-profit paper, those charges might not fit within its mission. If we&#x2019;re instead talking about ongoing, in-depth qualitative reporting on the characters behind a neighborhood, rather than flat facts, or an ongoing series by a journalist with a specific point of view, a reader might want to establish a subscriber or member relationship. But that, in turn, might make more sense for a for-profit publisher, while a non-profit might be serving its articles for free but asking for a donation. (Or it might not! There&#x2019;s nothing <em>requiring</em> that it does this.)</p><p>The medium matters, too: some models work better with the ways people interact with text, others with the ways people watch video. You also need to consider the characteristics of the intended audience. <em>Can</em> they pay for a micropayment or a membership, or does informing them require some other kind of underwriting like non-profit donations from an institutional backer or, yes, advertising? If we only inform audiences who can pay, we create news deserts in the communities that might need real reporting the most.</p><p>There&#x2019;s no single solution. Every publisher needs to figure out the business model that&#x2019;s right for it based on its specific context, mission, audience, and focus.</p><p>There&#x2019;s a real distinction between commodity facts (a stock price, a sports score, an event listing) and the analytical, contextual, investigative work that makes journalism valuable. The latter is an ongoing process of building trust. It&#x2019;s not ephemeral; it is relationship-based. And although, as I&#x2019;ve discussed, there are also real differences across publisher type, medium, and community, it&#x2019;s generally not a good fit for micropayments.</p><h3 id="so-what-should-platforms-do">So what should platforms do?</h3><p>I&#x2019;ve discussed that publishers need to navigate all their contextual factors and choose the business model that&#x2019;s right for them from first principles. Platform owners would likely prefer that publishers all use the same template &#x2014; it&#x2019;s much easier to build a scalable platform that way. Sam Altman isn&#x2019;t just thinking about how to provide compensation to publishers; he&#x2019;s also considering what would result in the least friction for his business.</p><p>Micropayments are useful for people who build agentic platforms because they reduce friction. The user asks for information (or the system contextually decides they need to see it); the system serves up that information. The micropayment transaction happens behind the scenes in a non-interruptive way.</p><p>Supporting trust relationships can be similarly non-interruptive, but they require a little more thought. Today, the thinking is that AI agents will use protocols like MCP to request information from sources. The protocol might change in the future, but the principle probably remains the same: it&#x2019;s an API that happens to be designed for AI systems rather than traditional client applications.</p><p>Adding a mechanism for explicit calls to action would be a great start. This would allow the publisher to prompt the user to start a membership. The publisher would receive more information about the reader, as well as potentially some revenue; in turn, the reader would receive access to more articles or data that their agent could use.</p><p>One embodiment of this is that a user could subscribe to a publisher and receive its articles in a reader, perhaps even using an existing substrate like RSS; they could then use their accumulated corpus of subscribed articles with their AI agent. The agent is not intermediating a relationship with the publisher; the relationship is with the human subscriber, and the agent then operates on what they&#x2019;ve subscribed to. This doesn&#x2019;t just build trust in the publisher: it builds a loyalty relationship with the AI platform too. Both the publisher and the AI platform build a stronger relationship with the reader.</p><p>Membership-first platforms like Ghost are already approaching this as they start to add more affordances for AI. It wouldn&#x2019;t surprise me to see existing publisher platforms move in this direction, building more foundational AI technology for memberships in the process.</p><p>Publishers don&#x2019;t need to compromise on their relationships with their communities in order to adopt new technology. Platforms don&#x2019;t need to flatten relationships in order to achieve scale. There&#x2019;s a lot to be gained by working together and understanding each other &#x2014; and remembering that human relationships build the kind of trust and loyalty that an ephemeral transaction never could.</p> Going to try shutting down my laptop every night - Johnny.Decimal https://johnnydecimal.com/blog/0206-shutdown-to-force-your-hand/ 2026-05-21T13:00:38.000Z <p>When you have the safety net of &#39;never close anything&#39;, you don&#39;t really have to think about where a thing goes. You can just leave things open in a window, unsaved, hoping that someone else will think about it at some point in the future.</p> <p>Starting today I&#39;m going to quit every app and shut down my laptop at the end of the night.</p> <p>Will I find it all again in the morning?</p> Context switching - Johnny.Decimal https://johnnydecimal.com/blog/0205-baserow-reveals-context-switching/ 2026-05-21T12:21:48.000Z <p>Still on a quest to figure out the right pattern for <a href="https://johnnydecimal.com/blog/0161/">work logs</a> (also <a href="https://johnnydecimal.com/blog/0183/">here</a> and <a href="https://johnnydecimal.com/jdu/taskpm/290-work-log-and-dashboard/">this episode of the Task &amp; Project Management course</a>), I&#39;ve been tracking what I&#39;m doing in a really simple Baserow table for a couple of days.</p> <p>It&#39;s just thing, started, and finished. If an item isn&#39;t finished, it groups up to the top (not shown here), so I have a simple list of stuff I&#39;m still doing. It&#39;s been <em>really</em> helpful and I&#39;ll keep doing it. (Idea is to template this out as something you can duplicate.)</p> <figure class="figure jdimage jdimage--auto-dark jdimage--drop-shadow"> <picture> <img class="figure__inner" alt="Screenshot of a database table. It shows 21 rows, each one a thing I was doing at some time today or yesterday." height="562" loading="lazy" src="https://johnnydecimal.com/blog/0205-Baserow-1904x1124@2x.png" width="852"> </picture> </figure> <p>That&#39;s me working on 21 separate tasks, across the breadth of my business, in just 2 days. And I&#39;m sure there are more: I haven&#39;t added a row for the fact that I&#39;m typing out this blog post.</p> <p>The modern world is <em>insane</em>. You can do so much. And at the end of the day your brain is broken. It&#39;s pretty obvious why.</p> <p>I&#39;m not sure what I do with this data yet. It&#39;s not like I want to slow down. But this doesn&#39;t feel sustainable? (Not complaining! Love my job. Just an observation.)</p> Graduation Day - Cool As Heck https://cool-as-heck.blog/graduation-day 2026-05-21T11:34:16.000Z <div>Today is graduation day for my twin girls, Moxie and Clarity.</div> <div><br></div> <div>They've gone through a lot of things I didn't have to go through when I was a kid: divorce, moving, changing schools, going back and forth between two parents. Yet they turned out much wiser than I was at their age. They've both strived to be great students and challenge themselves, attending college-level classes at the high school or classes at the local community college during their senior year. They joined clubs, made art, inspired change, built solid friend groups, and advocated for their fellow students. I know that they're ready for college and the new challenges ahead. I'm so proud of them.</div> <div><br></div> <div>Today my heart is full.</div> Whale Fall - Terence Eden’s Blog https://shkspr.mobi/blog/?p=70000 2026-05-21T11:34:15.000Z <p>Somewhere, in the endless blue ocean, a gigantic mammal shudders as it takes its last breath. Thanks to science, we know that all dogs go to heaven, but all whales descend through the murky depths until their carcasses litter the seabed.</p> <p>Imagine a giant dying. You can't. They are huge and endless. A towering presence which, so it seems, has <em>always</em> been part of our world. They dominate and are indomitable. It is simply unfathomable that they can ever end. Yet end they must.</p> <p>As the whale dies, we do not know what passes through its cavernous brain. But we do know what the rest of the ocean thinks.</p> <p>Lunch.</p> <p>The death of a whale is a thing to be celebrated. The thump of their still-warm body onto the floor is the starting bell for a feast. Some larger predators sense an easy meal and tear off the choicest morsels. But what of the scavengers? What about the new life not yet established? What happens to the weird little creatures just waiting for an energy boost?</p> <p>In many ways, it was fortuitous that Twitter pre-signalled its death with the Fail Whale.</p> <p>The twitching corpse is gently floating down to its watery grave. Some of the older and more established social networks have bitten out chunks of the still-fresh body and have run away with their spoils. But the fascinating thing is watching all the <em>new</em> services benefit from the death of a giant. Mastodon, Discord, BlueSky, Qaplion, Nostr, and a bunch of others hollowing out the rotting husk and using it to power their own growth.</p> <p>Will those .meow social networks ever become a gigaton behemoth capable of ruling the waves? Maybe not, but size is not the only metric of success. Finding and defending an ecological niche is its own reward. Evolution abhors a monoculture.</p> <p>Several bloated bodies meander through the brine, each one confident that its ageless wisdom will outlast the others. Had they any self-awareness, the hubris would gnaw at their tattered souls until the crushing realisation of their impending doom drove them mad.</p> <p>Perhaps it will happen to GitHub next. The endless downtime and forced injection of crappy AI will start a death spiral. Already established forges are waiting to pounce once they smell blood in the water. But what critters will emerge to suck the bones of the old giant and develop in unexpected ways? Some bizarre fungal growth will devour the stinking jelly unlocked from those shattered bones and a new ecosystem will emerge.</p> <p>Will WordPress's increasingly erratic leadership and tangle of legal disputes cause it fatal damage? Once minnows darted away from its presence; now they cautiously nip at its greying skin. Its mighty bellow still echoes through the clammy waters, but there's a tinge of frailty in its song.</p> <p>Everything dies eventually.</p> <p>The internal flora and fauna - be they parasitic or symbiotic - eagerly await their host's downfall. A chance to break free and explore new strange new world. A chance to begin a new relationship and co-evolve in unexpected ways.</p> <p>The biological pump is primed, the hungry jaws of an uncountable fleet of new ideas is just waiting to pounce, the giants swim on in blissful ignorance.</p> <p>You can read more about <a href="https://en.wikipedia.org/wiki/Whale_fall">Whale Fall on Wikipedia</a>.</p> <img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=70000&HTTP_REFERER=Atom" alt width="1" height="1" loading="eager"> New miniseries: 'Everyday Obsidian' - Johnny.Decimal https://johnnydecimal.com/support/updates/2026-05-21-everyday-obsidian/ 2026-05-21T06:22:57.000Z <p>We added the first episodes in a new JDU miniseries: <a href="https://johnnydecimal.com/jdu/obsidian/">Everyday Obsidian</a>.</p> <p>In this free series I&#39;ll show Lucy practical everyday tips for Obsidian. This is &#39;how normal people use it every day&#39;, not &#39;how to become an Obsidian guru&#39;.</p> PSA: PDFs leak data - Johnny.Decimal https://johnnydecimal.com/blog/0204-psa-pdfs-leak-metadata/ 2026-05-21T05:48:15.000Z <p>Lucy just noticed that a PDF she was viewing in her browser revealed something about its history when she hovered over the browser tab. In her case, harmless enough: the shameful fact that she created one of her lovely <a href="https://johnnydecimal.com/jdu/excel/">Excel summary sheets</a> in PowerPoint. (Not even Keynote!)</p> <figure class="figure jdimage jdimage--auto-dark jdimage--bare"> <picture> <img class="figure__inner" alt="Screenshot of a Firefox tab which has a PDF open. The tab reveals the inner 'title' of the PDF, which in turn reveals Lucy's shame: that she created it in PowerPoint." height="867" loading="lazy" src="https://johnnydecimal.com/blog/0204A-Browser-tab-leaking-PDF-2440x1734@2x.png" width="1220"> </picture> </figure> <h2 id="pdfs-are-full-of-invisible-data">PDFs are full of invisible data</h2> <p>Chock-full of it. Here&#39;s how this can trip you up. Let&#39;s say Jim is leaving so the team writes him a lovely message. Nobody really likes Jim, so you save the file on your Desktop with a snarky title.</p> <figure class="figure jdimage jdimage--auto-dark jdimage--bare"> <picture> <img class="figure__inner" alt="Screenshot of a Word doc. The text wishes Jim well, but the document's title on disk is 'We all hate Jim really because he's a piece of work'." height="700" loading="lazy" src="https://johnnydecimal.com/blog/0204B-Jim-Word-1908x1400@2x.png" width="454"> </picture> </figure> <p>Then you <strong>Print &gt; Save as PDF…</strong>, and of course you save the file as <code>Good luck Jim!.pdf</code>.</p> <figure class="figure jdimage jdimage--auto-dark jdimage--bare"> <picture> <img class="figure__inner" alt="Screenshot of us saving as PDF. We've renamed the PDF as it will be saved on disk, but forgotten about its 'title'." height="843" loading="lazy" src="https://johnnydecimal.com/blog/0204C-Save-as-PDF-1422x1686@2x.png" width="711"> </picture> </figure> <p>Oooh but you didn&#39;t notice the <strong>Title</strong> field there, and now that&#39;s embedded in the PDF. Jim can just inspect the file or, if you&#39;re unlucky, he&#39;ll open it in Firefox on the farewell Zoom call and it&#39;ll be visible to everyone. <em>Em-barrassing!</em></p> <figure class="figure jdimage jdimage--auto-dark jdimage--bare"> <picture> <img class="figure__inner" alt="Screenshot of the macOS file info pane clearly showing the original file title." height="637" loading="lazy" src="https://johnnydecimal.com/blog/0204D-Info-pane-754x1274@2x.png" width="377"> </picture> </figure> <p>You think this will never happen to you? <a href="https://kagi.com/search?q=data+leaks+embedded+pdf+title&amp;r=au&amp;sh=kmkyiIB6yZMU6rRsHZIZhQ">Oh sweet child, it happens all the time</a>. And there&#39;s not really much you can do about it other than be aware of it, and remember not to do it.</p> <p>PDFs contain a <em>lot</em> more information than you can see. Be careful.</p> Nobody is destined for greatness. - Westenberg 6a0e5fd5fdaca50001ddbba1 2026-05-21T01:31:20.000Z <img src="https://www.joanwestenberg.com/content/images/2026/05/photo-1632083955294-9be78257202c.jpeg" alt="Nobody is destined for greatness."><p>Demosthenes lost his first appearance before the Athenian assembly. His voice came out thin and failed him mid-sentence, and the crowd laughed him off the platform. Plutarch tells us he walked home with his cloak pulled over his face, certain his public life had ended before it started.</p><p>What he did next settled the rest of his career. He dug out an underground study and shaved half his head, so that he&apos;d stay indoors at his exercises for months, too ashamed to be seen. He crammed pebbles into his mouth and made himself speak around them. Climbing steep ground, he recited long passages, and he pitched his voice against the crash of the sea so that a hostile crowd could never break his rhythm again. He walked out of that hole as the finest orator Greece produced, the man who roused Athens against Philip of Macedon.</p><p>Nobody handed him any of it. He built it out of repeated failure and a stubborn refusal to accept the verdict of one bad afternoon.</p><h2 id="the-story-we-keep-telling">The story we keep telling</h2><p>We tell ourselves a flattering story about greatness. Some people get born for it, the gift already in them, coiled and waiting. We keep that story alive because it lets everyone off the hook. If you have to be marked for it from the start, then the people who reach it were always going to, the rest of us were never meant to, and nobody has to attempt anything that might hurt.</p><p>Anyone who reads the biographies finds the opposite. The people we file under genius turn out to be the ones who put in absurd quantities of hard, unwitnessed work before anyone noticed them. Some of them carried obvious aptitude, sure, but they fed it for years before they made it into something worth paying to see.</p><h2 id="where-the-naturals-come-from">Where the &quot;naturals&quot; come from...</h2><p>People reach for Mozart first to defend the destiny myth. They point at a child composing music at 5, call it proof of something supernatural in the blood, then skip what came before: Leopold Mozart, a professional teacher who wanted a prodigy for a son, started drilling the boy before he could read. By the time Wolfgang wrote anything we still perform, his father had put him through daily lessons for more than a decade.</p><p>The psychologist Anders Ericsson studied expert performers for most of his life and set out his findings in <em>Peak</em>, published in 2016. He found the same thing wherever he looked, among violinists, chess players, athletes and surgeons. The standout was the person who started young and put in more hours, whatever wiring they happened to be born with.</p><p>Ted Williams, who has a fair claim to being the best hitter baseball has seen, swung until the skin came off his hands. He liked to point out that nobody turned into a hitter by strolling up to the plate. Eliud Kipchoge, in his 40s, still grinds through the same training blocks he ran as a nobody, out of a bare camp in Kenya&apos;s Rift Valley, logging every kilometre by hand.</p><p>James Dyson built 5,126 failed prototypes of his bagless vacuum cleaner across the early 1980s before the 5,127th held together. No factory backed him and no investor believed in the idea. The established manufacturers turned him away one after another, because they made their margin selling bags and his machine needed none. The man with a multibillion-pound company today was broke through all of it, alone in a workshop, getting it wrong more than 5,000 times before anyone called him an inventor.</p><p>None of these people waited for a calling. They went and earned the thing, one repetition at a time, while it was still ugly and unrewarded.</p><h2 id="and-what-the-myth-costs">...And what the myth costs</h2><p>People who believe in destiny pay a price for it. They turn brittle, because they take their first hard setback as proof they were wrong about themselves, a sign the gift has run dry. Carol Dweck documented this in <em>Mindset</em> in 2006. Children praised for being clever, rather than for effort, dodged hard problems and folded when stuck, because failing one would expose the label as a lie.</p><p>The rest of us sit on our hands. People wait for a sign that they belong, and no one ever sends it, because that&apos;s not how any of this happens. Demosthenes got no sign. He got an underground hole, a half-shaved head, a mouthful of pebbles and the roar of the sea.</p><p>The people who make it tell the destiny story too, once they&apos;ve arrived. Looking back, they compress the grind into a clean line and leave the years of doubt out, until what remains sounds like a gift that unfolded on schedule. By retelling it that way, they teach everyone behind them the wrong lesson, and another generation believes it.</p><p>Earned greatness looks nothing like the myth. </p><p>Picture the thousandth repetition of a thing you fumbled on your first attempt, and the long stretch when nobody is watching. Behind that are the friends who lose patience, the savings that drain, the steadier job you turned down and the years that pass with no proof you were right. Other people add the glamour later, once the result is plain to see and you&apos;ve already paid for it.</p><p>There&apos;s a version of you that keeps waiting to feel chosen, and a version that goes down into the hole and gets to work. The first one keeps waiting.</p><p>Nobody is born holding greatness. </p><p>People build it in the dark, with pebbles in the mouth, long before anyone arrives to applaud.</p> Lifting Mastodon rate limits - Posts feed https://www.coryd.dev/posts/2026/lifting-mastodon-rate-limits 2026-05-20T22:04:00.000Z <p>I'm a reluctant Bluesky user and a new Bluesky user. I expanded my site's syndication implementation to support Bluesky and updated my links implementation to support tagging authors on Bluesky. Why join now? I'm not totally sure. Indigo launching was a factor. It looked like (and is) a lovely app.</p> [RSS Club] Let's meet up AFK - Terence Eden’s Blog https://shkspr.mobi/blog/?p=71519 2026-05-20T11:34:04.000Z <p><mark><em>Shhhh!</em> This post is only available to RSS subscribers like you</mark> 😊</p> <p>My wife and I are preparing for a big Interrail journey through Europe. Whenever we go on holiday, we like to meet up with friendly locals to have a drink and chat. <a href="https://shkspr.mobi/blog/2025/06/meeting-my-fedifriends-afk/">We did this on our last journey and it was great</a>.</p> <p>So, if you're a member of RSS club and fancy showing some tourists a cool bar, awesome restaurant (with vegan options), local tech conference, or nifty museum - please <a href="https://edent.tel/">get in touch</a>.</p> <p>Our exact dates aren't finalised yet, but from now until the beginning of July, we'll be taking roughly this route:</p> <ul> <li>🇩🇪 Hamburg →</li> <li>🇩🇰 Copenhagen →</li> <li>🇸🇪 Gothenburg →</li> <li>🇳🇴 Oslo →</li> <li>🇸🇪 Stockholm →</li> <li>🇫🇮 Helsinki →</li> <li>🇪🇪 Tallinn →</li> <li>🇱🇻 Riga →</li> <li>🇱🇹 Vilnius →</li> <li>🇵🇱 Warsaw →</li> <li>🇩🇪 Berlin → Munich →</li> <li>🇮🇹 Verona → Milan →</li> <li>🇨🇭 Basel →</li> <li>🇫🇷 Paris</li> </ul> <p>If you're in one of those cities and fancy a beer &amp; veggie burger, please give us a shout. We won't be able to meet everyone as we do have some existing plans and tight connections but, as they say, it's nice to <a href="https://www.youtube.com/watch?v=JhVRzh4_j50">go where everybody knows your name</a>.</p> <img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=71519&HTTP_REFERER=Atom" alt width="1" height="1" loading="eager"> Exporting Vinted Sold Data - Robb Knight • Posts • Atom Feed https://rknight.me/blog/exporting-vinted-sold-data/ 2026-05-20T10:58:13.000Z <p>Over the past month or so I've sold a bunch of stuff on <a href="https://vinted.co.uk">Vinted</a> and I wanted to know how much I've made but Vinted don't give you that data, at least not in a nice way. They have monthly reports but that shows what you started with and ended with which only works if you don't withdraw or spend anything, which I had.</p> <p>So I went to the <a href="https://www.vinted.co.uk/my_orders?order_type=sold">sold page</a>, scrolled the infinite scroll list until it had loaded the months worth of stuff and whipped up this snippet to take the price and title of the item and add it to the clipboard.</p> <pre class="language-js"><code class="language-js">list <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByClassName</span><span class="token punctuation">(</span><span class="token string">'my-orders-content'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><br />items <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>list<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'a .web_ui__Cell__content'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br />data <span class="token operator">=</span> items<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">i</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> price <span class="token operator">=</span> i<span class="token punctuation">.</span><span class="token function">getElementsByClassName</span><span class="token punctuation">(</span><span class="token string">'web_ui__Text__text'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>innerText<br /> title <span class="token operator">=</span> i<span class="token punctuation">.</span><span class="token function">getElementsByClassName</span><span class="token punctuation">(</span><span class="token string">'web_ui__Cell__title'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>innerText<br /><br /> <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>price<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> // </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>title<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'\n'</span><span class="token punctuation">)</span><br /><span class="token function">copy</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span></code></pre> <p>The output will look something like this which I can then paste into <a href="https://numi.app">Numi</a> or <a href="https://soulver.app/">Soulver</a> to give me a total. Bundles don't have a useful title because that's not available on the page.</p> <figure><img src="https://cdn.rknight.me/site/2026/vinted-data-in-numi.jpg" alt="Numi app showing sales data across three lines and a total at the end" /></figure>