Pragmatism in the real world

Previewing OpenAPI specs using redocly's Docker container

To provide consistency between the environments of our developers, I'm a strong proponent of using containers so that every developer is using the same versions of our tools. This is really important for command line tooling that depends on a separately installed language such as NodeJS or PHP as a simple npm i -g can install wildly different versions if a dev is running an older (or newer!) version of Node. For OpenAPI specs, listing… continue reading.

Using the Stripe CLI with with Docker Compose

One of the projects that I'm working on at the moment uses Stripe which means that we need to handle web hooks in order to ascertain what's happened as that's how Stripe communicates back to us. For production and staging, it's easy enough to register a url on Stripe's dashboard, but when developing, it's a little more complicated as our computers are generally isolated from receiving incoming web requests from the public internet, along with… continue reading.

No SSL padlock on Safari on macOS 18.4

With the release of macOS 18.4, Safari no longer shows a padlock when you visit a website that uses https. I assume there's a reason for this but I was scratching my head trying to work out how to view the SSL certificate when I went to a new-to-me website domain that my bank asked me to go to. This is what the address bar now looks like when you're on a secure connection to… continue reading.

Generating scripts with LLMs

With the recent release of the new OpenAI ChatGPT that can do image generation, I thought that I might add a feature image to my last blog post. I've had mixed experiences of AI generation of images, probably because I'm not good at prompting them. I started with this: We now have an image, but it doesn't have a credit. Now, I could go back to the LLM and ask it again, but these things… continue reading.

Backing up Signal messages on Mac

I'm using Signal more now and as it's fully end-to-end encrypted, if something goes wrong with your phone or you lose it, you will lose your entire message history. Signal on Android has an official backup method, but there isn't one for iPhone or desktop. As a result, a number of backup tools have been written by various people. The one I've had most luck with on my Mac desktop is signalbackup-tools. Note that the… continue reading.

Getting the screen's size in a macOS screensaver

As a hobby project, I've been writing a screensaver for my Mac that displays my photos with a caption and date taken. To get the width and height of the screen so that I could size the image correctly, I used this code in my ScreenSaverView: self.screenWidth = frame.size.width self.screenHeight = frame.size.height However, I discovered that with two or more screens, sometimes the frame size returned was wrong and so the photo was either too… continue reading.

Privileges app: sudo for macOS

By default, the first user that you create on macOS is an administrator and has more power over the system than a normal user account. The reason it does this is obvious as you need this power to create other users, to install software and so on. However it also means that the computer is slightly more vulnerable to attack via a vulnerability in the software I use day to day. To combat this, I… continue reading.

Cloudflare SSL/TLS setting for an encrypted connection to upstream

I was helping a friend set up a new website and hit a problem where the website was in an infinite redirect loop: I could see this in curl quite easily: $ curl -I https://myfriendswebsite.example.com/ HTTP/1.1 301 Moved Permanently Location: https://myfriendswebsite.example.com/ To debug, we turned off Cloudflare by setting the Proxy status on the DNS record in Cloudflare's admin to "DNS only" and the problem went away. Further investigation led to the SSL/TLS setting in… continue reading.

Converting a PHPUnit TestListener to an Event Subscriber

One of the bigger changes in PHPUnit 10 was the introduction of the new extension system which replaced listeners and hooks. The old way On one of my projects we have a TestListener that sets up the database before we run some functional tests against it. It looks like this: <?php declare(strict_types=1); namespace App\Test\Listeners; use App\Test\Functional\Helpers\DbHelper; use PHPUnit\Framework\TestListenerDefaultImplementation; use PHPUnit\Framework\TestSuite; class TestListener implements \PHPUnit\Framework\TestListener { use TestListenerDefaultImplementation; public function startTestSuite(TestSuite $suite): void { if (str_contains($suite->getName(),… continue reading.

OAuth scopes vs user roles

There is a different between OAuth scopes and roles. A scope is the abilities that the client requests that the user can then decide if they are going to authorise that client to do those things. A role is the rights that a given user has within the application. Scope examples are "read-name", "read-address", "read-email", 'write-all", etc. Example roles might be "moderator", "user", "administrator", etc. and is used by the app to determine what the… continue reading.