Writing & build logs.
Essays on software development, web builds, and AI tooling. Plus build notes from what I'm actually working on right now.
Scope the MySQL user first: the newsletter DDL as a security boundary on cPanel
On shared hosting, you don't control the firewall or the infrastructure. What you do control is which privileges the MySQL user holds. Scoping it to the newsletter schema alone made a compromised endpoint's blast radius structurally finite — not as a mitigation layered on top, but as a property of the design.
Zero drafts at 07:00: build the gate, not the prompt
The 29 June cron ran every stage correctly and produced nothing. Haiku underfired on claim-extraction, the pipeline accepted the shortfall without raising an error, and the log showed a clean exit. The fix was a corrective stage that detects the count failure, reruns with constrained parameters, and marks the run failed if the second attempt also falls short. Six pillars shipped in the three days that followed.
Ten cycles, one ready draft: the pipeline was consuming its failures
Between 30 June and 13 July, ten cron cycles produced one ready draft and zero auto-publishes while the skipped counter climbed from 2 to 7. The drafter was not stalling. It was treating failed attempts as permanent completions, and only heartbeat visibility on ready-draft count made the dead zone visible.
The cron exited clean. There were no drafts.
Two zero-draft mornings out of four cron firings across 29 June to 2 July, both exits clean. The failure was Haiku's claim extraction underfiring one stage before draft: structurally invisible, no error, no warning, cron returns success.
The cron fired at 08:22 and drafted nothing — scheduling is the easy part
On 2 July, the pipeline ran on time, ranked 150 clusters, fetched candidates, and produced zero drafts. The scheduler worked. The grounding step didn't. Automating gov.uk pillar articles forces a distinction that took a zero-drafts morning to make explicit: cron reliability and content freshness are different problems, and only one of them is solved.




