Showing posts with label digital. Show all posts
Showing posts with label digital. Show all posts

Structured editing of telephone numbers

Minor rant about telephone number inputs on web forms. Ignore this if you have heard it before.

The only time structured editing for the domain of telephone numbers works is when the user is entering a familiar number. Their eyes are on the form, and they can watch how the cursor moves between the area code, exchange number, and line number input regions as they type. For all other telephone numbers, structured editing fails, and fails badly. They won't be able to correct a small mistake because the domain editor is too rudimentary. Their only recourse is to reenter the whole number with their eyes alternating between the input and the source, one digit at a time.

This failure is especially galling because US telephone numbers are easily parsed with a trivial regular expression during form validation. Ignore everything but digits; if the count of digits is 7 then it is local, if 10 it is complete, and if 11 (and starts with 1) it is international.

Please let the user type or paste the number however they want it formatted and validate it later using

const digits = input.replace(/[^\d]/g, ''); 
if ...
Oh, and please do the same for social security numbers.

Rant over.

P.S. I have recently been looking for a new job, and many application forms have this problem. It is a small inconvenience for possible employment.

Code quality and the disposable-durable axis

Everyone on LinkedIn, Hacker News, etc has an opinion about LLMs and code quality. None that I have read are anywhere near as grounded as Max Kanat-Alexander's answer is. In short, frame the answer along the disposable to durable axis. His presentation Does Code Quality Still Matter? It Depends on This is well worth the quarter hour of your time.

Rust, egui, and application interoperability

The Rust programming language is everywhere and in every device these days. I see its appeal, especially now that so much implementation is agent generated. Not only do you have great type checking and memory ownership management, the agent does not have decades of poor and outdated programming practices to ignore in their training set.

Several of my colleagues have used Rust to build TUI applications, but I had not heard of anyone using it for GUI applications. That has recently changed with Brandon Thomas's explosive announcements of his Adobe application work-a-likes. These are written in Rust and utilize Emil Ernerfeldt's immediate-mode GUI egui. An immediate-mode GUI differs from a retained-mode GUI in that each update redraws the entire UI. The actual amount of UI redrawn generally only concerns those parts that have changed. This is accomplished by determining the differences between the previous state and the new state. I think everyone having worked on web frontends will be reminded of React, but React's management of the DOM and egui's management of the UI are quite different (as I understand it).

I found Ian Purton's explanation of how egui is used in PhotoCraft very helpful -- Photoshop, Rebuilt in Rust: The Architecture Behind PhotoCraft. Much of the architecture is very similar to what is used with Smalltalk and later exploited in the Eclipse and Netbeans platforms. What is novel, however, is that PhotoCraft exposes its operations via an MCP server, much as earlier applications used RMI, COM and CORBA, for example. Everything old is new again.

QR codes, Macs, LLMs, and single-file, standalone CLI

The Mac does not have a tool for reading the data encoded in QR codes. Unlike the iPhone, you can't show the QR code to the camera and have it take you to the encoded URL. There are apps in the App Store that do this, but I don't really want to install an application for this infrequent need.

The solution was simply to ask an LLM to write a Python command-line interface!

Write a python script run with uv that will use the macos camera to take a picture of a QR code and then show the associated data encoded in the QR code.

A second later I have qr_scanner.py.

I have been using this technique often, especially with Claude Code. When the data needed is deterministic and frequently used I prefer to create a CLI and then direct Claude Code to use it. Generally this leads to fewer tokens, round trips, and quicker results. I use Python for these because a script + uv makes these tools single-file, standalone CLIs.

(And before you ask, yes, it took far longer to write this post than to create, use, and discard the script.)

Update: I tried this again, but this time asked for a desktop GUI. Again, the result came quickly and worked without issue. What I found humorous was that the LLM used Tk for the UI.  John Ousterhout's tool from 1988 continues to live on.

DeepSeek's harness and prefix caches

I've been learning about DeepSeek's harness. At the core of a harness is preparing a prompt for the next round of model interaction. An efficient prompt will take advantage of the inferencing engine's prefix cache. That is, when the characters at the start of a prompt, ie the prefix, matches an existing record in the prefix  cache the inferencing engine can use the cached results to continue processing the remaining portion of the prompt.

DeepSeek's harness has a sophisticated layer managing the prompt. It is composed of an append only log and an undo mechanism. Anything added to the log is accompanied by a means of reversing the addition. The reversal does not change the log; instead it appends to the log instructions about ignoring the addition. When the harness builds the prompt it effectively recreates the previous prompt with new entries appended. The prompt (almost always) has an identical prefix. You rarely pay for the same inferencing twice.

The same log implementation is used to manage its tools (aka plugins) also. This implementation is work done a few years ago and is open source. As is the harness.

Specification "documents"

I have a minor role working on a complex system that has many requirements. Some are monumental. Some are microscopic. They all need to be tracked and, at some point, traced to the implementation. Unfortunately, the specification has no unique, immutable identifiers for the requirements. Without these there is little chance every requirement will be tracked and less of a chance they can be traced.

The specification is a Word document. A Word document is easy to create and update, to distribute, and to read (either online or in print). Word has useful features for conveying specifications -- section numbering, line number, version tracking, etc -- but not for tracking.

This got me thinking about tools like Starkits and Marimo (w/ uv) and using these to convey the specification's requirements and to track them. Ideally these specification "documents" can be as easily created, distributed, and read as Word documents are. They can be run locally by an individual or run on a server and used by the whole team. No need for a third party SaaS. No need for company IT involvement.

I am not naive here. When at Raytheon my team had an engineer working full-time managing requirements in DOORS. What I am thinking about is something between DOORS and the unstructured, backlog of Jira tickets.

I don't have much more to say about this right now. This note is here to remind me of this idea during some future.

Visualization at the edge between intuitive and training

I've had a long term interest in visualization -- mostly implementing other people's designs. I don't believe that all visual tools need to be intuitive; many will need training to use effectively. I think this one is on the edge between intuitive and training needed.

This Widget Forces You to Think - YouTube

Preparing "Approval Tests" for refactoring Python

Emily Bache's short example of preparing "Approval Tests" for refactoring Python code is very good. Not only for the approach, but also for how advanced IDEs like PyCharm greatly support developers common editing and refactoring needs.

Reaction: Arjan Codes wrote tests the HARD way - My way is BETTER - YouTube

Don't look up

If you live in RI your home's electric meter was recently replaced to enable remote access. I have wondered how secure is that remote access? While this presentation does not address the electric meter, it does address how much of our satellite infrastructure is unsecured and accessible with cheap hardware. The presentation is about the available downlink data, but note the presenter's off-hand comment that if you fly a drone between the uplink site and the satellite you could likely gather the uplink data.

39C3 - Don’t look up: There are sensitive internal links in the clear on GEO satellites - YouTube

Update: A friend said it is easy to access the electric meter data for his home ... and his neighbors. Why is infrastructure security still so bad even in 2026!

Streamlit and a trivial cities explorer

I spent a little time this morning learning the basics of Streamlit. Earlier this month I had found a US cities dataset¹ and decided to use Streamlit to explore city populations. 

This dashboard shows each state's population along with a state selector to dynamically show a state's city's population along with a map showing its location and relative population size. 

While it took me much of the morning to figure out how to use the Streamlit and Pandas SDKs, along with a side-quest on how to debug a Streamlit application in Visual Studio Code, the final application is hearteningly trivial at barely a dozen lines of Python.

1. Unfortunately, the dataset of not very good based on what I know about RI and NH cities and towns.

Jenson's stuck desktop and Foster's recalibration of the futurism


I suspect many of you have seen by now Scott Jenson's presentation "Are we stuck with the same Desktop UX forever?" But, if you have not then it is worth your time. I went on to read the book he mentions Nick Foster's Could Should Might Don't: How We Think About the Future. Jenson's presentation suggests that Foster's book is a "how to", but it is more a useful survey of, and a call for the recalibration of, the futurism field.

Classic Design Patterns: Where Are They Now

Brandon Rhodes' talk "Classic Design Patterns: Where Are They Now" is a good critique of the "Gang of 4" Design Patterns book that dominated software design thinking for decades. Why should you give your attention to a critique of a book from 1994? In part because the critique gives concrete examples of how successful design solutions become molded into programming languages and how programming languages outgrow the limitations that originally necessitated the design solution.

I don't know of the speaker, but he seems to speak at many Python conferences.

Update: I have since watched several of Brandon Rhodes' presentations. He is a good speaker and his presentations are worth your time.

Streamlit and data visualization

I do like computational notebooks, but find them cumbersome to work within. If like me, you've been looking for a notebook-like experience, coding in python, editing using your preferred editor, auto reloading, primarily local, deployable to a small audience, etc then Kris Jenkins's talk Building Data Visualisations in Python in Minutes about Streamlit will be of interest.

Installing Pi-hole

Having become irritated by the daily deluge of web advertisements that make most sites unusable on my phone, this weekend I took the time to install Pi-hole. I'd prefer that the little Raspberry Pi Zero 2 W used an ethernet connection, but am too cheap frugal to buy yet another dongle. Interestingly, the combinded cost of the Raspberry Pi and a micro SD card is about that of a used thin client (eg an HP T630) which can be configured as a general purpose server running several lightweight services.

These two video tutorials were helpful (even if the process is quite straightforward): Block Ads on ALL DEVICES (Smart TVs) — Simplest Pi-hole Tutorial and Raspberry Pi Set Static IP.

Update: The default blocklist is very aggressive. Many community and non-profit sites use the free or low-cost tier of commercial communication services (eg, Constant Contact). The default blocklist blocks these services due to their tracking activities via image URLs. Unfortunatly, this made the community communications less worthwhile. Until I have time to better consider the blocklist I have disabled Pi-hole. For the short period the Pi-hole was enabled, it was a glorious few days of smooth, swift internet browsing. Reminded me of the early days.

Why Stripe’s API Never Breaks

The short video Why Stripe’s API Never Breaks introduces how Stripe handles API versioning. Stripe's API URLs do not include a (consequential) version number and yet every API release is supported. Instead,

  1. The API client includes in each HTTP requests a header with the client's API release date, eg "X-Stripe-Version: 2024-01-23".
  2. Stripe's API server transforms the dated request into a current release request.
  3. Stripe's API server transforms the current release response into the dated response.

This does mean that each new API release needs transformers for all previous releases. I suspect that there are few breaking changes so most transformers default to the previous release's transformers.

Using a version HTTP header does not seem different than using a version number in the URL path, but there is something elegant about maintaining stable URLs across API versions. It also seems easier in most web frameworks (eg Rails) to introduce the transformers after routing.

Board game UX

I don't know if the game Star Wars: Outer Rim is enjoyable, but the game's physical design is amazing. Which reminds me I have What the Tech World Can Learn from Video Game UX lined up to watch.

Update: The video was about using gamification to enhance learning to use a handheld ultrasound scanner. Nothing new.

Inter-company event sourcing

I was in a client's meeting today and they were discussing how one of their batch processes has a dependency on data generated by a supplier's batch process. The problem is that the client does not know when the supplier's process is complete so they can start their process. (The supplier's data is accessed via an API rather than a bulk file delivery.) The discussion went along the lines of 

We know their process starts around 10 PM and takes about an hour to complete. So let's give it a couple of hours to finish, just in case it's slow that day, and we will start our process at, say, midnight.

I scream into the void. This kind of inter-company data processing coordination is quite common. Common enough that I am still surprised there is no standard, or industry-specific, solution we use.

Costs of helpful data flexibility.

I'm having a discussion currently with a young developer who has only ever worked in Ruby and JavaScript. I noticed that the developer had chained "symbolize_keys" to the end of a method call. In Ruby this converts a hash's keys from strings to symbols, ie { "a" => 123 } becomes { :a => 123 }. Their reason for this was to offer flexibility to the called as to how it returned the result. They thought this provided flexility and robustness. I countered that it did the exact opposite.

When a function can be given parameters and return results in multiple formats then robustness is only had when the function handles all formats equally. To do that the function needs to be tested with all formats. This can be done, but in practice, and I've seen across many organizations, it is not. Not only does the function need to be tested with the multiple formats, but the callers and the called need to be tested too. It's a combinatorial explosion of testing.

The other detriment to this flexibility is that since no function is sure of the format every function converts the data to its preferred format even if the data is already in the preferred format. This conversion adds to the function's code size and has a runtime cost (CPU and memory) on every invocation. The cost of a single use might be small, but our applications work in a world with thousands of concurrent sessions each with deep call chains, and expect microsecond responses. Those single uses add up.

My recommendation to the developer was to require one format as part of its contract and add validation that runs at least during testing. (I'd like to just tell them to use a typed language where this wouldn't even be an issue!)

I mentioned that the developer's experience is in Ruby and JavaScript. I have found that is common for such developers to not expect data to be in a specific format or type. I assume some of this comes from never being trained to always validate and convert data coming from the outside before using it inside. (Eg, directly passing around an HTML INPUT element's value or a database's column value.)  Once inside, you can be assured of its correctness. Instead, data is passed around without any function knowing a priori that it is correct.

I am unsure if I will convince this developer to not use "symbolize_keys". I am rowing against the tide.

Update: Not only did I not convince the developer, but the system's architect rejected it also.

SSL terminating tunnel using ghostunnel

From time to time the need for a simple SSL terminating tunnel is wanted. This is used to enable the browser to use an HTTPS connection to an HTTP server. It is common to use a proxy server, but I was curious if there was something simpler. I was able to create an SSL tunnel using ghostunnel

https://github.com/ghostunnel/ghostunnel

To build it for MacOS 14.7 I needed to update the go.mod to use toolchain go1.22.7 (instead of toolchain go1.22.4).

Created the cert and key

openssl req \
  -x509 \
  -newkey rsa:4096 \
  -keyout key.pem \
  -out cert.pem \
  -sha256 \
  -days 3650 \
  -nodes \
  -subj "/C=US/ST=RI/L=Providence/O=MojoTech/OU=Labs/CN=clientsite.com"

Add the client's domain name to /etc/hosts

127.0.0.1 clientsite.com

Run the tunnel

sudo ghostunnel server \
  --listen clientsite.com:443 \
  --target localhost:3000 \
  --cert cert.pem \
  --key key.pem \
  --disable-authentication

Run Python's file directory serving http server

python3 -m http.server 3000

And finally, open https://clientsite.com in the browser or with curl

curl -k https://clientsite.com

I think since this is Go and executables are statically linked, you could share the ghostunnel executable and PEMs with other developers.

Bye little Linode VM

The website https://andrewgilmatin.com/ is no more. I wasn't using the little Linode VM for much of anything anymore. If I were to keep it running I really needed to move it off of the discontinued CentOS 7. I would have to transition content, old code, and figure out security. Much has changed since I last needed to do that. I was not up for that marathon again.