January 2023



I shied away from mentioning that Milo was ill last month. I guess I was hoping that he’d bounce back soon, and I didn’t want to worry anybody. But January brought terrible news, as it seems he has lymphoma. He’s started chemotherapy, and I hope I get to mention what he’s been up to on plenty more pupdates.

Good Apple

I previously mentioned that Apple had been great in sorting out a replacement iPhone, when my daughter’s SE2020 failed. Well… she broke the screen on that one, and once again Apple came through with a repair that got it working again. Nothing for free this time, but the £159 to get the screen repaired was a lot less than buying a replacement handset.


Back when I was in the Navy I applied for a credit card that was issued by MBNA. They were arsey about my address (a Naval base) and wanted my service number, which seemed like something they’d never inflict on a civilian. So I decided to take my business elsewhere.

Many years later MBNA took over a loyalty card I’d got, and then the loyalty card was withdrawn, and MBNA gave me a cashback card offering 0.5% cashback, and market rate FX. It was a sweet deal, and I used it as my main card for many years (despite the FAR too frequent declines on Apple Pay).

It seems sadly they decided to get rid of me as a customer, and started pulling out the reversion marketing tricks.

It started with my trying to pay for my daughter’s university accommodation. A chunky online transaction, but one I’ve done before with that card. First attempt, declined – maybe I got the SMS code wrong? Second attempt, declined – I definitely got the SMS code right that time; MBNA lose the business, and I use another card.

The following day I tried to buy some clothes online. Declined. Then my wife calls to say her companion card has been declined in a cafe. I call customer services, they say call the fraud team. I called the fraud team, who (eventually) tell me that both cards will be good to go again in 10m.

An hour or so later I buy something on Amazon; and a bit after that there’s an email to say that the payment’s been declined.

I call the fraud team again. This time they tell me that Visa has put the card on ‘3 day hold’. After a bit and back and forth I’m told I can make a complaint, and we start that process. They hang up on me before the complaint is registered.

So now I have a new Amex Platinum Cashback card, and a John Lewis Partnership Mastercard.

The miserable thing is that those cards come out top in customer satisfaction, at less than 75% :0

It seems there’s no longer such a thing as a GOOD credit card, just (sometimes) less bad ones; but if anything goes wrong the experience will be awful. All the online reviews are a sea of 1*s recounting awful experiences (though no mention elsewhere of ‘3 day hold’). My read is that fraud has become so endemic that all customers are treated as psuedo-fraudsters, and it doesn’t matter how much business you bring in.

Skiing again

After almost 4 years I’m back on the slopes. This time in Courchevel (after my sister recommended The 3 Valleys). I’ll follow up with a full report, but so far the skiing has more than made up for a less than ideal journey to the resort.

Contact lenses again

I wore contact lenses all day every day for most of my adult life. Then middle age long sightedness teamed up with the short sightedness I’d had since my teens, and contacts became less practical. I still wore them for things like skiing though. But I haven’t been skiing for four years, so it’s kind of weird to be using lenses again. Extra weird is I’ve managed to lose my right lens on the final run down for the past two days. Maybe the visor on my new helmet doesn’t keep the wind out as well as my old goggles?

Solar Diary

January brought a cold snap, but that meant quite a few sunnier days, so generation was almost back to November levels with 110kWh.

Still no word from EDF on Smart Export Guarantee.

Beating Beat Saber

More lousy weather, and a sick dog, has meant less walking, so (particularly at weekends) I’ve been topping up my exercise once more with a bit of ‘swords’. I got the Lady Gaga pack, which is 100% bangers. There are a couple of harder ones in there, but I managed Full Combo first try on one song, and most of the others feel easily in reach.


Milo was only 18 months old when we noticed the lump on his neck, and it took some weeks to reach a diagnosis, but it seems that he has cancer (bad), specifically lymphoma (very bad), more specifically lymphoma with Mott cell differentiation (aka Mott cell lymphoma [MCL], which is maybe less awful than other types of lymphoma). He’s started on chemotherapy, and early signs are promising.

Milo sporting the compression bandage he got at the injection site for his first round of chemotherapy


I expect there will be two types of people reading this post:

  1. People who know me, and perhaps know Milo from my daily #pupdate posts on Twitter.
  2. People who’ve got a sick dog who are looking for more information. I hope this helps, but I caution that this is the story of one little dog, with his own specific set of circumstances; so please talk to your vet about your own dog’s symptoms and treatment.


From first noticing that something was wrong (a lump on his neck) to a lymphoma diagnosis from a scan took 7.5 weeks. This was pretty scary when reading online that the average survival for a dog with lymphoma is 4-8 weeks. We lost a lot of sleep in the first days after the scan.

As I write this were still not 100% sure that it is lymphoma, but sure enough that we’ve started treatment, because there’s an obvious risk in waiting.

Sickness and lump

On the final Sunday of November 2022 Milo was sick late in the afternoon. By bedtime he’d been sick some more, and was looking VERY sorry for himself. He seemed better in the morning, and ate his usual breakfast kibble, so if it wasn’t for the lump that my wife found on his neck we might not have even taken him to the vet.

The vet thought it was gastroenteritis brought on by something he ate (he and his brother are prone to scavenging things when out on walks). His temperature was normal, but she suggested a bland diet (chicken and rice) for a few days. He weighed in at his normal 5.5kg.

It wasn’t clear if the lump was connected to the sickness, or something else. The vet suggested bringing him back if it wasn’t gone in a week or so. She also took time to outline all of the possibilities, including that it might be a swollen lymph node caused by lymphoma; and the diagnostics that would be associated with that – everything that followed over the next weeks. We could have gone all in right then, and done all the tests (and a specialist referral). But that would have been a lot of bother for Milo, and a lot of cost. Given his age and general wellbeing the odds of the worst case seemed very remote.

Milo came home, enjoyed his chicken and rice, and seemed to bounce back to normal. But the lump remained.

Needle biopsy

We took Milo back to the vet, and he re-examined him, culminating in taking some samples from the lump. A few days later we got the results, which confirmed that it was a lymph node, but were otherwise ‘non diagnostic’ – there was no indication of a problem.

An unwelcome Christmas present

As I was finishing up Christmas dinner I saw Milo repeatedly sitting at the garden door to go outside. He’d then go out, come back in, and then minutes later be back at the door. When he pooped on the floor I was a little cross with the rest of the family for not letting him out. But we got things cleaned up, and a day later returned to the chicken and rice diet as he seemed to have an upset tummy again, and the vets was closed for the Christmas break. He was still eating enthusiastically, and enjoying walks, so not a case for the emergency vet. But an ’emergency’ appointment for first day back to work.

The vet gave him some antibiotics, which seemed to make him bounce back. She also asked us to continue with the chicken and rice, and to collect faecal samples as she’d noticed ‘some firmness’ in his bowel. He was booked in for a blood test the following day.

Blood test

The blood tests came back pretty much clear. Everything was normal apart from excess reticulocytes (immature red blood cells), and that was explainable by the fact that there had been some blood in his poop, so of course he’d be making fresh blood cells.

Faecal test

The vet wanted 3 samples from consecutive days, but we didn’t have 3 samples as the New Year weekend approached; so it was after the long weekend before the samples went for analysis.


The faecal tests picked up antigens for Giardia, a parasite that can cause gastroenteritis, and Milo was prescribed a course of Panacur to treat it. We also started feeding him Royal Canin gastrointestinal (GI) loaf, as he’d been eating a LOT of chicken and rice. As we were getting towards the end of the course of Panacur he was sick again, so the vet prescribed a few more days of treatment.


It was time to get a scan, of the lump, and his tummy. I called up the vets to make an appointment, and their scanner was away for servicing – for up to two weeks.

Over the weekend Milo was visibly lacking energy and losing weight, so back into the vets for an appointment on Monday morning. He’d dropped to 5.2kg, and the vet was concerned about what he was feeling. Luckily the scanning specialist was due the next day, and had time to see Milo too.

The interpretation of the scan was the worst news – signs of lymphoma. Samples had been taken for cytology. An appointment with a specialist oncologist at North Downs Specialist Referals (NDSR) was recommended.

We started reading:

This all seemed like bad news. It had taken 7.5 weeks to get to a diagnosis, and we were reading that dogs with lymphoma usually last 4-8 weeks. It felt like we were running out of time.

NDSR called the following morning, their next available appointment was almost a week away. Milo seemed to be going downhill fast (maybe in retrospect the result of being sedated and poked around), and it felt like he might not make it that far.


Meanwhile the report came back with an interpretation of ‘Consistent with lymphoma’ – not a definite diagnosis, but a fairly strong leaning. There was also a comment:

The two sets of slides contain similar predominant populations of intermediate round cells displaying features most consistent with lymphoid origin and lymphoma as you suspected. However, interestingly there are areas in which Mott cells appear over-represented and given the young age of this patient and breed, lymphoma with Mott cell differentiation is a possibility. To further the diagnosis and confirm the exact type of lymphoma will require histopathology and likely immunohistochemistry.

Veterinary Clinical Pathologist

This lead us to Clinical characteristics and outcomes of Mott cell lymphoma in nine miniature dachshunds, which was cause for some hope – MCL is less bad than other varieties, and one of the dogs in the study was still alive after over 1500 days.


Milo had picked up a little in the days before we visited the specialist, so as he was taken in to the consulting room he didn’t appear too bad. A little thin, but otherwise OK.

Although there were strong indications of lymphoma, the specialist still wasn’t sure. He offered three possible course of action:

  1. Treat the symptoms, using steroids. But don’t start cancer treatment.
  2. Further tests to confirm cancer (and what type), but wait for confirmation before starting treatment. The range of possible tests included:
    • A PCR for Antigen Receptor Rearrangements (PARR) test on the samples taken during his scan.
    • Flow cytometry, which would require another scan and associated sedation.
    • A surgical biopsy, which would require general anesthetic.
  3. Start chemotherapy, and run a PARR test in parallel (and perhaps further tests if the PARR wasn’t definitive).

I picked option 3. NDSR could start the chemotherapy straight away, and then my local vet could pick things up. Or we could do it all with our local vet. In the end our vet wasn’t able to start right away, and also wasn’t able to get some of the drugs. So we were back at NDSR the next day to start there.


Doggy chemo isn’t the same as with humans. Firstly only certain breeds suffer from hair loss, but also the severity of treatment is much less. The aim is to get an extended quality of life rather than to ‘cure’ the cancer. A good friend who’d lost a dog to lymphoma put it something like this:

With people you can hit them so hard with chemo that they might feels like they want to die, but ultimately they get better. If you do that to a dog they lose the will to live and they do die.

Milo is on a CHOP protocol, which consists of giving him a doses of three different drugs in a rotation:

  • Vincristine (injection)
  • Cyclophosphamide (tablets)
  • Vincristine again
  • Doxorubicin (intravenous infusion)

For the first month he gets one of those weekly, along with daily steroids. For the second month the weekly doses continue, but without the steroids. After that the pace eases a little, with treatments every 2 weeks for another 4 months. All being well, he’ll be done in time for our summer holiday in the Lake District.

Each time he goes for a treatment he needs a blood test, to confirm that his white blood cell count is normal; and along the way other tests (and scans) might be needed.

It could just be the steroids, but Milo has bounced back pretty quickly. Within a couple of days his poop was back to normal, and a day later he was back to play fighting with Max. He still needs to put some weight back on, but the early signs are promising.

GitHub is at the heart of how I do work, and Dependabot is one of the core tools. Even before we started using OpenSSF Scorecards, which pushed us to pin dependencies, Dependabot was something we used a lot to ensure that things were up to date.

But, Dependabot isn’t perfect, and looking at the discussion threads involving those who support it, there might be some underlying problems that are stopping things from being improved. That of course leaves the door open to new tools, which can hopefully do what Dependabot does and more (or perhaps augment Dependabot functionality – maybe I just need a bot for my bot).


For many package managers I need to configure Dependabot for each location that it will find files defining dependencies. If I have Dockerfiles in four places then I’ll get four pull requests (PRs), even if the FROM line is the same across them. Merging those PRs separately gets time consuming, as each merge to trunk turns into a rebase for the next PR, and each rebase means another run through continuous integration (CI) tests.

Nobody wants to sit and wait for tests to run.

The workaround for this is to rollup the PRs. I can git checkout the first PR’s branch, and then git merge each of the subsequent PR branches. One approval, one run through CI, one merge that closes all the PRs at once.

But that’s a manual process. I’d much rather say (in PR #1234): @dependabot rollup #1235 #1236 #1237 and it can take care of the merges for me.

Of course all of the above would be less of an issue if we could configure Dependabot with lists of locations rather than have to repeat configs around single locations…

Class approval

We have the OpenSSF Scorecards action deployed to 13 repos, which means every time ossf/scorecard-action gets bumped that’s 13 PRs, and every time github/codeql-action/upload-sarif gets bumped that’s another 13 PRs. This quickly gets tedious.

What I’d like to do instead is one review (an instance of the class), which then automatically approves (and merges) all the others.

Dealing with Dependency Cascades

There are places in the Atsign code base where I’ve consciously decided not to pin dependencies, because every release results in a new Docker image, and every new Docker image would yield in a new SHA that has to be pinned against – a dependency cascade, which potentially becomes a dependency cyclone, only moderated by the Dependabot (typically daily) schedule.

Of course circular dependencies are a problem almost as old as using dependencies, and there’s no easy answer here; but I’d like to be able to define some behaviours e.g. these hashes come from the last release, don’t create another release when they’re merged to trunk, or we’ll be at this forever.

Queueing theory is the mathematical study of waiting lines, or queues.

Wikipedia – Queueing theory

This is timely, as the big news of the day is that our Prime Minister, Rishi Sunak, wants all pupils to study maths to age 18. So maybe this is one of the things people should be learning about (in addition to bank balances, household budgets, taxes, interest rates etc.).

An example

Imagine a busy Accident & Emergency department that only has one bay free. Patients take an average of just 10 minutes to triage and treat, and they arrive at the rate of 5.8 per hour.

What will the expected waiting time be?

With only one bay open, patients will have to wait nearly five hours on average before they are seen.

What happens if you’re able to free up another bay?

If you open a second bay, the average waiting time is not just cut in half; it goes down to about 3 minutes. The waiting time is reduced by a factor of 93x.

Why was the wait so long with one bay?

There’s not enough slack in the system.

Patients are arriving every 10.3 minutes on average and are taking 10 minutes to see on average. If patient arrivals were exactly evenly spaced and each took exactly 10 minutes to treat, there would be no problem. Each patient would be seen before the next arrived. No waiting.

BUT… the service and arrival times have to be very close to their average values to avoid a line, and in reality that’s not how things happen. On average there will be a long line, 28 people. But with a second bay, it’s not likely that even two people will arrive before one of the bays is free.

Adapted from What happens when you add a new teller? by John D. Cook

Why does A&E only have one bay free?

Back pressure.

There’s a queue of ambulances outside of A&E because at any given moment all the bays are busy (and the corridors are already full of trolleys).

A&E can’t move patients onto wards because their beds are full.

Wards can’t discharge patients who are fit to leave because there’s no social care available (whether they should go to a care home, or get a care package in their own home).

Nobody is accountable end to end

If the scope of these problems was (say) a factory, then we could pull out Theory of constraints and go looking for bottlenecks and resolving them. But that sort of approach assumes that there’s somebody who can look at then fix the end to end flow.

But as we look at the back pressure, it builds up across the dividing lines between organisations, with nobody empowered or accountable to free up capacity for the stage before them.

This isn’t just about hospitals

Across the public sector and private sector the relentless pursuit of efficiency has resulted in services that might be approaching 100% efficient, but are also approaching 0% effective. Everybody is waiting, nobody is getting served.

We need more slack.

You’re efficient when you do something with minimum waste. And you’re effective when you’re doing the right something.

The Knowledge Project blog – Efficiency is the Enemy

It might seem good for profits (or spending of precious taxpayer money) to be sweating every last asset, but what about the effect on the overall economy? If everybody’s busy doing nothing, because they’re waiting on hold or whatever, then overall productivity has taken a nosedive.

I’ve had a few things that charge from USB-C for a while: my Planet Gemini, Nintendo Switch, Oculus Quest, SteamDeck, GL-MT1300 travel router, and a bunch of Raspberry Pi 4s; but the arrival of my Lenovo X13 has had me kitting myself out with a bunch of new chargers. So here follows some reviews (with affiliate links if you also want to buy the same)…

Power banks

Anker 737

I’ll start with the Anker 737, as I’ve been using its metering and OLED display to measure the output of the other chargers.

It’s a BIG beast of a thing, properly deserving to be called a ‘power brick’, weighing in at 2/3kg, but that gets a LOT of battery with 24000mAh (pretty near the limit for many airlines), and it can output 100W to a single port and 140W across its three ports (2 x USB C PD, 1 x USB A IQ), making it quite capable of charging two laptops and a phone or tablet all at once.


  • Huge capacity
  • Can push out a lot of power (which might avoid having to carry multiple power banks)
  • OLED display is great to show what’s going on
  • Comes with a nice little carry bag that has room for a wall charger and a bunch of cables


  • Heavy
  • Expensive (I paid £99.99, though the RRP is £40 more)
  • Only comes with one cable, though that is a 100W USB C-C

Anker 525

Also known as the PowerCore Essential 20K PD this is a 20000mAh brick with a single USB C PD input/output and a USB A IQ output.

I bought this for a work demo I was doing at Mobile World Congress (MWC) to power a Raspberry Pi 4, which it does perfectly; but when I tried to power my GL-MT1300 travel router at the same time, it turns out that it doesn’t have sufficient oomf, which is why I now have two of these.


  • Relatively inexpensive (RRP is £69.99, but I’ve generally paid £40-45)
  • Comes with carry bag and a pair of cables


  • Only 20W output, so it’s only suitable for phones and tablets

Wall Chargers

All of these use Galium Nitride (GaN) power components for reduced size and weight compared to traditional silicon based switched mode power supplies. To verify their output I measured their charging watts into the 737 power bank, and in pretty much every case they showed around 5W down on the advertised output, though it was a similar story with the traditional 65W Lenovo power brick that came with my X13.

Ziwodiv 65W

I’ll start with the charger that’s impressed me most. The Ziwodiv 65W is tiny, cheap, and yet kicks out (close to) the advertised power (I measured 60W when charging the 737).

The only thing I don’t like about it is the captive UK plug, with no options for easy travel (which it would otherwise be great for given the diminutive size and weight).


  • Inexpensive (RRP for the charger is £22.99, but using a voucher I got the charger and a 2m USB C-C cable for £21.99)
  • Tiny


  • Fixed UK plug

Mu Folding Type-C 20W

Even tinier, but not quite so powerful, is the Mu Folding Type-C 20W PD Fast Charger. With it’s innovative folding UK plug it’s small enough to be pocketable.

It’s just a shame that they don’t do a multi plug version of this for travel (like they did with earlier versions).


  • Impossibly small for a charger with UK plug when folded
  • Reasonably priced at £29 given the quality and design


  • Only 20W, so only suitable for phones/tablets (or in a pinch charging up a power bank overnight)
  • UK plug only

Syncwire PD 67W

I thought this was wonderfully small (until I got the Ziwodiv), and it’s multi country slide on plugs are really neat. It has a US style two blade fold out plug built in, and when folded up those blades can be used to attach UK and EU plugs. That’s won it a place in my US travel bag.

With nothing else connected the C1 output pushed 62W into the 737. It’s presently priced at £42.99, which is a bit steep compared to the £32.29 I paid for mine. It’s probably worth keeping an eye on with a price tracker such as CamelCamelCamel.


  • Small
  • Flip out US plug, and comes with slide on adaptors for UK and EU sockets
  • Comes with a solid and long USB C-C cable rated at 100W


  • Flip out plug arrangement might not work with tight sockets (or might foul adjacent sockets)
  • Only 2 USB C outputs, so won’t cover a full range of travel devices.

Anker 543

The Anker 543 is a 65W charger with two USB C PD outputs (one rated at 45W and the other at 20W) and two USB A IQ outputs. That’s enough for everything I usually have with me when travelling (laptop, iPad, iPhone and Apple Watch), which has earned it a place in my UK/EU travel bag.

Although intended to be a desktop charger it’s small and light, making it also good for travel. I also like that it’s got a figure of 8 (aka C8) socket, which means I can use it with a EU plug C7 cable that has a UK adaptor. The 45W USB C output put 41W into the 737. RRP is £44.99, and Amazon presently have then at £32.99.


  • 2 x USB C and 2 x USB A means not needing to carry other chargers
  • C8 input allows for a small and flexible power cable, which is generally better than a ‘wall wart’ design
  • Supplied with an adhesive strip for desk mounting


  • Doesn’t come with any cables or carry pouch

Mackertop USB Type C 65W GaN Laptop Charger

The Mackertop has the form factor of a traditional laptop power brick, with a captive braided USB C cable, and a ‘Mickey Mouse’ C6 socket for its mains cable.

I’d have preferred a C8 socket, as the cables don’t carry the extra size and weight of an (unnecessary) earth cable. As part of my US travel kit it’s now paired up with a C7-C6 adaptor. It supplied 61W when charging the 737. These are presently £29.97 on Amazon (though if I recall correctly they were cheaper before the run up to Christmas).


  • Captive cable can’t be misplaced
  • Smaller and lighter than a traditional laptop power brick
  • USB A output


  • A C8 socket would be better than the C6 ‘Mickey Mouse’ socket, allowing for smaller/lighter mains cable

Samsung 45W UK Travel Adaptor

The Samsung Travel Adaptor is the same form factor as the charger supplied with the Oculus Quest, keeping travel size down by having a slide out earth pin. Mine presently sits in the bag with the 737 so I know I have something to charge it with.

‘Travel’ here would seem to refer to its small size and weight rather than any plug flexibility. These are presently priced at £39.99, but watch out for sales etc. as I bought mine for a much more reasonable £18.63.


  • Small and light


  • Pricy at RRP
  • UK only plug
  • Single USB C output


There’s no perfect adaptor, which is why I’ve ended up with a bunch of different ones, in different bags for different scenarios. That said, I’d be buying a bunch of Ziwodiv adaptors if they had the same flip out plug arrangement as the Syncwire.

December 2022



We finally got the sizing figured out to order the boys some Equafleece Dachsie Jumpers, which have them looking smart and keeping warm:

Up North

When I grew up in the North East of England everybody I knew lived at the coast. But over time, friends and family have moved on, which meant my trip this month was my first where I didn’t go to the coast at all, because nobody I know lives there any more. It was a bit weird. But also it was nice to catch up with family and friends, and get to see their new places and surroundings.


My trip up North coincided with the start of a cold snap in the UK. As I was heading for home there were a few light flurries of snow, but nothing too troublesome.

I thought I was escaping to warmer climes down South, but I was very wrong about that, returning home to a few inches of snow (on apparently untreated roads), and accompanying traffic chaos. Getting home from the railway station was NOT the adventure I had planned for my Sunday evening.

New(ish) Laptop – Lenovo X13 Gen 1

I last got a new laptop when I joined CSC over seven years ago, and I’ve previously written a medium term review of my Lenovo X250, and mentioned the swap over to a replacement when I left DXC. The battery life of the replacement has never been great, and it was starting to feel sluggish, so I felt the time had come for a new machine. Given that the X250 had been so good, and family members have been happy with X270s I’ve picked up, the natural choice was a Lenovo X13. The Gen 1 machines are starting to show up on eBay at reasonable prices, and when I saw (more than[1]) the spec I wanted for £375 it was an easy decision to hit the Buy button.

So far I’ve been delighted with the machine. It’s slim, solid, light and fast – everything I want from a laptop. Battery life seems OK (but not amazing), but with USB-C charging it will be easy to keep topped up (even if that means using a portable power bank).

My one niggle is that it doesn’t have a proper Ethernet port, which means having to buy and carry around a little adaptor from the ‘mini RJ45’ to something that has a full sized socket. In terms of design trade offs, I’d rather have a proper port, and for the laptop to be a little thicker (with space for a bigger battery).

The most pleasant surprise is that the laptop I received appears to have spent its life in a cupboard, so I’ve effectively got a new laptop for something like a quarter of the retail price :) After getting things set up with a fresh install of Windows 11 I ran CrystalDiskInfo which reported 26h of run time for the SSD, which I think boils down to:

  • Corporate buyer gets new laptop, applies asset sticker, and installs standard corporate image. Laptop then goes into cupboard waiting to be issued.
  • Premium warranty expires, so laptop gets replaced with a new one (Gen 3?) and sent to refurbishers, who install their image.
  • Laptop shows up at my place, where I immediately do a fresh install of Windows because I want 11 (not 10) and don’t trust what the refurbishers might have installed.

IoTSF Award

Normally my work involves sitting at my desk at home doing backroom boy stuff, but this month brought an exception to my normal routine with a trip up to London for the TechWorks Awards & Gala Dinner where I was delighted to collect the Internet of Things Security Foundation (IoTSF) Champion Award on behalf of my Atsign colleagues.

Solar Diary

As expected, the darkest month wasn’t the best for generation, with just 84.7kWh:

Also no progress on Smart Export Guarantee payments from EDF, who still seem to be dragging their heels. Not that it matters much when I only exported 16.1kWh (<£1) over the month.

Beating Beat Saber

The bad weather and Christmas break have disrupted my usual exercise routine, so the virtual swords have been out again. I bought the recently released Rock pack, which has some all time classic tracks in it. Some of the levels are tantilisingly close to being all perfect cuts at Expert level, but I’m struggling with others. There’s a section near the end of Born to be Wild that’s defeated me on both attempts so far that might need some practice runs.


[1] I’d have happily gone with the same spec I’ve been buying for friends and family for years – i5, 16GB RAM, 1368×768 display. What I got was i7, FHD display, and it even has WWAN (though I’ve yet to try that with a SIM to see if it’s any better than tethering to my phone or iPad).


I’ve been using Advent of Code as a way to practice Dart, try out ChatGPT, and learn from how other people approach the problems. ChatGPT quickly disappointed, but there’s still been plenty to learn, and I’ve found some things I’ll definitely take into my future coding.

Also (value judgement here) I’m finding it much easier to reason about what other people’s Dart is doing versus what other people’s Rust is doing.


Tim Sneath (the Director of Product and UX for Flutter & Dart at Google) tweeted that he was running a leaderboard for people doing Advent of Code with Dart.

Let’s do this! If you want to participate in Advent of Code 2022 with Dart, join our private leaderboard: https://adventofcode.com/2022/leaderboard

Use code 1671198-6c003f39. Who knows, we might even find some swag for the most committed! #AdventOfCode2022
@dart_lang #Flutter

Tim Sneath

Then I came across Simon Willison’s post about Learning Rust with ChatGPT, Copilot and Advent of Code, and I thought ‘maybe I should try that with Dart’.

It didn’t take long for ChatGPT to go astray

I probably wasn’t as thorough as Simon in documenting my ChatGPT interactions, but like him I kept them in GitHub Issues.

Things started off pretty well in Day 1, with a decent enough example of reading files.

import 'dart:io';

void main() {
  // Open the file for reading
  var file = File('my_file.txt');

  // Read the file line by line
  var lines = file.readAsLinesSync();

  // Print each line to the console
  for (var line in lines) {

The first signs of trouble came on Day 3, with ChatGPT offering a sample that looked OK, but resulted in a type mismatch.

Then on Day 5 I found ChatGPT making stuff up that doesn’t exist. Perhaps it would be nice if dart:collection had a Stack class, but it doesn’t. Maybe more worrying was how authentic looking the documentation was for the fictional class.

Since then I’ve occasionally tried to get help from ChatGPT on error messages etc., but service has become pretty unreliable under the huge load that’s been put onto it.

Learning from Tim’s code

Tim has been posting his solutions on GitHub, and I’ve been taking a look at how I might sharpen up my own use of Dart.

Directory structure

The first thing that hit me is the directory structure. Dart (and Flutter) projects tend to be a certain shape, and this keeps to that form. I should probably find (or make myself) a Dart boilerplate repo to start things off properly.

Reading the input file

Tim uses a standard approach to reading the input:

void main(List<String> args) {
  final path = args.isNotEmpty ? args[0] : 'data/day01.txt';
  final data = File(path).readAsLinesSync();

This defaults to reading the day’s input.txt from its appropriate file (in the directory structure already mentioned), but allows easy overriding to test against example input or something else. He also doesn’t dive headlong into tearing the file into lines, but passes that object around whole to other classes that iterate across it.

Final everywhere

I see final all over the place in Tim’s code, where I’m accustomed to seeing various variable declarations.

In some cases this use obviously fits into the pattern of “A final variable can be set only once”, with the path and data example above illustrating that. But there are other times I found myself scratching my head a little, like final in an iterator:

for (final row in data) {
  if (row.isNotEmpty) {
    currentCalories += int.parse(row);

For that block to work it’s quite obvious that the value of row is changing on each iteration, but what is ‘final’ is the amount of memory that needs to be reserved for each row.

Final and lists can also be counterintuitive, but then I find this example in the docs for the Dart type system:

void printInts(List<int> a) => print(a);

void main() {
  final list = <int>[];

It doesn’t mean that an immutable list is being created (that wouldn’t be very useful), but rather that each element of the list is immutable, which is a useful cue to the runtime in terms of memory allocation. Of course the use of final in lists is related to using final with lists (or iterables) in an iterator.

Deeply nested operators

There’s a lot going on in something like:

int countContainedIntervals(Iterable<String> rows) =>
    rows.map(convertRaw).map(isIntervalContained).where((e) => e).length;

But each chained operation gets us towards the desired outcome.


After some initial success ChatGPT has been a disappointment (and I suspect it has better training material coming from stuff relating to Rust’s learning cliff), but it’s always worth spending some time reading other people’s code to see what and how they do things differently, and why that might be better.


OSSF Scorecards provide a visible badge that lets people see that an open source repo is adhering to a set of practices that minimise risks, measured by a set of automated checks. Getting this right for a single repo can be an involved process, but with that experience in hand applying the learning to a larger set of repos can be fairly straightforward. Implementing Allstar first can help pave the way.

OSSF What?

The Open Source Security Foundation (OpenSSF or OSSF)…

…is a cross-industry organization that brings together the industry’s most important open source security initiatives and the individuals and companies that support them. The OpenSSF is committed to collaboration and working both upstream and with existing communities to advance open source security for all.


OSSF Security Scorecards

…assesses open source projects for security risks through a series of automated checks.



Over the summer we read about Dart and Flutter enable Allstar and Security Scorecards, which seemed like a good way to show that they cared about security. So if we followed in their footsteps then hopefully we can show the world that we (Atsign) also care about security.

Allstar first

Scorecards looked like a LOT of work, so we started with Allstar:

Allstar is a GitHub App that continuously monitors GitHub organizations or repositories for adherence to security best practices. If Allstar detects a security policy violation, it creates an issue to alert the repository or organization owner. For some security policies, Allstar can also automatically change the project setting that caused the violation, reverting it to the expected state.


Starting gently

We began with an opt in strategy for a single repo, and that evening Allstar did its thing and spat out a series of issues complaining about branch protection, and a missing SECURITY.md. It took a while to figure out exactly what was wrong with the branch protection settings, but once that was done the issue automatically closed.

Ramping up

Once it was clear what Allstar required from us Terraform was used to get a consistent branch protection config across all the public repos, and Git Xargs was used to ensure that SECURITY.md was in place. Allstar could then be enabled for that full set of repos.

We also tracked down a few repos with binaries in them that belonged in Releases rather than the repo itself.

Then Scorecards

Starting with the same pilot repo as before the Scorecards GitHub Action was dropped into place, and immediately noted 125 issues in the Security tab on GitHub. It turned out that particular repo was maybe the worst place to start, as it has a number of complex GitHub Actions, some of which run a bunch of things in Dockerfiles and Python. That all meant a huge stack of dependencies to be pinned, and a lot of token permissions in workflows to be restricted. Thankfully the StepSecurity App was very helpful in identifying minimal token permissions, and finding SHAs for Actions; leaving some mopping up work for the Docker and Python bits.

OpenSSF Best Practices

Maybe the hardest part on that first repo was completing the questionnaire for the OpenSSF Best Practices Badge Program. This scored us an 84% ‘In progress’, and maybe bumped the Scorecard itself by 0.1. It’s not a process I spent time repeating for the next bunch of repos.

Scaling out

Implementing Scorecards isn’t as scriptable as Allstar, and in the end each repo was done manually, so to keep the work manageable only the repos featured in our GitHub Org profile were added rather than all public repos. Doing that mainly consisted of adding the Scorecards Action, adding the badge to the README.md, and ensuring that dependencies were pinned and token permissions minimised.

The scores are in

At the end of the initial wave the scores looked like this:

I’m very happy with the mid 8s, and OK with anything in the 8s.

That 7.1 has already been improved to a 7.6, and those 7.4s just need some more PRs to run through the post branch protection regime.


8.5 is a decent score (the Dart SDK is presently at 8.6, and plenty of the repos for OSSF tools are at or below that level), but obviously there’s still more that can be done, specifically:

  • Fuzzing
  • Implementing a Static Application Security Testing (SAST) tool
  • Best practices for the other repos
  • Signing binaries for the repos that have them (and automating that release process)

I suspect though that we’re now in a situation where 20% effort has got 80% score, and the remaining 20% score will take another 80% of effort.


Yesterday brought the first time showing a customer the Scorecards. They seemed impressed, and it registered as a clear signal of caring about security.

Dependency pinning has also shone a light onto things we’re using that aren’t in the Step-Security Knowledge Base (some of which now are), which perhaps we need to pay closer attention to.


For a little more on how Atsign use GitHub (and some links to more resources) check out atGitHub.

November 2022



It’s been cold, and wet, and windy, so the coats are back on for walks. Some days they aren’t keen to go out at all, and would rather just snuggle up.


The National Museum of Computing (TNMOC) had a pop up exhibition on Charles Babbage, and the work done by volunteers to bring his sketches to life; and that provided a good excuse for the London Retro Computing Meetup to get together there.

Last time I visited TNMOC it was possible to walk through from Bletchley Park (before it became Bletchley Theme Park and fell out with many volunteers). Despite some concerns about a leaky roof, the place felt more together than last time; and it was wonderful to hear from the deeply knowledgeable volunteers.

They now have their own Bombe reconstruction, covering how Enigma was broken; and the volunteers really brought to life the exhibits for Tunny and Witch (along with Colossus, though I’d seen that before).

If you find yourself anywhere near Milton Keynes with time to spare it’s well worth a visit, and if you’re anywhere in the South of England and interested in the history of computing it’s worth a day trip.

Solar Diary

November produced only 119.4 kWh, less than half the figure for October :(

Another month rolled by without any progress by EDF on my Smart Export Guarantee application (other than a specious email about missing info to register an export MPAN, when I already have one that they’ve been told about). But, I guess this matters less in the autumn/winter months when there’s less excess generation – I exported a mere 29.4 kWh this month, which if EDF got its act together they’d have paid a whopping £1.65 for :0

October 2022



The boys were too frequently pulling on their lead when wearing harnesses, so we did a bit of slip lead training, and now they’ve got collars and they’re walking much more nicely :)


I’ve mentioned in past posts that I run a handful of VPSs so that I can emerge from the ‘right’ country on the Internet when required. My venerable VPS in the US fell over, and the hosting service didn’t do a great job of bringing it back up, and it was on the now too long in the tooth OpenVZ platform. So I decided that if I needed to rebuild a server it might as well be a new server, and after a quick look at LowEndBox I found a decent KVM based plan with Racknerd. So far, so good.

Back to the Bay

My last long haul trip before the Covid lockdowns was to Palo Alto, and I returned to the Bay Area for QConSF. The conference was great, and things seemed pretty much as I expected them from the past. It was also nice to finally meet some of my colleagues face to face.

Mini review United Premium Plus

My flights out and back were both packed, which made things ‘interesting’ from the perspective of trying to ensure some comfort. I chickened out of waiting for check-in and paid for Economy Plus on the way out to get an aisle seat with decent legroom. For the return I was offered upgrades to Premium Plus at $529 and Polaris at $2199, so I gave Premium Plus a go.

The ‘hard’ product isn’t much of a step up from Economy Plus. A little more seat width (and much wider fixed armrests, so no risk of next door spilling over), a little more leg room, a bigger screen for the in flight entertainment. But the same food as economy, the same toilets as economy, the same cabin crew as economy. With 2-3-2 seats, it might look a bit like biz class before it became lie flat, but it’s not that comfortable, and there’s nobody offering port and cheese after dinner.

I ended up with a middle seat, which essentially left me trapped between the strangers either side of me trying to get some sleep.

Would I pay sticker price for this? No.

Would I pay to upgrade again? Probably not, especially if I already had an Economy Plus legroom seat locked in.

Do I think the whole thing is a cynical ploy to bring back 4 class cabins and drive higher price differentiation for Polaris? Yes. In the before times I’d generally pick up Polaris upgrades for $769, sadly it looks like those days are over, at least for the newly configured fleet.

20 years

The start of the month marked 20 years since we moved into our house. When we bought the place we had no intention to stay, but over the years we’ve made it what we want it to be, and grown to love the neighbourhood. I’m still not sure it’s our ‘forever’ home, but it will take some effort now to find a place we live in for longer.

Solar Diary

October with 253.5 kWh was much less productive than September at 369.9, and it’s almost possible to see the slide down through the month:

The sun getting lower was also noticeable as I was out on my bike in the last days before everything got wet and leafy.

Meanwhile it’s taken the whole month for EDF to not process my Smart Export Guarantee application, and tell me that they’re missing details needed for an Export MPAN (something I already have, and told them about). It’s almost like they don’t want to pay me for the electricity I’m presently giving away to the grid :/