Blog

Long write-ups on Rust and security work, including the parts that went wrong.

Featured 5 min

Paste an error into my guides page and it picks the guide

On 28 September the blinking cursor on my guides page became a place to type. A plain word filter finds nothing in a real rustc error, so the prompt also asks whether the paste holds one of a guide's symptom lines whole. Hiding the filtered rows with Alpine's x-show broke under fast typing. Binding the hidden attribute fixed it.

alpine.js typescript rust search
Read the article

All Posts

5 min

Paste an error into my guides page and it picks the guide

On 28 September the blinking cursor on my guides page became a place to type. A plain word filter finds nothing in a real rustc error, so the prompt also asks whether the paste holds one of a guide's symptom lines whole. Hiding the filtered rows with Alpine's x-show broke under fast typing. Binding the hidden attribute fixed it.

alpine.js typescript rust search

5 min

Stockfish said readyok twice and my app read it once

My Rust chess app checks the settings it sends Stockfish by sending isready and waiting for readyok. Stockfish says readyok even after it has refused a setting. For about two weeks my code stopped reading at the refusal, so that readyok stayed in the pipe and the next check took it as its own.

rust stockfish uci testing

5 min

A stricter chess library caught my test moving White twice

The move library in my chess app had stopped getting releases and brought advisories I could only ignore. I swapped it for cozy-chess, because shakmaty's GPL licence would have put my MIT app under the GPL as a whole. The new crate checks every move it plays, and an old undo test panicked. It had been moving White twice in a row since October 2025.

rust testing dependencies licensing

7 min

A smoke check at the end of every deploy

My deploy script used to stop once the server said it was running. Now it ends with a bash script that checks every public page, the feed, the CV and the footer, without adding a single visit to my own visitor log. On the day I added it, it failed a deploy over a capital letter while the site itself was fine.

self-hosting testing automation bash

7 min

Moving my site's browser code to TypeScript 7

This week I moved the small layer of Alpine.js code on this site from plain JavaScript to TypeScript 7, the compiler rewritten in Go. Strict mode tidied up a lot of small things, but the two real bugs that turned up were found by a script working through the site in a browser, not by the type checker.

TypeScript 7 Alpine.js accessibility testing

11 min

An MCP pentest server with a 6-layer safety architecture

Raven Nest's role and safety. 22 security tools including Metasploit, 46 MCP endpoints, a context budget tracker that keeps local models from drowning in context, plus an exploit confirmation gate which took two iterations to get right.

rust security mcp ai pentesting automation

12 min

Hardening a portfolio site: contact form, PGP-encrypted email, and a real pentest

I built my own portfolio in Rust because I wanted to demonstrate the security work I care about, not just talk about it. This is what that meant in practice: JWT plus Argon2id, 12 security headers, PGP-encrypted contact form notifications, no third-party email relay, and a 0-Critical / 0-High pentest result. Plus the bits I had to accept I couldn't fix.

rust security owasp actix-web self-hosting

13 min

Hand-rolling BitNet b1.58 in Rust: from autograd to tensor cores

I wanted to genuinely understand BitNet b1.58 - ternary weights with INT8 activations, trained through a straight-through estimator. So I wrote it from scratch in Rust with no third-party ML dependencies. Then I tried to make it run on Ada tensor cores. Then I found out the GPU was slower than the CPU at my batch size, and learnt why.

rust machine-learning cuda simd performance

Want to Know More?

Check out my projects or get in touch to discuss ideas.