ports, task lists, and supply chains
Welcome to week two of the aforementioned weekly updates.
#web
My websites, web services, and all related infrastructure (as code).
The highlight this week was removal of static internal ports. I mentioned last week that I was thinking about migrating to Unix domain sockets, but that wasn't solving the actual problem: it was replacing a port number with a string label, which really isn't much better.
The kind of internal ports I'm talking about are the ones the Go web servers listen on (one per site) which Caddy reverse-proxies to. They are purely internal, so the port numbers can be assigned dynamically. The network is only used by the containers, so there's no chance of port conflicts, either.
So that's what was done: site definitions moved from a map to a list, in which the index defines the port offset, which is added to a base port to produce the final port that's then fed back into Caddy via environment variables.
Other web-related changes were not quite as satisfying. An influx of requests to non-existent subdomains saturating the logs made me return to static subdomain definitions. I also omitted empty bundles from the HTML output and preloaded fonts to remove a FOUT.
#system
Everything related to my local personal systems and their configuration (as code).
Not many changes to my pi extensions this week, and it's mostly optimisation work.
The bg extension (for agents to manage background processes) now injects a message when a background process starts (user-initiated) or terminates, as there were several instances of agents making incorrect assumptions because they were not aware of state changes.
The task list extension (for agents to manage task lists) had a fragmented toolset, spread out over 7 (!) different tools. This is the problem with incremental design. You need to take a step back sometimes and look at what you've created.
| Tool | Description |
|---|---|
task_list |
read the list |
task_set |
replace the list |
task_add |
append a task |
task_complete |
mark a task complete |
task_restore |
mark a task incomplete |
task_edit |
edit a task |
task_clear |
clear tasks |
These were collapsed into four.
| Tool | Description | Replaces |
|---|---|---|
tasklist_get |
read the list | task_list |
tasklist_set |
replace the list | task_set, task_edit, task_clear |
tasklist_append |
append tasks | task_add |
tasklist_mark |
toggle task completion | task_complete, task_restore |
This was possible by making a few changes. Firstly, the tools were updated to work with task titles rather than IDs. Agents are capable of reiterating the task title they want to reference, which means no longer needing to assign tasks persistent IDs.
The task_complete and task_restore tools used to accept a list of IDs, but tasklist_mark now simply accepts an object like { complete: boolean, titles: string[] }, no ID recall necessary.
I thought tasklist_set would be the only setter, but tasklist_append was a must-have for the very common case of adding a task to the end of the list. There's no point in providing surgical insertion tools, though, as for such precise edits it's simpler to regenerate the entire task list afresh.
Finally, task_clear was redundant and is now achieved by passing an empty array to tasklist_set.
#torch
My home automation dashboard, complementary to Home Assistant.
This update turned into its own post, so will follow later in the week. The summary is that energy reporting broke for the smart plug I use to monitor my dryer, and I had some fun fixing it.
#upgrades
My thoughts about a package upgrade vetting process.
I've been reviewing the upgrade process for my machines. Package sources include the official Arch repositories, the AUR, Ruby gems, and more. Each of these is a potential attack vector, and each upgrade brings risk.
Supply chain attacks are on the rise. In my time in the industry, it's always been accepted that vetting dependencies would be a good thing to do, if only we had the time. We may not have more time, but we do have a time compressor in the form of agentic AI.
Now we can gather up the details of a full system upgrade into text form and feed that to an agent to review as thoroughly as needed. Not just for security issues, but also compatibility issues, and anything else you can think of.
A dependency review could range from looking at the changelog to cloning every dependency and transitive dependency, then analysing the source code in extreme depth. However, prompt injection is an important consideration. Frontier models are already very good at detecting it, but they're not perfect.
For now I've encoded this process in the form of a skill as a PoC but I'd like to think about if this could become something more.
#housekeeping
Across various projects:
- Updated even more pinned URLs in
mise.locks after mise changed the domain upstream - Moved
--colorflag after thegolangci-lint runsubcommand