Latest Posts (20 found)

Unleashing agents inside the workshop

I recently learned of Ubuntu Workshops . In short, Workshops allow you to create an isolated development environment to safely work with AI agents. You get a configured (via YAML) sandbox where you can safely run an agent without the need for permission checks and guardrails. Workshops allow you to expose or block certain parts of your system as needed (for example, you can expose your GPU for local models or block access to your webcam). As an example, let's build a simple Rust app that converts images from the HEIC format (bane of my existence) to JPEG. We'll use Iced to provide a simple GUI that supports drag and drop. First, install the Workshops Snap from the Ubuntu App Store. I also had to install the LXD subsystem for virtualization : To setup the workshop, create an empty directory and run the following commands: This will give a workshop named "dev" with Codex and Rust ready to go. On first run, we'll need to login to Codex using the following: Next, we want to define an "auto-mode" for Codex so we don't have to deal with permission check prompts. We'll do this by defining an "action" in the file. We've added two actions, to define a non-interactive session, and for an interactive one. Both have the flag which bypasses permission checks. As an added benefit, actions make it easy to standardize how we pass instructions to agents. We could easily define a Claude action that accepts the same arguments as Codex. Now let's define our prompt, instructing the agent to build our Rust application. This could of course also be done interactively via the Codex TUI inside the workshop, or through a a AI software factory . For now, we'll create a file and add the following: Finally, we'll setup Git for version controlling. Time for the fun part! We'll use the command to build the application in the folder without needing any input from the user. The agent will now run completely autonomously with no need to press "enter" on permission checks. Our host system remains protected as the agent is sandboxed away from our filesystem and devices. In fact, you'll notice in the prompt we specified that the agent should not try running the application. This is because we didn't provide access to a Wayland or X11 display server, so the agent cannot run a GUI application. Here's what I got as a result: The UI isn't great, but it works and successfully converted some photos from my iPhone! After putting together this article and testing out workshops, I'd say it's definitely a tool worth using. Workshops add minimal overhead, provide a composable/reusable environment for development and safeguard your host system from agents going rogue. Between this and Myna , Canonical is doing a lot to support the new development workflows that are becoming common

0 views

2026-10-20 16:31: Hooman, we are ready to receive your apple core. 🍎

Hooman, we are ready to receive your apple core. 🍎 Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views

Do minor curl vulnerabilities in the open

The curl project has decided to alter its vulnerability disclosure program procedure and starting October 26 2026 , we insist that all vulnerability reports submitted to us that are deemed to be severity LOW or MEDIUM should instead be submitted as issues in our GitHub repository . Only vulnerabilities deemed to be HIGH or CRITICAL will be kept private in the HackerOne tracker . Security researchers in doubt can still submit the issue on HackerOne and we can tell them what severity we deem it to be. Over the last few years, over 90% of all submissions could quickly be assessed to be less than HIGH. Issues submitted to HackerOne we deem are LOW or MEDIUM will be requested to be resubmitted on GitHub and will be closed as informative on HackerOne (and publicly disclosed). This policy change is entirely triggered by the current avalanche of vulnerability reports that keep pouring in. We see no end to them and we do not anticipate this flood to decrease within the next several months. We are struggling as a project as all key maintainers feel strained, overloaded and brought to the brink of what we can muster. We must act to survive. This is our next step in a survival strategy. It might not be our last. We aim to not drown. By opening up the process we allow the whole world to participate. Both in the assessment and understanding of the report and claimed vulnerability, but also in the creating and writing the advisory and figuring out details of when the issues was introduced etc. Ideally we get better help to make sure the fix is the correct one, that it fixes the problem, and any other related problem that is similar and that it does not miss a related problem sitting next to this. An obvious recent trend is that the moment we announce a new set of CVEs and their associated fixes, there is an army of AI-using researchers who throw all those at their models and harnesses to find similar mistakes or omissions in the fixes. By taking this process to the public all the way, ideally we get more help to do that scrutiny better before we ship releases. We recognize that the amount of work needed per received vulnerability report does not shrink by doing them in public, but we think that we might share the burden among more people easier, and we hope that lessons and documentation brought up in these discussions will be easier to spot and learn from. The open process can also allow distros and other users of curl to keep up with security fixes earlier and better. Several people have suggested there is a risk that researchers mistakenly submit severity HIGH issues on GitHub thinking they are LOW or MEDIUM. It is basically unheard of that a researcher would have understated a reported problem so I consider that a low risk scenario. Also: there was already before this a risk that someone would submit a vulnerability report in the public, it is not a new risk. Handling some vulnerabilities in the public of course makes the immediately available for both good and bad people. This policy will give bad people a slightly longer window of opportunity to exploit weaknesses at the expense of existing curl users. That is unfortunate but we see no way of avoiding this. We limit this practice to less than HIGH for this reason: at least these problems are not terrible. We have discussed simply dismissing all severity LOW issues, but within the CVE program there is an appeals process and if we don’t hand out a CVE to an actual vulnerability, then someone else will do it. We thus cannot ignore true vulnerabilities, or they will come back to bite us nonetheless. We can however resist and refuse silliness and I personally aim to deny and decline more vulnerabilities harder on the basis that they do not actually hurt any users or existing applications. A clear trend these days is that many newly reported vulnerabilities are figured out by AI models that create crazy sequences or option combinations that do something unexpected, but the sequence is something that aren’t likely to ever be used in the real world, or the unexpected that happens is something that occurs every time so applications doing this would spot the problem immediately. I.e problems that have almost no risk to actually trigger in the real world. We save no users by insisting on doing the CVE dance for those issues. We only get work for ourselves and a whole world that has to act on them. There is an almost infinite number of combinations you can use libcurl’s many options, protocol mixes and flexible API to do things that might not be clearly documented and the AIs will continue to try them all and together with the humans driving these checks they are super eager to treat every minor discrepancy as a vulnerability. We can’t continue down this spiraling path with our sanity intact. We don’t have the bandwidth, manpower or even will to handle a never-ending vulnerability reporting stream at this pace. I believe few software projects can stand this kind of prolonged high volume deluge for extended periods. Something needs to give way. We only use these for levels in the curl project: LOW, MEDIUM, HIGH and CRITICAL. Often we refer back to recently managed vulnerabilities to see how we judged them, but we also provide a set of basic guidelines . I’m sure we can also make them better and clearer.

0 views
Unsung Today

Obsessive about obfuscation

My perhaps strangest confession to date: I’m annoyed about all the common ways people obfuscate text. I think I developed this frustration during the GUIdebook times . In my gallery of splash screens , I would often be faced with this situation: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/obsessive-about-obfuscation/1.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/obsessive-about-obfuscation/1.1600w.avif" type="image/avif"> I didn’t want to propagate the registration info, and could think of a few ways to obfuscate it: = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/obsessive-about-obfuscation/2.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/obsessive-about-obfuscation/2.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/obsessive-about-obfuscation/3.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/obsessive-about-obfuscation/3.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/obsessive-about-obfuscation/4.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/obsessive-about-obfuscation/4.1600w.avif" type="image/avif"> = 2x) and (width >= 700px)" srcset="https://unsung.aresluna.org/_media/obsessive-about-obfuscation/5.2096w.avif" type="image/avif"> = 3x) or (width >= 700px)" srcset="https://unsung.aresluna.org/_media/obsessive-about-obfuscation/5.1600w.avif" type="image/avif"> The first one felt okay, but it looked like the information just wasn’t there to begin with. Black bars and blurring didn’t look realistic, felt ugly, and drew too much attention to something ultimately not as important. Eventually I arrived at the last solution – the Diffuse filter in Photoshop – which I felt kept the text’s “texture” (or, color in the typographical sense). You can see it everywhere in GUIdebook’s splash collection . What somehow didn’t occur to me at that time was an even better solution: to modify the existing text instead of covering it. Make up a realistic name or serial number, typeset it exactly the same way, and plop it in the same place. This is exactly what I did recently in the post about ⌘1 in Messages – it started with a regular screengrab, but I replaced all the names and avatars with fake ones. I can tell you now: This approach is a lot of work. Which is why I was amazed to discover that a Mac email client called MailMate actually has this kind of a feature built in. It’s called Distortion Mode, and I believe it’s meant specifically to help in taking screenshots without disclosing anything – it replaces all the strings with fake Latin in a rather clever way, and even adjusts the timestamps! The product person in me is a bit weirded out by the name and the whole feature even existing. In what universe is it important to make it easy to take screenshots of mail software? Why wouldn’t the team work on something that actually matters? But maybe it’s okay and even desirable for apps to be a bit quirky this way. MailMate even owns up to it on : MailMate is not for everyone, but if it’s for you then you might never have to switch email client again. Plus, I mean, I started this post by saying “I’m annoyed about all the common ways people obfuscate text” – so let me pass the first stone to someone else.

0 views

Laypeople support technical fields for technology, not art

Some people think that LLMs should not be used in technical fields like programming or mathematics , because those fields are actually art. True or not, this kind of argument is not going to be persuasive to the general population. The argument goes something 1 like this: It doesn’t matter how effective LLMs are at technical fields like programming or mathematics, because one of the essential values of those fields is that they’re art . While it looks to laypeople like these fields exist to solve practical problems, what they’re actually for is to produce works of beauty, or to express something distinctively human, or to spend time contemplating the infinite . Simply solving the problems misses the point in the same way that building an infinite poem generator would miss the point of poetry. I agree that programming or mathematics can be beautiful. I remember being mildly awestruck at learning epsilon-delta proofs , and I have written a lot about the kind of software I think is elegant. Since there’s no clear definition of art or of aesthetics in general, it’s plausible to me that almost everything could have an artistic dimension to it. All of this is compelling to software engineers, many of whom (like me) find some programs beautiful and are flattered to think of themselves as artists. But I suspect it’s spectacularly uncompelling to onlookers, because it undermines the implicit reasons that they have for supporting technical fields. Many people who are not programmers or mathematicians think of those fields like this: In other words, regular people 3 think mathematicians (and to a lesser extent programmers) are valuable because they think science is valuable, and they think science is valuable because they think technology is valuable. They are willing to accept that technical fields can be art only insofar as that eventually helps researchers have the kind of creative insights that advance science: as Rikab sarcastically puts it, that advance the knowledge frontier . If you go to those non-technical people and you say “LLMs can accelerate problem-solving in these fields, but I’m strongly against using them because the real point is to produce great art”, they will be very unhappy. They might reasonably feel cheated, in the same way as if they hired someone to renovate their kitchen who insisted in doing it all with hand tools in order to experience “the joy of creation”. This argument — we should stop using LLMs in technical fields because they’re art — is going to be even less compelling to technical employers . Engineers and mathematicians who want to defend the artistic value of their field will need more compelling arguments 4 than just appealing to the value of art. We will need to find some way to connect the value of art with the practical technological value that motivates public interest in our fields. For instance, we could argue that: I don’t know if I agree with all of these points. I haven’t yet seen an LLM-created codebase truly hit a wall (at least, not this year), and I don’t see a reason why LLMs should be incapable of creating new abstractions or having human-like inspirations. I also don’t think great products have to have great code: why wouldn’t workmanlike code in service of a great idea be enough? Does Fallingwater have to have beautifully installed 6 insulation? Still, any argument we make to our employers or the general public about art is going to have to try and make this case. Instead of saying that human-made technical work is valuable because it’s art, we need to make an affirmative case for why art can make technical work more effective. Otherwise we’re conceding the main reason why the general population thinks our work matters. As usual when I’m trying to avoid strawmanning a point of view I don’t hold, please email me if you agree with the quoted paragraph and consider it a fair representation of your position. If nobody writes in to tell me they agree, I will reword the paragraph. Leaving out some specific concerns about the health of social media, short-form video, gambling apps, and so on. Is there actual evidence for this claim I’m making, other than it just seeming kind of obvious? I couldn’t find anything definitive, but the UK CaSE study (see “The balance of fundamental and applied research”) and this paper are suggestive. This is not a criticism of the Glyph post , which is aimed at other engineers, and does include an argument that artistically-produced software is better for users. I take this to be the argument in the Glyph post. Ironically, the house does actually have serious mildew problems . The poor construction quality does not seem to have affected its status as art. I enjoy the fruits of technology: modern medicine, transport, mobile phones, and so on While I don’t understand the exact relationship, I know that technical fields like mathematics and programming are essential to sustaining and advancing these technologies Therefore I’m happy to respect and support mathematicians in their mysterious research work And I’m broadly okay with 2 software engineers drawing healthy salaries for the same reason Great software products must rely on elegant abstractions , which need a human creative touch: simply piling on working code will hit a wall past a certain level of complexity LLMs can solve problems, but actual progress in mathematics depends on creating new abstractions , which is a more creative task that LLMs are not yet good at Progress in technical fields is uneven and relies upon inspiration, which needs creative hammock time and distinctively human understanding LLMs can produce working software, but truly great software requires human inspiration 5 , and great software is what advances the field As usual when I’m trying to avoid strawmanning a point of view I don’t hold, please email me if you agree with the quoted paragraph and consider it a fair representation of your position. If nobody writes in to tell me they agree, I will reword the paragraph. ↩ Leaving out some specific concerns about the health of social media, short-form video, gambling apps, and so on. ↩ Is there actual evidence for this claim I’m making, other than it just seeming kind of obvious? I couldn’t find anything definitive, but the UK CaSE study (see “The balance of fundamental and applied research”) and this paper are suggestive. ↩ This is not a criticism of the Glyph post , which is aimed at other engineers, and does include an argument that artistically-produced software is better for users. ↩ I take this to be the argument in the Glyph post. ↩ Ironically, the house does actually have serious mildew problems . The poor construction quality does not seem to have affected its status as art. ↩

0 views

NixOS Is Making Me Less Afraid

Something funny happened a little while ago: I read about FreshRSS, and it sounded nice, so I installed it on a server and started using it . That would not have happened a year ago, but then again, a year ago I didn’t have any NixOS servers. For the past few years, my RSS feeds have lived locally on my phone only. There was a good idea behind that, but it never quite worked in practice. For one, many things are easier to read on a larger screen. But it was also brittle to trust a phone app to manage the read/unread status of thousands of articles across a hundred feeds. What I really wanted was a server-side feed aggregator. This is software that runs on a server, manages RSS feeds, and then I can read the RSS feeds either through a web interface, or through client applications. I’ve wanted that for a while, but I’ve never taken the step, because it would be yet another side project to maintain the deployment of. But now, with some NixOS experience, adding a working FreshRSS configuration (including backups) took 9 lines of Nix code. That installation has just hands-off worked for the past few months. If or when that server breaks, I can spin up a new one running the exact same configuration, probably in something like 15 minutes. When we can do something like that, there is literally no reason to not just try the new software. Contrast this against how FreshRSS is installed outside of NixOS. Then we’d (Continue reading the full article on the web.)

0 views
Jim Nielsen Yesterday

No More Icons In Every Menu By Default

Have you heard the good news? I bemoaned the approach of putting an icon in every menu item by default which shipped with macOS Tahoe — but now it’s gone in Golden Gate! John Gruber wrote about this reversion back in June , including the fact that Apple’s new Human Interface Guidelines specifically call out Tahoe’s approach to menus as an example of what not to do on macOS. As the old saying goes, it takes a big man corporation to admit when they’re wrong. As I mentioned in my original post , one of the arguments I had in my quiver against this practice was “Apple doesn’t do it”. But once Apple started putting icons in all their menus in Tahoe, I lost a persuasive point in my argument. But now, I think I have an argument that’s even stronger than before! It’s no longer: “Apple doesn’t put icons in their menus.” It’s: “Apple tried putting icons in all their menus, and even they went back on it!” They designed it, shipped it, lived with it for a year, then publicly changed their guidance on it. To me, that’s a lot more persuasive than simply saying, “Apple doesn’t do this.” Choosing not to do something you’ve never done is one thing. Choosing not to do something you’ve done is experience . That’s the essence of life: learning by doing . Reply via: Email · Mastodon · Bluesky

0 views

Building a Tool for Job Searchers

The job search process can be chaotic, stressful and scary. It's easy to lose track of the progress you've made in a sea of rejection emails. As you progress through the stages, it becomes important to keep track of everyone you talked to and what you discussed. When you have multiple applications going at once, it can become messy! Like any good engineer, I decided to build my own solution! Mostly as a way to keep my mind busy and stay on top of AI tooling, but also because I believe there's real value to a tool that brings notes, scheduling and a CRM into one job search focused package. Source - XKCD I'm calling my project JobCaddy. As of right now it focuses on helping job seekers track where they've applied to, the various stages they've gone through and the people behind each stage. Test account with fake data My eventual goal is to add suggestions on actions you should take. One thing I learned as a hiring manager is that many people forget to focus on the human aspect of the process. The conversations and people you meet are extremely important. As you progress through stages at a company, you should be sending thank personalized thank you letters, referencing previous conversations and able to recall the name of each person you talked to. JobCaddy will act as a mentor of sorts, suggesting follow-ups and helping you prep for next stages based on your notes and people you talked to. Test account with fake data Like I said, this is in part a project for me to stay on-top of AI developments while I'm job searching. I'm using Next.JS deployed on Vercel with a Supabase backend and shadcn/ui for components. I'm building it primarily with Codex and have been leveraging the impeccable skill for styling . My workflow revolves around the Codex CLI in Herdr , dictation via Myse on Ubuntu and tooling management via Mise . I leverage Sublime Text for manual coding. It's been a pretty fun process, allowing me to quickly iterate based on pain points I run into while using JobCaddy for my own job search!

1 views
neilzone Yesterday

A review of the BigMe B6, an Android colour eInk tablet

For quite some time, I have been keen to try an Android device with an eInk screen, particularly a colour one, but I had not found one at a price that I was willing to pay. I saw the BigMe B6 on AliExpress. It was £134.00, and seemed to meet my requirements - including a pocketable 6” screen, and a USB-C port - and I was willing to spend that to give it a try. It arrived quickly, and came with a nice folding case which holds the device magnetically, and turns the screen on and off when opening and closing it. I had 88% charge when it arrived, so I was able to get on an use it straight away. I used to back up all the partitions on the device (except ), in case I needed to restore them. At this point, I was planning on rooting the BigMe B6, but ultimately I decided not to do so. I used for this, using the “Read partitions” function. (I used “Select all partitions”, and also had “Dump GPT” set (which it was by default). I then manually de-selected “userdata”.) I clicked “Read partition(s)” to start the partition dump. This took 20 minutes or so, mainly thanks to the 12 GB “super” partition. I backed up all the existing apks (in case I needed to reinstall them, in the event of rooting the device and uninstalling software): It comes with a lot of unnecessary (to me) stuff on it. I’d prefer a far more plain, unencumbered, device. I used this gist as inspiration, and used to disable a lot of that software. I have not rooted the BigMe B6, so the software is just disabled, not removed. I have seen some posts saying that it tries to work as a USB host by default. Perhaps things have changed, but when I plugged it into a laptop (Debian 13, GNOME), it mounted as a USB client device, just as I would expect. My goal in buying this was to have a cheap-ish device, for recreational stuff. So, I have installed F-Droid, and used F-Droid to install: All run fine. I also installed Heliboard, as an alternative keyboard. I like the customisability, in particular being able to make it smaller and yet easier for me to use than the native keyboard. The launcher is a bit childish, in a “looks poorly hand drawn to me” kind of way, but I don’t spend much time looking at it, so I have not bothered to do anything about replacing it. I’d like to try it with a Bluetooth keyboard at some point, I think, and see what it is like writing in vim or similar. It had some included eBook reading / management software, but I disabled all of it in favour of using KOreader. KOreader has its own quirks (perhaps a blogpost in itself) but, frankly, it does exactly what I need, and it does it well. In particular, I like being able to set the margins and line spacing that I want, and the auto-turn functionality, which flips the page after a set number of seconds, is very handy. The main pain point for me is that I have never successfully managed to sync my library of books - in Calibre - to the internal storage. I think that it is the sheer number of items, but whether I use Calibre’s own sync function, or drag-and-drop, or just , the transfer fails. And I have had one heck of a time trying to remove books from the internal storage, again perhaps because of the number of items in the directory. Frankly, this is annoying, and I wish that I had solved it, but I have not. Instead, I have worked around it, spending an extra £20 for a micro SD card, and accepting that, to copy books to the card, I need to remove it from the BigMe B6, put the micro SD card into a laptop, and rsync the ePubs from my library to it from there. What a pain. I could, in time, experiment with something like syncthing on it, but all I really want is to be able to plug in the eReader, via USB-C, and rsync books to it. But, hey, with a micro SD card and KOreader, I can read my books on it. The screen works really well for this - it is a joy to read on it. Browsing on an eInk screen is an interesting experience, and I have played around with the screen refresh settings to see if I can optimise it a bit. It is, IMHO, surprisingly snappy and browsing the web is no problem unless the site is poorly designed and full of JavaScript, in which case it is tolerable. Watching / streaming videos is possible, but not desirable. Fine at a pinch, or if one likes a sort of cyberpunk aesthetic. But I would not buy the BigMe B6 for watching video. I turn the Wi-Fi off when I am finished, if I am not switching off the device completely. The screen on the BigMe B6 is really nice! The screen refreshes fine, and it is easy to scroll around / use the touch-screen functions. It works a heck of a lot better than I was expecting for the price, to be honest, and I really enjoy reading / browsing on it. It is just as pleasant - if not slightly more pleasant - to read on it than it is on my dedicated eReader. Changing the eInk settings can make a significant difference, with clarity / removal of ghosting coming at the cost of more regular refreshes (which means a flash and a short delay). I want to experiment some more with this, perhaps with per-app settings. The “colour” part of the colour screen is also nice, if a bit of a novelty for me. The colours on the screen are a bit washed out / muted, but it is more than sufficient to display a book cover, or to give a decent enough representation of a photo in a blogpost. It is - of course - nowhere near as good as the colours on a non-eInk screen. Here’s a blogpost by Derick Rethans : Overall, while battery life is not a patch on my Kobo Clara HD, it is absolutely fine. To make the most of it, I turn the device off (as opposed to just pressing the power button, which darkens the screen, but does not power it off), if I am not going to be using it for a while. The trade off is that it takes about 60 seconds to boot. With Wi-Fi turned on, it - unsurprisingly - used the battery more quickly than if Wi-Fi is off. So I keep Wi-Fi off too, unless I am using it. I don’t have any particularly good observations here, other than it being worse than my eReader. I charge it a couple of times a week, or more if I am reading loads or browsing a lot, but obviously YMMV. And that’s fine. I am rarely far away from a USB-C cable. According to the Android “About” pane: The device has five printed buttons at the bottom of the screen. The first two - something that looks like a graph, and one marked “AI” - stopped working once I had disabled some of the unnecessary software. While I cannot change the look/text of these buttons, using “Key Mapper” from F-Droid, I was at least able to re-purpose these. I have not dug too much into this app, but it looks pretty useful in itself. Now, the “graphs” button (which gives a key code of 10018) toggles Wi-Fi (after some scary warning screens about “Expert Mode” in Key Mapper), and the “AI” button (which gives a key code of 10019) launches KOreader. Excellent stuff :) It had a Login screen. I pressed “Skip”. I have not logged in or done any form of registration. It looks like one can register an account with BigMe, but it is not a requirement. I have not found anything that I cannot do for lack of an account. It comes with Google Play, and I guess that one would need to sign in with a Google account to use that, but I have not done so and, again, I have not found anything that I cannot do as a consequence (since I do not use Google Play). The BigMe B6 came with Android 14. I could be wrong, but I should be surprised if it got much in the way of software updates. It came with version 3.0.0 of “BigMe” (whatever that is), and there was no system update available. The version of Android that BigMe is using is clearly intended to be on a phone. For instance, in the shutdown menu, it offers an “SOS” function, to call the emergency services. Not a big deal, and certainly something that I overlook easily for the price, but, well, not great either. I am used to having a lot more settings available to me, in GrapheneOS. The BigMe B6’s settings app is spartan, but so far the only thing that has bugged me is lack of a dark mode control. I can do it using , but that is an unnecessary pain. Instead, I just set dark mode manually in each app. Android settings says that the device is encrypted. But I don’t know what is encrypted. So far, I have not put anything sensitive on it, and I do not plan to do so - I don’t know why, perhaps coming from using GrapheneOS instead of stock Android - but while I am happy to use it for recreational stuff, I can’t quite bring myself to connect it to my email account, for instance. Tusky (Mastodon client) Fennec (browser) Tor Browser Readrops (RSS reader) Device name: Smart Office Notepad Product Code: Color Processor: Octa-core Storage capacity: Available 41.93 GB / Total 64.00 GB Screen resolution: 1072x1448

0 views

Feds Suspect Ransom Negotiator Ran ShinyHunters Extortion Site

U.S. federal investigators pursuing the ShinyHunters hacking group that recently stole highly sensitive data from the FBI have identified executives at two different ransomware negotiation firms who maintained unusually close relations with the extortion group, KrebsOnSecurity has learned. Sources close to the investigation say one of the executives in the United States even helped ShinyHunters operate a website that pressured victims into paying a ransom. Hackers aligned with ShinyHunters have claimed credit for dozens of major data breaches since 2019, when the group was primarily operated by cybercriminals living in France. As those original members were arrested or jailed one by one, control over the ShinyHunters brand eventually passed to “ Rey ,” identified last year as a teenage hacker from Amman, Jordan. According to the FBI, ShinyHunters has extorted more than $70 million from victims so far this year. In late September, ShinyHunters hacked the FBI recruitment website fbijobs.gov and taunted the agency by threatening to publish the stolen files, which reportedly included medical and psychological records, Social Security numbers and home addresses, and information about each employee’s unit and specialization. The FBI jobs site hack has prompted the agency to move with uncommon speed to arrest, detain and question people who had any communications with Rey or other ShinyHunters suspects. Reuters reported on October 3 that Rey had been detained by Jordanian authorities and was cooperating with the FBI. Rey was able to assume control over the hacking group because one of its alleged senior members had just been nabbed. On the evening of September 15, 2026, authorities in the Netherlands arrested convicted hacker and ShinyHunters suspect Pepijn van der Stap . Dutch police reportedly used flash-bang grenades in an effort to stun and apprehend Van der Stap as he was logged in to various online accounts. According to a source close to the investigation, the authorities arrested Van der Stap while he was using his Signal instant messaging account, which allowed them to read recent communications with frequent contacts — including ransomware negotiators based in Canada and the United States. Multiple sources with knowledge of the matter told KrebsOnSecurity that Van der Stap’s messages were the key to unraveling a murder-for-hire plot that emerged immediately following his arrest. The Dutch news outlet RTL reported last month the two murders were allegedly to be committed abroad, and that there are indications Van der Stap gave the order for the attacks (there is no indication those orders were ever carried out). On October 9, KrebsOnSecurity broke the news that the FBI arrested a 54-year-old Canadian cybersecurity executive named Edward Dubrovsky in connection with the ShinyHunters investigation. Dubrovsky, who recently published a book on handling cyber extortion that recommended always engaging with the hackers, was charged with threatening to disclose stolen or hacked data and interfering with interstate commerce through extortion, according to court records . Politico reports prosecutors have asked that Dubrovsky remain in custody pending trial, and that records related to his case remain under seal. A source close to the investigation told KrebsOnSecurity that Van der Stap’s Signal messages showed he had frequent conversations with Mr. Dubrovsky and with at least one executive at a large U.S.-based consulting firm, and that these executives often knew the details about new ShinyHunters victims before the victims themselves had even learned of the breach. That source shared another potentially explosive finding by federal investigators: the Dutch hacker’s chats showed Mr. Dubrovsky knew ShinyHunters had stolen highly sensitive data from FBI servers, and that he never informed the bureau of the data breach prior to ShinyHunters threatening on Twitter/X to publish the agency’s deeply personal personnel files. KrebsOnSecurity has learned from two sources close to the ShinyHunters probe that FBI investigators believe at least one executive at a U.S.-based consulting firm played an active role in operating the now-defunct ShinyHunters victim extortion website “ shinywire[.]com .” KrebsOnSecurity is not naming the U.S. company or the suspected executive(s) for now because they have not yet been charged with a crime, but it is a prestigious firm with more than 1,000 associates. A section of the homepage for the now-defunct Shinywire website. The Shinywire website was active from approximately May 3, 2026 until October 16 and had entries for nearly 100 organizations hacked by ShinyHunters. Each entry urged victims to engage with the cybercrime group and discuss terms for payment. The pages also included samples of stolen files and promised those files would be published online if the victim ignored their demands. The following screenshot shows a cached portion of the Shinywire extortion page for Intuitive Surgical , an American medical technology company that was breached in March 2026 after an employee fell for a targeted phishing email. The Shinywire website, as indexed by urlscan.io. This listing is an extortion demand targeting Intuitive Surgical, an American medical technology company breached in March 2026 by a targeted phishing email attack that compromised an employee’s credentials. Victim organizations that refused to engage or negotiate after seven days would find all of their stolen data published on the ShinyHunters victim shaming blog (a website that is only reachable via the anonymity network Tor ). In a story published October 15, The Globe and Mail wrote that a few months before Edward Dubrovsky was arrested by the FBI, the Canadian cybersecurity executive alleged in court documents he had become collateral damage in a campaign by a former business partner to “destroy” another industry executive. The story noted that Dubrovsky filed the lawsuit in Ontario this year against Daniel Tobok , the former chief executive of Cypfer , a cybersecurity firm founded in Toronto with offices in the U.S., Britain, the Netherlands, the United Arab Emirates, and Mexico. The two first became business partners in 2017 and later developed Cypfer together, where Mr. Dubrovsky was a managing partner and chief operating officer. But by 2024, the two had a falling out, with Dubrovsky accusing Tobok of gradually excluding him from business matters and making “increasingly capricious business decisions.” Mr. Tobok reportedly denied the allegations and filed a counterclaim, accusing Mr. Dubrovsky of accessing confidential information and unfairly competing with Cypfer through work at another firm called CyberSteward Inc . He also said Mr. Dubrovsky has misrepresented himself as a Cypfer founder, and is not a shareholder. According to interviews with several former colleagues of Mr. Tobok, as far back as eight years ago he was known to ransomware purveyors by a particular nickname: Ghostbyte . In 2018, a Canadian company was hacked by Dharma , a prolific Russian-language ransomware affiliate program that first surfaced in 2016. The victim company told the Dharma ransomware representative they were leaning toward paying because some of the files were unrecoverable after being locked, but that they needed a better guarantee that Dharma would keep their word if paid. A redacted copy of the Dharma rep’s reply is pictured below, and it shows the ransomware group urged the victim to contact a person at a Canadian IT firm that helps companies seeking such guarantees. The Dharma rep recommended the victim contact the email address [email protected] . “If you want guarantees, you can write to the IT company,” the Dharma reply advised. “Take the phone and negotiate with them. This IT company often solves such problems in Canada. You can contact them and sign a contract for services. You’ll still have to pay.” An email reply from the Dharma ransomware group to a victim, recommending they contact an email address that is connected to Mr. Tobok. It’s unclear if Mr. Tobok ever used that Ghostbyte address offered by the Dharma representative, and he has not responded to multiple requests for comment. However, the breach tracking service Constella Intelligence finds an email address Mr. Tobok has frequently used — [email protected] — is associated with two online accounts where the chosen username was “ghostbyte,” including a Snapchat account. Incidentally, Constella also finds the Dharma rep’s email address [email protected]  is associated with a cryptocurrency address that processed 38 transactions totaling 43 bitcoin, ~$3.5 million at today’s value (the most recent transaction for this wallet is dated February 2019). In a statement shared on October 14, Cypfer said the company’s business does not include making or facilitating ransomware payments, and that Cypfer learned of Dubrovsky’s arrest when the news first broke in the media. “We had no prior knowledge of Mr. Dubrovsky’s arrest,” a spokesperson told KrebsOnSecurity via email. “ CYPFER has not received any outreach from law enforcement and, to our knowledge, is not the target of any law enforcement investigation.” The statement said CyberSteward and Cypfer are separate companies with no officers, directors or employees in common, and that Cypfer was recently acquired by the Apros Group , a holding company led by Jason Hogg , a former FBI special agent and former CEO of Aon Cyber Solutions Group . In 2020, Aon aquired Cytelligence , a security consulting firm where Mr. Tobok was founder and CEO and Mr. Dubrovsky was a managing partner. It is not illegal in the United States to pay hackers for an encryption key to unlock servers infected with ransomware, or in exchange for a promise to delete any stolen files and refrain from publishing them online. While victim organizations can land in legal hot water if they pay a ransom to a group that is sanctioned by the U.S. Treasury Department, ShinyHunters is not among the ransomware groups currently sanctioned by the United States or by any other government. Experts say ransomware victims are typically directed by their insurance provider to work with a specific incident response firm. But not all cyber forensics and breach response companies will agree to facilitate payments to ransomware groups on behalf of their clients. As a result, once victim firms make a decision to pay, the firms that eschew rewarding extortionists are invariably replaced by companies that have no such qualms. In December 2024, ShinyHunters began extorting the education technology company PowerSchool , stealing private information on 62 million students and 9.5 million teachers in the U.S. and Canada. PowerSchool reportedly paid a $2.85 million ransom demand, and a “frequently asked questions” statement (PDF) about the breach says PowerSchool was assisted in that effort by CyberSteward (ShinyHunters affiliate Matthew Lane , 20, of Sterling, Mass., was sentenced in November 2025 to four years in prison for his admitted role in the PowerSchool hack). But that ransom payment did not stop future extortion attempts using the same stolen data. By May 2025, individual school districts were reportedly receiving separate ransom demands using samples of the same stolen files. While nobody has alleged ShinyHunters was behind the second wave of extortion against PowerSchool users, the incident drives home the reality that there is no technical way to verify the threat actors have deleted the stolen data as promised, or prevent others from abusing the same records. A number of leading cyber incident response firms, including Coveware and Unit 221B , have consistently warned victims against paying ShinyHunters , noting that “destroyed” victim data is often kept, resold or used to extort the company’s clients directly later on. The FBI echoed those sentiments in an alert on May 15, 2026 advising victims against paying the ShinyHunters group. Meanwhile, ShinyHunters members have been harassing and threatening employees at Coveware and Unit 221B for offering this advice. The following screenshots show just how annoyed the ShinyHunters leaders were with Coveware’s relentless advice against paying the group. The first image is from a conversation on May 6, 2026 that took place between the group’s main account on Telegram and a co-conspirator. In that chat, snippets of which were shared with KrebsOnSecurity by a trusted source, ShinyHunters complained that Coveware was harming the group’s payment rates. The operator of the ShinyHunters account on Telegram speaking privately with a co-conspirator and complaining that Coveware was harming their business. “Go on my website, majority of those companies would’ve paid if it weren’t for Coveware giving them misinformation,” the ShinyHunters account wrote. “Someone (100% Coveware) is going out of their way to make sure i am not paid.” In another conversation on April 11, 2026, the ShinyHunters Telegram account privately said they were trying to “eliminate the problem,” which they said was Coveware. Coveware declined to comment for this story. “I’m sure the company will pay but in this specific case I am aware of Coveware and their involvement, and I’ve probably been not getting a lot of other negotiations mostly likely because Coveware keeps getting involved,” the ShinyHunters account bemoaned. The operator of the ShinyHunters account on Telegram telling a co-conspirator they were “trying to eliminate the problem,” which they identified as Coveware advising victims not to pay the cybercrime group. Mark Camillo is chief executive at CyberAcuView , an industry group founded in 2021 by a consortium of major cyber insurance carriers. Camillo said some firms charge a flat retainer fee, while those that specialize in helping companies negotiate a ransom payment tend to charge a percentage of the total ransom amount paid. That latter dynamic, he said, is an inherent conflict of interest, as the negotiator has every incentive to make things more favorable to the attackers because they are financially incentivized to negotiate and pay out, and to not negotiate down on the price. “It has come to the industry’s attention that many of the ransomware payers charge a percentage of the final payment which may or may not be disclosed,” Camillo said. “This makes no sense if they are also the negotiator. There needs to be more transparency in the process as no one in the ecosystem should be profiting purely on the size of the ransomware transaction or payment itself.” Camillo said the firms doing this work would argue the fees are needed because there may be unexpectedly higher costs to secure larger quantities of cryptocurrency or more risk carrying the float, and because cryptocurrency exchanges may charge higher fees for high risk transactions. “There definitely needs to be more visibility around the transaction and clarity on the increasing value of the crypto and the exchange’s percent in the transaction to get to the bottom of this and remove any misaligned incentives,” he said. In recent months, the U.S. Department of Justice has prosecuted a number of ransomware negotiators alleged to have conspired with cybercriminals to defraud their clients. On October 7, the DOJ charged MonsterCloud CEO Zohar Pinhasi , 50, with wire fraud and conspiracy for allegedly charging customers to remediate ransomware attacks without paying the hackers. According to charging documents, Pinhasi secretly went behind his customers’ backs and paid hackers anyway, paying ransomware groups $8 million while charging customers $19 million. In July, Angelo Martino , a 41-year-old ransomware negotiator from Land O’Lakes, Florida, was sentenced to 70 months in prison for conspiring with the Blackcat/ALPHV ransomware group to extort multiple victims. According to the DOJ, Martino was paid by BlackCat attackers to provide confidential information about the negotiating position and strategy of his employer’s clients and enable the ransomware actors to maximize the ransoms paid by the victims.

0 views

He, She, and It

Both Shira and her husband Josh are owned by the Y-S corporation, so it is the corporation that decides to award sole custody of their son, Ari, to Josh when they split. Josh and Ari are soon shipped offworld to Pacifica, leaving Shira with no way to see her son. Heartbroken, she leaves the domed corporate enclave and travels to the free town of Tikva, in what used to be New England, where she grew up and where her grandmother still lives. But things are not easy in Tikva, either: they are under attack from unidentified forces who have slipped through their net’s defenses to murder several residents. In return, one of the residents has manufactured an illegal weapon he thinks can save them all: a cyborg. Among the competing dystopian and utopian communities, the book plays with what it means to make a life, and whether or how you can control it. Or if you ought to even try. View this post on the web , reply via email , or become a supporter .

0 views
Stratechery Yesterday

Do You Trust Apple?

Listen to this post : On July 21, 1999, Steve Jobs did something remarkable at Macworld New York: first he went to Apple.com, then to “CNN Interactive”, then to Disney.com. That wasn’t the remarkable part: what blew the crowd away was when he picked up the just-introduced iBook and walked around while waiting for Disney.com to load. The crowd went wild at the lack of wires: I’m not going to quote this entire product introduction, but I’ve clipped the whole thing for your enjoyment; here are a few pertinent parts of Jobs’ introduction of what he called “AirPort”, and what the rest of the industry called “WiFi”: There is one more thing. The main point of this keynote was the aforementioned introduction of the original iBook: This meant that “one more thing” was in fact not just an extra unexpected product, but an explicit addition to the primary product’s feature set. No wire. What is going on here? We are really excited to announce, in addition to iBook, AirPort wireless networking…It’s a wireless LAN. It runs at 11 megabits per second, and it’s based on industry standards. This is 802.11 wireless networking, and everybody is jumping on board with this thing over the next six to nine months. So all sorts of devices are going to be able to interact with AirPorts. We’re just going to be there first and best, and the specification also incorporates quite a bit of privacy protection, so everything you send out is encrypted. A lot of privacy. We’ve worked with Lucent on this for the last 18 months, hand-in-hand to marry their wireless technology with our ease-of-use technology and to bring the cost of this down for people, because this stuff has been pretty pricey to date. Apple’s selling proposition has, in many respects, never changed: modern technology that is easy to use and private too. So AirPort, what is it? This is the first thing: this is the AirPort base station, and it looks like this, right like that, and so the AirPort base station is really cool… And, of course, industrial design: So what about the computer side of things? Well, iBook is the first computer ever designed right from the start to be optimized for wireless communications, and so right in every iBook are two built-in antennas…Then, we have an AirPort card, a small little card, and the iBook is designed to accept it. So let’s take a look at that. As you know, Apple pioneered this way of adding memory without taking your whole portable apart through simply lifting the keyboard. Well, we have enhanced that now to take an AirPort card, and as you see, there’s a space right there in every iBook ready for an AirPort card, and you can drop one in, just like that, and connect the cable that comes from the antenna. Right? You saw that? I’ll go back. Just connect that cable and push it in, and now your iBook is AirPort functioning. You are on the wireless network. All the software detects the AirPort card and automatically sets it up for wireless networking without going through hours of configuring your computer. It all happens automatically. This has been a major effort on the part of Apple’s hardware and software engineers and also Lucent. This paragraph is a bit extraneous, other than the fact it is personally meaningful: my first Apple computer was an iMac G4, the following all-white generation, with the same AirPort card installation. I remember being amazed at just how easy it was to add wireless . And now, here I am, 22 years later, still using an Apple laptop to write this Article. Two weeks ago I wondered how long I was for the Apple ecosystem ; one product I was definitely not interested in was the then-forthcoming Apple smarthome product: What struck me about Gurman’s article is just how unenthused I am by an Apple smarthome product. Some of this is fatigue from a decade of Siri disappointment and skepticism about the company’s ability to deliver on a voice-centric product. More than that, however, I bristle at the idea of introducing Apple’s constraints to more parts of my life. Those constraints aren’t just about things like full disk access. To the extent that Apple delivers on integration with things like thermostats and door locks is the extent to which they work with 3rd-party device makers; the problem is that third party device makers mostly suck, particularly from a software perspective. Even if Siri were perfect, Apple will have the challenge of delivering an experience that isn’t defined by the lowest common denominator. What I’m much more interested in is controlling the software layer myself. The fact of the matter is that with AI you can decompile almost all existing software — there is a revolution happening in gaming over the past few weeks, as game after game is decompiled to source and ported to any platform you wish — and you can write your own. That means my software that interacts with my agent in the way I want it to for everything; that’s way more exciting than praying Apple delivers the right API and that 3rd-party developers don’t suck. That product is called Apple HomeView , and some prominent Apple observers don’t get the point. John Gruber wrote on Daring Fireball : My skepticism boils down to the question of why anyone would want to add one (or more!) additional ever-present screens to our homes and lives. Phones can stay in our pockets until we need them. Watches remain on our wrists. HomePods can be tucked away unobtrusively in corners, and remain fully useful. HomeView needs to be in a prominent location for its display to serve any practical purpose. Apple’s initial pitch for it doesn’t earn that prominence for me. I understand Gruber’s skepticism, particularly given the product’s truly atrocious introductory video . Beyond the overall stress-inducing nature of the suburban family scene depicted, most of the use cases, as Gruber notes, are nonsensical: to take a particularly egregious example, why would the teenage daughter look at a message from her clandestine boyfriend on the HomeView instead of her iPhone (which has to be present on the network and unlocked in the past several hours for that functionality to even work)? Apple was, in this particular case, trying to show off HomeView’s multi-user capability, which is based on facial recognition, but my biggest takeaway is that maybe highly produced marketing videos sold as product keynotes aren’t the worst idea in the world. In fact, I think that HomeView is pretty compelling. Smarthome functionality is genuinely useful: I have, of course, just laid out five compelling use cases for the HomeView, but it wasn’t hard! These are all real, genuinely useful capabilities for a new home device. And notice what the limiting factor is for the middle three: actually getting different devices to work together reliably. That’s why the other exciting part about Apple’s HomeView announcement actually hearkened back to the original AirPort: Apple Home Collection. From Apple’s press release : Apple today announced Apple Home Collection, a new lineup of smart home accessories — including indoor and outdoor cameras, thermostats, temperature sensors, and a video doorbell and door lock — designed in collaboration with LG Electronics and Schneider Electric. These new accessories are simple to set up starting with one tap with iPhone, and everything is managed through the Apple Home app — no separate app or account required. Each accessory is encrypted end-to-end in Apple Home, so only users and the people they choose can access their home data. Building on the thousands of Works with Apple Home and Matter accessories available today, Apple Home Collection offers customers a new array of recommended products to better understand what’s happening inside and outside their home, manage access, and keep the temperature just right throughout the day. Availability for all products begins in December, with select accessories available starting early 2027. “Apple Home Collection makes it easy to choose smart home accessories with confidence,” said Matthew Costello, Apple’s vice president of Hardware Engineering. “Working closely with industry leaders LG Electronics and Schneider Electric, we designed every accessory to work seamlessly with Apple Home, so managing your home is simple, reliable, and private.” Apple doesn’t have to do everything itself in the home, just as they didn’t have to invent wireless networking in 1999; what they need to do is “marry [partner’s] technology with [their] ease-of-use technology”, and I’m optimistic they’ve done exactly that with LG Electronics and Schneider Electric. The key detail is “no separate app or account required”; that points to deep integration with Apple products, from setup to day-to-day usage. Again, I’m not sure I’m the target customer for this (although the automatically unlocking door locks look awesome); my solution to incompatible or flakey integrations is to use AI to build my own customized software. I’m under no illusions, however, that I am a normal consumer who wants the benefits of technology without the headaches; I trust Apple, more than anyone else, to at least aspire to delivering on that vision, and these 2nd-party partnerships are a great start. The second part where you may trust Apple more than any other company is with privacy. Jobs was talking about privacy as a selling point 27 years ago, and Apple has only doubled down since then. In the case of HomeView specifically there is that facial recognition feature, tied to your own hardware; more broadly, if there is any company you might entrust with tracking your more private spaces it is Apple, both because of promises they make with their technology and also their consistent stance on not using customer data. Indeed, Apple’s privacy umbrella is strong enough that LG’s very sketchy privacy track record is likely to be a non-issue amongst potential customers. From Bloomberg, in 2016 : Apple Inc. has disbanded its division that develops wireless routers, another move to try to sharpen the company’s focus on consumer products that generate the bulk of its revenue, according to people familiar with the matter. Apple began shutting down the wireless router team over the past year, dispersing engineers to other product development groups, including the one handling the Apple TV, said the people, who asked not to be named because the decision hasn’t been publicly announced. Apple hasn’t refreshed its routers since 2013 following years of frequent updates to match new standards from the wireless industry. The decision to disband the team indicates the company isn’t currently pushing forward with new versions of its routers. An Apple spokeswoman declined to comment on the company’s plans. The official end of the line came in 2018 , five years after the last product was released, leaving customers in limbo waiting for updates that never came. That right there is one reason to not trust Apple in the home: the company already decided once that products that didn’t move the needle relative to the iPhone weren’t worth their time, even if delivering an integrated home experience was still something Apple was uniquely positioned to provide. Yes, by the 2010s most people had WiFi access points from their ISPs, or mesh WiFi products from the likes of Eero, but Apple still could have done something useful. For example, one of the biggest challenges in designing a wireless network is that the iPhone aggressively holds onto access points; if Apple had continued to design its own access points it could, even today, provide a superior experience. Alas, the business was deemed to be not big enough to bother. One reason Apple might be more interested this time, however, is the possibility of subscription revenue. Specifically, the cameras in Apple Home Collection will require a paid iCloud+ plan for recorded event history — higher levels for more cameras — which fits in with the company’s focus on services. Apple Music is also natively supported on the HomeView, whereas you’ll need a recently unlocked iPhone to use Spotify. Of course to some this might be another betrayal of trust: Apple used to sell you products, now they want to sell you on-ramps to recurring revenue. Both of these issues of trust, however, pale in comparison to the single biggest question facing HomeView: do you trust Siri to actually work? From Mark Gurman at Bloomberg : Apple Inc.’s new HomeView has been a long time coming — far longer than the company intended. I first reported on the device in January 2023, when Apple was aiming to bring it to market as early as the end of 2024. What should have been a relatively straightforward launch instead turned into a nearly two-year saga of delays. The culprit was Apple’s AI crisis, which left the company without the one piece of technology the HomeView absolutely needed: a working version of its revamped Siri assistant… From the beginning, the HomeView was built around a Siri that could retrieve personal content, distinguish between members of a household and show each person private information. It was also designed to be controlled primarily by voice, rather than through its touch screen. Without a serviceable version of the new assistant, Apple couldn’t deliver the experience it had envisioned. That left the hardware ready to go, but the software nowhere near finished. So Apple postponed the HomeView repeatedly — first until spring 2025, then summer, then fall, and then again throughout 2026 before finally unveiling it this past week. And the hardware betrays its age. With thick bezels, an A18 processor and 8 gigabytes of memory, this is clearly a product conceived years ago. Finished units have been sitting boxed up in warehouses for the better part of a year, waiting for the software to catch up. There is a world where Apple never gives up on AirPort, and instead uses it as a foundation to deliver the integrated smarthome in the late 2010s; in that world Siri’s performance is important but also less pressing given that some number of homes would already be locked in. The second world, which Gurman describes, is one where Apple delivers on the new Siri in 2024 like it planned, and the HomeView is its showpiece experience. This is still a compelling product in that scenario, where integrating information from your iPhone is close to the cutting edge of what AI is capable of. The world we are in in 2026, however, is a much different one. In this world Siri AI has shipped, and while it is more capable than what came before, it is much slower, and makes more mistakes with basic tasks that the deterministic old Siri handled reliably. Moreover, the competitive landscape is dramatically different: agents like Muse, Instinct, Dots, or Grok Bots not only integrate information but actually act on it; new Siri already feels long in the tooth. This is where a foray into the home is particularly challenging. One doesn’t replace one’s thermostat or cameras or doorbells every year; these are one-time purchases meant to last for a long time. Ditto cutting a hole in your wall to mount a HomeView, which certainly makes more sense for many of the product’s core use cases. Making such a commitment, however, means committing to Siri AI as the primary interface, and trusting that Apple will make it good. This is a costly choice, and not just monetarily. The real concern is opportunity cost: committing to a world controlled by Siri AI means forgoing a world controlled by any other AI. That’s too expensive for me; how many consumers, even those who trust Apple to make things work together, and who value the company’s commitment to privacy, will make a similar evaluation? The answer right now, in 2026, is probably not too many, which is to say Apple might have got this product out just in time. I think there is something here, even if Apple’s marketing team doesn’t seem to be able to explain it very well. At the same time, I think HomeView highlights some of the mistakes and shortcomings of former CEO Tim Cook’s tenure; earlier this year when Cook retired I wrote about his impeccable timing , both in terms of when he took over Apple, and also when he stepped down: To that end, it’s right that Cook is stepping down now. Jobs might have been responsible for taking Apple from 0 to 1, but it was Cook that took Apple from 1 to $436 billion in revenue and $118 billion in profit last year. It’s a testament to his capabilities and execution that Apple didn’t suffer any sort of post-founder hangover; only time will tell if, along the way, Cook created the conditions for a crash out, by virtue of he himself forgetting The Cook Doctrine and what makes Apple Apple. The Cook Doctrine states that Apple needs “to own and control the primary technologies behind the products we make”, but Apple doesn’t own and control the models underlying Siri; meanwhile, one of the things that makes Apple Apple is focusing on making great products that customers love. How did Apple’s obsession with services revenue fit in that rubric, particularly when said obsession rose in conjunction with stripping out every part of the business that didn’t move the needle in terms of revenue, even if it made for a better user experience? Privacy, meanwhile, is great as a strategy credit ; what happens when it gets in the way of making products that work? It is true that Apple’s AI approach has the benefit of not moving the needle in terms of costs, at least relative to its big tech peers. It’s possible that just as Apple is partnering with LG Electronics and Schneider Electric on home devices, the company will deliver compelling experiences through its partnership with Google (and surprising thawing with Meta via its Meta Superintelligence Lab ). After all, Apple hasn’t always done everything — Lucent Technologies once featured in a Steve Jobs keynote! The difference is that that was an Apple that was eager to race ahead, not simply catch up; Jobs was planting seeds for the future, seeds that Cook harvested. Cook did make investments that matter, particularly in Apple Silicon (even if that effort started under Jobs), and in wearables; the job for Ternus will be ensuring that Apple’s “ease-of-use” technology is not just easy but actually useful. Years ago I set up a small monitor on the side of our condo’s living room for the kids to play video games; I happened to have a Raspberry Pi on hand, which I used to set up a service called DAKboard . DAKboard showed the time, the weather, the family calendar, and a rotating collection of photos. It has, in the intervening years, been one of our most-used and most-beloved pieces of technology, looked at multiple times a day every day. Thermostats are finicky and hard to use; it’s much better to be able to program them from your phone, or from a touch device. The problem for me in my current home is that my thermostats seem to mysteriously lose their connection to my home automation system every few weeks. Doorbells are critical in a world of e-commerce, especially when it comes to the dreaded “signature required”; incorporating them with your devices, along with a screen to see who is at the door, is a no-brainer. Unfortunately for me my doorbells also seem to get randomly disconnected, and I never notice until I miss a delivery. Cameras are a useful security measure, but only if you can actually view them. The issue is — you guessed it — that they often become inaccessible or are non-intuitive to use, particularly the moment you need them. Sometimes I want to access information without using my hands, like when I am cooking. You can prop up an iPhone or iPad in the kitchen, but what do you do when it goes to sleep in the middle of a recipe?

0 views

Static Analysis for the Uninitialized

I really enjoy learning new things in my free time. Lately I’ve been studying this book on Static Program Analysis . The book is very good, but some of the formulas are quite dense so I like to try writing them out in code. The chapter I’m currently reading (chapter 9) has a section on finding possibly-uninitialized variables using bipartite graphs. I’ve found it to be quite enjoyable, so in this post I would like to describe, in my own words, how to do it. We’ll start by analyzing some code from a toy programming language the book uses called “TIP”, and then we’ll use the techniques we developed to analyze some Ruby code. In other words, we’re going to write a program to analyze programs. We’re really going to be meta-programmers today! The TIP programming language is like a very very simplified version of JavaScript. Below is the code we’ll be analyzing: This example is taken straight from the chapter. In TIP, you declare variables with the keyword kind of like in JavaScript. In chapter 9 of the book, the TIP language only has integers; later chapters add pointers. In TIP, 0 is considered false, and there is a special function that returns an integer input from the user. Each line in the above code has a comment indicating which variables are possibly uninitialized. I keep saying “possibly”, and I’ll explain why later. The first line declares the variables with , and all variables start as “uninitialized” when they are declared. The second line gets input and assigns it to , so now only and are uninitialized. The third line adds and and assigns it to . On this line, is still considered to be “uninitialized” because is uninitialized, and the value of depends on the values of and . The fourth line is an if statement, and whether we take the if statement depends on input from the user. In other words, we can’t statically determine whether this statement is taken or not. The if statement doesn’t impact the “initializedness” of any variables, so all variables maintain their state ( and are uninitialized). If we take the branch, the 5th line will assign a value to , so at that line only is uninitialized. On the 6th line, we can’t know whether the if statement branch executed, so we have to say that and are possibly uninitialized. This is why our analysis is only giving us a “possibly uninitialized” result. If the branch is taken, then will be initialized, otherwise it won’t. But since we can’t know whether the branch will be taken, we have to be conservative and say that may be uninitialized on line 6. These two states, and , form a two element lattice, with on top. The top is the “safe” answer: it’s never wrong to say a variable might be uninitialized, it’s just less precise. When two paths in the code meet, like at the end of the if statement on line 6, we take the higher of the two states (because the less precise decision is also the “safe” one). On one path is initialized, on the other it’s possibly uninitialized, so after the if statement it’s possibly uninitialized. The rules for each line in uninitialized variable analysis are so-called “distributive functions”. For example, take the rule for line 3, . If we feed it the set , we get the same answer as feeding it and separately and then taking the union of the results: . This is just like in math class where we could say . In the case of a two element lattice and an analysis that uses a distributive function, we can represent the variable states using a bipartite graph. The book works out the proof for this, but I’m going to omit it (because I want to get to the coding part). But if you want to see the proof, check chapter 9! A bipartite graph is just a graph with “two sides”. Nodes on one side of the graph will connect with nodes on the other side of the graph, but never with their own side. I imagine it like two football teams tackling each other, each player is a node, and tackling someone else is an edge in the graph. Hopefully the players don’t tackle people on their own team, and they form a bipartite tackle graph! In our case, each node in our graph will represent a variable in the program, and we’ll have one extra node that represents “uninitialized”. For one graph, we’ll double those nodes, and use the edges to represent the flow of data through the code. For example, let’s look at the bipartite graph for the first line, : The node on the left represents the value “uninitialized”. On the line, the “uninitialized” value flows from to the , , and nodes. Next let’s look at the graph for line 2, : In this graph, the uninitialized node flows to itself. The variables and haven’t changed, so whatever value was in and just flow to the other side of the graph. The variable got initialized from , so no value flows to the other side of the graph. The reason no value flows is because we’re tracking “uninitializedness”, and on this line becomes initialized, so the absence of an edge means we got a value. If we repeat this value flow process and then line each graph up next to each other, we’ll end up with a graph like this: A black dot in the variable’s column indicates that the variable is possibly uninitialized at that point. Grey dots and lines indicate paths that don’t occur because the link was severed earlier. The dotted lines indicate alternate paths the code can take; an if statement has two outgoing paths. Looking at the graph we can see that (obviously) uninitialized ( ) is always uninitialized (we don’t bother to print that out because it’s not very helpful). We can also see that the black dots correspond to the “uninitialized variable” comments from the example code. For example, right after , the and variable have a black dot indicating that they are possibly uninitialized. If we assign each variable a number (and reserve 0 as the number for “uninitialized”), we can represent this bipartite graph in Ruby using a bit matrix. The graph needs to store a connection between any of the variables, and an “on” bit represents an “uninitialized” state from our lattice flowing from one variable to another. Since we need to be able to record an edge from any variable to any variable (plus the uninitialized value), the number of bits required is . Our example case has 3 variables, plus the extra variable for “uninitialized”, so we can do it in 16 bits. In practice though, to make accessing the data easier, we’ll align on a byte: The way we use this class is by assigning numbers to variables and then calling with the edges we need. For example, to represent , we need to connect “uninitialized” to the , , and variables. If we’ve assigned them numbers, we can do it as follows: Now we can represent the data flow rules for any line in the program. The next step is we need a way to connect graphs together. To do this, we’ll add another method that takes as input a list of “possibly uninitialized variables” (these are also known as “facts”) and returns a new list of “possibly uninitialized variables” based on the data flow rules for that graph. Since the input variables are just numbers, we can use each one as a row index into our bit matrix. Practically speaking, this means we bitwise OR together the rows for each input variable, and then get the position of the “on” bits in the output. Here is the code for the function: Let’s add a second rule for : In the above rule, just as in the visualization above, we connect the uninitialized nodes, then we connect to itself and to itself. These “self” connections mean “whatever value was in as input, we’re going to pass that along as output”. Now we can use the method and chain the two graphs together: At the start of the program nothing has been declared yet, so the only fact is “uninitialized” itself ( ). If we apply that to the first line, we see that all of the variables are “possibly uninitialized” (as expected). We can take the output of the application and feed it as the input to the next graph, and we see that the uninitialized variables are 2 and 3 (or , and ). Now all we need to do is define the rules for each line of code and apply them, and we’ll be able to calculate which variables are possibly uninitialized! Next we’re going to create a class that lets us record rules for each part of the program. The example code we wrote above works well for straight-line code since we can just apply the data flow rules from each line to the previous line. But the example program we have contains control flow and we’ll need a way to model the “dotted line” from the visualization above. To do that, we’re going to construct a simple control flow graph. A control flow graph (or CFG), is constructed from “basic blocks” where each block contains “straight line code” and ends in either a jump or a return. Each block has up to two outgoing edges, and those edges connect to possible jump targets. There are other ways to define a basic block, but this is my blog, so my rules! First we’ll define a class and a class. The class just holds on to the source line (a string for printing), and a graph representing the rules at that line. The class holds the list of objects that make up the block. It also contains a list of successors (jump targets) as well as predecessors (basic blocks whose jump target is the current block): Next we’ll define a class that has a bunch of helper methods that let us construct a CFG along with a graph for each line. I’m not going to explain all of the lines of the class because I think using the class is a better way to explain it. However, the full source is below. Let’s use the class to define all of the data flow rules for the sample TIP program: First we define a new program class. Then we ask the program class to record a source line of TIP along with the data flow rules for that line of code. I added lots of comments to explain the code, but let’s revisit one excerpt just to make double sure: Here we’re asking the program to record the TIP source code , and the data flow rule for this line is that “uninitialized” flows into , , and . This is exactly the same as the bipartite graph we created above, but this time we’re just recording that graph alongside the TIP source code. After we’ve recorded all of the rules, we call on the program so that it can calculate and set predecessor edges. We’ve got multiple graphs going on here. We’ve got a control flow graph that represents the program overall, and a bipartite graph representing data flow at each line. Our goal is to walk the CFG, and for each block calculate variable definedness at each line. The input state for each block is the union of the output state for that block’s predecessors. In other words, in order to analyze the whole CFG, we only really need to record the final state at the end of each block. Also, each calculation cares what happened in the past . For example, the definedness of the variables at line 2 care about what happened at line 1. This means we have a forward dataflow analysis . Any time the facts we derive depend on what happened in the past, it means we need to move forward through the code. So we define a strategy class that lets us analyze the CFG by moving forward through the code: In the above class, the method takes a basic block, looks up the predecessors for the block, then unions the output of those blocks. The function takes a block and some input (which happens to be the return value of ), and for each line of code in that block computes output facts based on the input. Those output facts are the “possibly uninitialized variables” at that line. Since we really only care about the state of the world at the end of the block, we just use an (a left fold for scheme people) over the code in the block. If, after analyzing all lines in the block, the facts are the same as what we had recorded previously, will return false. Otherwise, it saves the facts for that block and returns true. The method returns all blocks in reverse post-order (the traditional order for doing forward analysis that my grandparents used), and the method returns the successors for a block. We’ve got our CFG, and we’ve got a strategy for iterating the graph and analyzing it. Now we need to actually do the analysis. We discussed earlier that this problem is a two element lattice with a monotonic function (it moves up the lattice, never down). That means it’s perfect for a worklist algorithm. Our worklist algorithm is actually quite simple, it’s just this: Given an iteration strategy, ask for a list of blocks to process. While we have blocks to process, get a block. Ask the strategy for the input facts for that block, then ask the strategy to record output facts for that block given the input. If we learned something new ( returns true), then ask the strategy for children of that block and add the children to the worklist (if they aren’t in the worklist already). After this processing finishes, the hash inside the object will contain possibly-uninitialized variable information for each block. We can iterate over the blocks in the analysis and print out the possibly uninitialized variables for each line: Since we only recorded output information for each block, we have to do some extra processing at the end to print out the facts at each line, but if we run this code we finally get this output: Whew. That was a ton of work. But the good news is that we can reuse this framework for other languages too. I’m not going to explain the intricate details of this code, but we can use Prism to parse Ruby and feed that into our class. The function walks the Prism AST and records a rule for each statement, using the same kinds of rules we wrote by hand for TIP. Just to emphasize this, we wrote all of the data flow rules by hand for TIP, but our Prism code does it automatically based on assignments in the Ruby code. Once we get this into the program class, we can perform the same analysis on this code: (The curly braces are just how our class prints if statements, even for Ruby.) If you actually run this Ruby code, will raise a , because hasn’t been assigned yet so Ruby thinks it’s a method call. That’s exactly the kind of bug this analysis is meant to catch! You can find the full source for this program here . I feel like finding uninitialized variables isn’t that impressive. But the power in the technique here is that we can do any kind of analysis using this framework as long as the facts we track are a finite set, and the transfer functions are distributive (as I mentioned earlier). (The book calls this framework the IFDS framework, though I’ve omitted part of the full framework in this post). For example, we could use this same code to do “taint” analysis: “does this variable hold untrusted data?” If we were to number expressions and perform a backward analysis, we could discover what the book calls “very busy expressions”. A “very busy expression” is an expression that will definitely be evaluated no matter which path the code takes, before any of its variables change. For example: In the above example is considered “very busy” because we calculate it regardless of which branch the if statement takes. That means it is a candidate for hoisting above the if statement. Anyway, I’m having a lot of fun reading this book and I just wanted to share the stuff I’ve learned so far. Have a good day!

0 views

Trying Myna on Ubuntu 26.10

A new, experimental feature in Ubuntu is Myna , a local speech-to-text engine. After giving it a shot, I can say it works really well, and feels native to the system. I've tried a few alternatives on Linux, and none of them have been as smooth or responsive as Myna. Everything from the on screen display as it transcribes, to the little "Ping" sound oozes polish. I highly recommend giving it a shot!

0 views

UUIDv7 doesn't have the properties you think it does

I’m going to call it. UUIDv7 is weird. Most blog posts about UUIDv7 tout these benefits: But none of these properties are strictly held. Certain RFC compliant implementations of UUIDv7 violate these properties to extreme degrees. The only useful property UUIDv7 appears to strictly provide is uniqueness and therefore collision resistance. I’ve already discussed how UUIDv7 IDs can be guessable , so this post explores the other properties. Superficially, it seems that embedding a timestamp in the ID can remove the need to track the creation time in a separate database column, providing marginally more efficient database operations. If you need to list things ordered by creation time very often, it’s useful if the primary index gives that behavior, removing the need for another index. Unfortunately, the timestamp embedded in a UUIDv7 ID may not relate to the object creation time. The Postgres docs for helpfully warn that “the extracted timestamp is not necessarily exactly equal to the time the UUID was generated”. RFC 9562 allows implementations to alter the timestamp field, using values that aren’t strictly derived from the system clock. This relates to the tension between UUID monotonicity and timestamp accuracy. In certain scenarios, the difference between the timestamp and the current time can be arbitrarily large. Implementations MAY alter the actual timestamp. — RFC 9562 §6.1 This specification makes no requirement or guarantee about how close the clock value needs to be to the actual time. — RFC 9562 §6.1 … implementations MAY increment the timestamp ahead of the actual time … — RFC 9562 §6.2 Incrementing the timestamp ahead of the system clock is an interesting problem. If the generator is seeing so much load that a counter field is regularly overflowing then the timestamp could accelerate into the future. Using a sufficiently large counter would be wise and the RFC says the minimum size SHOULD be 12 bits. A counter overflow would require a pretty aggressive creation rate, over 4,096 IDs per millisecond per node, which is beyond the limits of many systems. This overflow becomes relevant, however, if the timestamp freezes; which I’ll discuss in a later section. One prominent implementation that increments the timestamp is the Python standard library’s UUIDv7. The increment happens only in certain circumstances, like when the counter overflows. Unfortunately, the generator can get stuck in an increment cycle if the clock ever jumps backwards and the timestamp can race ahead of the system time by an arbitrarily large amount. Here’s a simple example: Which gives: We expect the difference to be 3600 seconds (one hour) as the implementation refuses to allow the embedded timestamp to jump backwards and we expect the difference to decrease as the system clock catches up to the frozen timestamp. But when the load is above one ID per millisecond the difference will increase without bound. At lower loads it will take longer for the system clock to catch the timestamp, but we don’t see the runaway effect. The related issue shows Python developers reasoning that this is consistent with the RFC, is consistent with other implementations, and that there isn’t “much we can do” on a “flawed system”. I think these points are correct as I see this same behavior in other implementations. Nevertheless, it would be helpful if existing UUIDv7 implementations could handle system clock jumps without runaway behavior. There are many real-world examples of clocks jumping backwards, even decades out of sync in time-sensitive environments. Embedding the timestamp in the ID means that you cannot share the ID without also sharing the timestamp. It’s pretty difficult to think of an example where this really matters. One example could be a user profile page that doesn’t disclose when the account was created, but the UUIDv7 ID in the URL leaks the high-precision timestamp. This issue would typically be very low on my list of security concerns because I find much more severe problems when I do security assessments. Nevertheless, there are contexts where this matters and engineering resources would be focused on addressing it. If you’re in the latter camp, be wary of UUIDv7 leaking metadata. This section is even more pedantic, so skip ahead if you’ve had enough. Briefly: UUIDv7 IDs provide some sort of rough order, which may be suitable for your requirements. When I was reading the UUIDv7 RFC I was surprised to see it describing a method for creating IDs across different nodes that are monotonically ordered. This was proven impossible back in the 1970s , and lead to the development of vector clocks and similar technology. At a high level, the problem is that system clocks cannot be synchronized to a suitable precision. Ordering things by timestamp only works if you know precisely what time it is. Any uncertainty in the time results in uncertainty of event ordering. Succinctly: Timestamps are only time-ordered if you know what time it is and you don’t know what time it is. For this reason, similar ID formats claim to be nearly sorted. It seems odd that UUIDv7 makes a stricter claim and does not deliver on them. At the very least, the challenges of synchronizing clocks across systems make the millisecond and especially the sub-millisecond timestamps quite suspect. But even on a single node, using a single implementation, UUIDv7 IDs are not strictly monotonic. The easiest way to get out-of-order UUIDv7 IDs is to use an implementation that uses a millisecond timestamp without a counter. This approach trivially generates out-of-order IDs inside a small for loop . So no, there’s nothing in the UUIDv7 specification that would ensure the IDs are strictly monotonically increasing. Specific implementations may do better than others (with sub-millisecond timestamps, counters, well-synchronized clocks, etc), but we’ve known since the 1970s that this problem is not strictly solvable. In UUIDv7’s favor, roughly ordered IDs are still quite useful. So don’t rip UUIDv7 out of your systems just yet. Just be wary of what assumptions you have. The RFC has lots of discussion about the handling of clocks that jump backwards. Timestamps are only time-ordered if clocks tick forwards, so special care is needed. We’ve already discussed one mitigation: tracking the last generated timestamp to ensure that an earlier timestamp is never used. To do this safely you’ll need to write the last used timestamp to persistent storage, such that you can read it again after a system reboot or a process restart. I’ve looked at several UUIDv7 implementations I couldn’t find one that writes timestamps to persistent storage. So implementers seems disinterested in addressing the issue and they generate out-of-order IDs when a process restart follows a clock jumping backwards. Looking at real-world clock synchronization problems, you’ll find many examples of clocks getting set to future dates . When this happens, the backwards jump would align the timestamp to the actual time, but a last-used-timestamp guard would force timestamps to use keep using that incorrect timestamp until the system clock catches up. If the system clock takes a long time to catch up, you may start experiencing counter rollovers. My mental model for UUIDv7 is that it’s a mash-up of a bunch of different ideas which implementations are free to choose as they see fit. There’s a wide variance of properties that UUIDv7 implementations can provide, with varying degrees of certainty they can successfully provide those properties. If you’re building your own implementation you can likely build something that has the properties you need. But most of us want to reach for an off-the-shelf version, especially when standard libraries provide an implementation, so we’re generally at the mercy of someone else’s implementation decisions. Implementations can change over time, making broad changes to their behavior while still being RFC compliant. Distributed systems may have multiple implementations across their subsystems, each with distinct properties. The only thing you can really expect is strong collision avoidance and ID uniqueness. Be sure to ask these questions when picking a UUIDv7 implementation: Unfortunately, this sort of analysis is much more difficult than building an RFC compliant generator. Authors of UUIDv7 generators may not know the answers to these questions and may themselves be surprised that the RFC does handle this for them. Hello! I'm Robert Alexander, a DevSecOps consultant available for contract work . This blog features some of my work and thoughts on software, the cloud, and security. You can subscribe to my posts with your favorite RSS client and follow me on Mastodon . If you'd like to show your appreciation and help support my writing, you can do so via this link. monotonically increasing IDs a helpful timestamp of when the object was created; and unguessable IDs Is the implementation compliant with the RFC? What additional properties does this implementation guarantee? Under what limits can those guarantees be met? Are there any assumptions required for these properties to hold, such as having an accurate system clock? Under what conditions will the implementation alter the timestamp? How guessable are the generated IDs?

0 views

How I am reading more

We live in what is being referred to as a “ post literate society ” in which 40% of Americans did not read a single book last year . This is mind blowing to me, but - I can also see that with screentime (on a phone alone) being somewhere over 5 hours a day , it makes sense where most of everyone’s time is going. However, if we can replace even one of those hours of that screentime with reading books, and that will amount to reading far more than 0 books per year! I generally read around 20 books per year, but I figured that I could do far better than that (and did in 2023 ). That year also coincided with massive personal, spiritual, and professional growth - I don’t think that this is mutually exclusive and is probably correlative. This year, I made a resolution to get back at it, and this is how I am reading more. The most important thing I think nearly anyone can do to read more is reduce screentime on a phone. By simply installing Kindle, KoReader, Libby, AudioBookshelf, MuPDF, or one of many other reading apps, we can use this in lieu of doomscrolling social media and news websites. Going further, we can delete social applications, youtube, and even the browser, and replace any idle time at checkouts, commuting, and where you would historically be “wasting time” with reading and listening to books. We are simply going to “waste time”… better! While I personally don’t subscribe to this method in that I don’t retain nearly as much that is being said in audio form (this is why I don’t consume podcasts, either), some swear by the ability to read while on the go simply by listening to books. If it works for you, then awesome! I just don’t seem to benefit much from audiobooks. I may revisit this though for driving and the gym and update this post if I do use audio more often. My wife hates this one trick! This, for me, has been the biggest eye opener and allowed me to read ~100 pages per day over the past month or so of this experiment. I simply have books lying around in my office, in the living room, my Kobo sitting next to the bed, etc. and instead of picking up my phone, I pickup a book instead. All things are downstream of how we spend our time - time spent reading begets more reading. Some may not like this in that they want to read one book to completion before starting on the next. I personally have anywhere from 5-15 books on the go at once. Off the top of my head, here is a non-exhaustive list of what I have on the go: I find that reading this way is tremendously interesting in that there is “cross-pollination” between domains and a growing connection between all things. You will find authors across time and geographical location discussing the same quote, book, or idea, across domains of theology, physics, computer science, design, art, everything. I then sit and meditate with what I’ve ingested, and create connections of my own. It’s fascinating. Not only this but, it’s a “cheat” in that if I get bored with one book/topic, I just go on to another, in one big circle. Boredom doesn’t mean ceasing to read, just selecting something else that I am actually in the mood for. The very first thing I do in the morning is make the Sign of the Cross and Pray. The very next thing I do is sit down to read. I have started to wake up earlier in order to get the time to myself so I can do this, and it is truly awesome to get an hour or so or reading in before starting work. I read 10 pages, do some pushups and stretching, read 10 more pages, more physical activity, and repeat for about an hour. Most days I get about 30-50 pages in before anything, and I feel that it gets the wheels turning in my mind for writing, creating, etc. as I have always found reading to be “conversational”. I am not usually gung-ho in the morning to immediately begin working, and this has immensely helped my ability to drop into work and the rest of the day. Try it out! If you are so inclined to use applications such as Goodreads or the like, then this can be a fun way to keep track of that which you are reading and “compete” with friends. I’d recommend against giving Amazon all your data, but you do you. I also think that reading has become an extension of social media in that there is an element of “one-uppmanship” which I don’t care to participate in. I personally keep a /reading page on my blog for the current year, and keep track that way. It’s a fun way to discuss books when people can see what you’re reading on your blog and it’s a good conversation starter. I have always hated the rationalization that “reading is too slow”, or that “I have no time to read!” As I said above, if you have time to scroll your phone, you have time to read and converse with the greatest minds that have ever lived. We need to slow down more than ever in this crazy, accelerating world. I find that almost no one sits and chews on ideas anymore, and that is detrimental to the future of humanity if we are not to create polymaths and people of skill. If we don’t have time to read, we don’t have time to grow, and that is simply not true. So, read more! I am thankful that my parents and teachers instilled a love of reading in me from a young age. Truly, one can learn about anything and everything if we only pick up a book and start flipping through. I personally don’t want to live in a post-literate society, I want to discuss these great works and continue to learn from everyone that’s come before, so that is why I choose to keep reading, and to read as much as I possibly can. Try it out for a month, and see how much you fall (back) in love with reading. I think we have all just forgotten how amazing it is to pick up a great book and lose ourselves in the worlds and ideas of another’s mind. As always, God bless, and until next time. If you enjoyed this post, consider Supporting my work , Checking out my book , Working with me , or sending me an Email to tell me what you think. The Brothers Karamazov The Go Programming Language The Art of Unix Programming The Republic An Introduction to the Devout Life The C Programming Language (K&R) Structure and Interpretation of Computer Programs Chruch Fathers Against the Machine The Bible (Everyday, first thing I read) Operating Systems, Three Easy Pieces Computer Systems: A Programmers Perspective Designing Data-Intensive Applications

0 views
Sean Goedecke Yesterday

What requirements don't you have?

When designing software, the requirements you don’t have are as important as the requirements you do. Identifying what you can compromise on — what can be slow, or stale, or inflexible — is usually the key to an elegant design. For instance, take preforking web servers like Unicorn . Because they lack the feature of shared mutable state between server instances, they can run each server in its own process, which provides isolation for free. Because Unicorn specifically ignores the problem of slow client handling 1 , it can queue requests directly on Unix sockets, drastically simplifying the implementation. Because S3 does not support atomic multi-key updates — you cannot update multiple blobs in a single transaction — it can store data at the blob level however it chooses. That makes it much faster, since reads and writes don’t have to cross storage partitions, and much easier to scale, since less coordination means fewer sources of truth. StatsD uses UDP by default, which means it doesn’t guarantee that every piece of data you send makes it into storage. In exchange for dropping that requirement, it incurs much less network overhead, which is a big advantage for a stats aggregation service that’s constantly shoveling data over the wire. The general design approach of fanning out data to an edge cache buys a lot of speed and scaling by dropping the requirement that data must always be up-to-date. SQLite buys operational simplicity — it can run out of a single file! — by dropping the requirement of concurrent writes. By accepting high tail latency 2 , Cursor can scale their distributed git backend more easily. Well-designed systems turn their weaknesses into strengths. Anyone who’s spent time designing real-world software (or who’s studied distributed systems ) knows that system design is a process of compromise. If you attempt to satisfy every single potential requirement — speed, concurrency, up-to-date data, a simple interface, supporting complex user behaviors — you will fail to design a working system at all. Figuring out what requirements you can relax is difficult because it combines both business and technical expertise . It is technically challenging to identify precisely the level of staleness that a particular design change will allow; it is likewise challenging from a business perspective to determine whether that level of staleness is acceptable to users. In most cases, an engineer who understands the technical side must try and explain it to a product manager, who can make a judgement on the business side. But this is a very difficult partnership to get right. Engineers and PMs have different incentives and little ability to check each other’s work, which makes it hard to build trust . Without trust, the product manager is liable to avoid giving any ground at all 3 , which leaves the design in an impossible state. This is an underappreciated reason why solo developers or startups can sometimes run rings around larger companies. Because the technical and business decisions are united in a single person, they can make design tradeoffs that would be impossible for a large company, enabling them to build systems that are far more elegant and powerful. Knowing what requirements you don’t have becomes far more important when working with coding agents. Frontier models are very capable, but they have all gone through the purifying flames of RLVR : like high-achieving schoolchildren, they are obsessed with satisfying the Grader. On top of that, they have very little business context compared to an experienced human. That often manifests as them catching correctness or consistency “bugs” that are really just hypothetical unsatisfied requirements. For instance, it’s not uncommon for an LLM to casually introduce a mutex or other concurrency mechanism to ensure that two pieces of semi-related data are kept in sync, even if not told to do so. I’ve seen LLMs add weird checks in the middle of request handling to ensure that some already-checked piece of data hasn’t changed mid-flight, even if that wouldn’t successfully prevent the feared TOCTOU bug 4 . LLMs are obsessed with edge cases like “what if the current user loses their admin status in the middle of us handling one of their admin requests?” 5 , or “what if the cache in storage partition A is updated a nanosecond before the one in storage partition B, leading some users to see different data?“. Particularly if run in a loop or told to “make no mistakes”, they will pile on cases like these until they’ve transformed your four-line change into a thousand-line monster. This is why I’m confused by some people’s claims that code review is dead . About half the time I review a large AI-generated change, I notice some unnecessary requirement that makes the diff more complex. When I dig deeper, the LLM invariably introduced this requirement on its own. When working with a cache, I will often spell out in my prompt that I don’t mind the data sometimes being stale or briefly inconsistent between cache instances. When reviewing Golang code, the first thing I do is scan for added mutexes or layers of indirection that don’t look necessary to me. If you allow requirements like these to propagate unchecked through a codebase, they will petrify the system over time. The whole thing will be such a mess of checking and re-checking and holding locks and enforcing consistency that it cannot be scaled at all. Keeping systems elegant requires a ruthless focus: on accepting stale data or occasional tail latency, on avoiding all but critical instances of coordination, and in general on figuring out what requirements you don’t have to satisfy. The problem: if an HTTP request sent by someone with slow internet trickles in one packet per second, does that have to tie up a server process for the whole time? Unicorn’s answer is ‘yes, so put nginx or HAProxy in front of me’. When a read request hits a stale storage node, that node must update itself before responding. I’ve also seen this happen in reverse, where the product manager desperately tries to convince an engineer that some level of stale data is acceptable, while the engineer digs their heels in and insists on the “perfect” system. The consequences are similarly dire. Of course, simply doing a separate check shortens the TOCTOU window instead of removing it. In every single system I’ve worked on, it would be fine to simply carry out (or fail) the admin request: if somebody was allowed to perform some operation 10ms ago, it’s likely not a disaster to let them perform it now. The problem: if an HTTP request sent by someone with slow internet trickles in one packet per second, does that have to tie up a server process for the whole time? Unicorn’s answer is ‘yes, so put nginx or HAProxy in front of me’. ↩ When a read request hits a stale storage node, that node must update itself before responding. ↩ I’ve also seen this happen in reverse, where the product manager desperately tries to convince an engineer that some level of stale data is acceptable, while the engineer digs their heels in and insists on the “perfect” system. The consequences are similarly dire. ↩ Of course, simply doing a separate check shortens the TOCTOU window instead of removing it. ↩ In every single system I’ve worked on, it would be fine to simply carry out (or fail) the admin request: if somebody was allowed to perform some operation 10ms ago, it’s likely not a disaster to let them perform it now. ↩

0 views
Unsung 2 days ago

Motor, motor memory

While I didn’t have as much fun with car lights , I experienced another nice motor memory moment last week when using CarPlay. During my drive, I wanted to ask the new Siri something – but as only an occasional driver, and my phone out of sight, I was puzzled as to how to actually invoke it. I did see the new Siri app icon appear in the sidebar on the car’s screen, but tapping on that only showed me a list of prior conversations. Sure, I could probably initiate a new chat by tapping the button in the top right corner, but that corner felt really far away from where I was sitting, and didn’t feel inviting to someone who – just as a reminder – was driving a car at that time: So before giving up, I did one thing that somehow felt very natural – I pressed and held the “home” button in the bottom left corner: And… it totally worked. I feel that with any good motor memory story , your fingers do something seemingly on their own, and then it’s up to you to figure out why they did so. I believe in this case they did so because Apple built a good set of overlapping gestures and expectations: So, kudos to the many designers on sustaining a stable gesture system that lasted decades, and embedded itself in my fingers so well that it felt completely natural to invoke in a situation I really wasn’t allowed to split my attention or play with the interface. (An extra delightful moment in that last video – note how the physical home button and the virtual Siri button match in size.) In many other places – iPhone, Apple TV – you long press a physical button to invoke Siri. Also, on Apple’s touch devices and on Apple TV, “long press” on a touch target has been a consistent entry point to an “advanced function” in a same way right click is on desktop. Lastly, on earlier iPhones asking for Siri was literally a long press of the physical home button:

0 views
Kev Quirk 2 days ago

2026-10-18 13:22: Terence Eden asking on Mastodon what people's setups look like. Here's mine - 38" ultrawide...

Terence Eden asking on Mastodon what people's setups look like. Here's mine - 38" ultrawide LG monitor that docks to my Framework 13, Fully standing desk, fish tank and motorbike helmets on the wall. I love my home office, but I do like heading into the office too. Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .

0 views