Bless me, Father, for I have sinned. It’s been nearly six months since my last blog post. Jesu…!
The only way for me to even explain the roller coaster I’ve been riding is to go chronological order, keeping in mind that there are quite a few overlaps.
Albatross #1: The Sale of My Other Home in Tewksbury (April to Present)
My “other” home is the residence of my ex-wife and autistic son. I have 50% ownership. It was to be sold upon my son’s 21st birthday per our divorce agreement. That was 4+ years ago.
The primary difficulty is that my ex-wife is a hoarder. I hesitate to use the term as reality shows tend to equate the term with people to store their own excrement in jars. This is certainly not the case. She simply does not throw things out. Ever. Hers, stuff I left behind, our son’s, her late mother’s. She also does not clean as often nor as completely as she should, what with all the stuff everywhere, which is also a problem.
The house in question is a 3BR federal-style home with an attached in-law apartment that her mother was living in while we were married. Her mother went into assisted living and passed away over a decade ago and my ex-wife never went through her stuff. I mean, she used the space. After the local school system essentially threw my son out after botching numerous efforts of inclusion, my ex-wife joined a homeschooling group and used the empty in-law apartment to host various homeschooling activities and was able to get my son involved in activities not otherwise restricted to folks with his condition.
Of course, running your own homeschooling situation means purchasing lots of educational materials, materials that she never got rid of, materials that I had to help pack and move, in addition to all of her late mother’s things. Ugh.
I could rant more about the situation, much more, but it drains me. It brings back memories of a very painful and lonely past and the mountain of stuff that I thought I had left behind is all there and needs to be moved yet again. The primary reason for my involvement is that my ex-wife lacks a support network and is incapable of doing it alone. If it’s going to get done, I need to be directly involved.
While that particular set of hurdles to getting the house on the market is passing, a new one has appeared. While Tewksbury has a sewer system, our home was never tied in to it. It has a septic tank. By law, it needs to pass a Massachusetts Title V inspection before it can be sold. The septic system is over 40 years old and, after speaking to the guy whose company does these things and who has lived in town forever, it probably won’t pass. I should just bite the bullet and have the work done to decommission the septic tank and tie into the sewer system. Ka-ching.
Albatross #2: The Demise of Brick Mill Games, LLC (April to June)
While Brick Mill Games, LLC ceased to be a legal entity as of 31-Dec-2025, I still had legal and ethical obligations to fulfill. The dissolution of a business partnership, especially when the partners considered themselves to be friends, is not an easy experience. Things get very serious once the dreams of success fade away and monies and intellectual property concerns take center stage.
Gaining Stability
From April to June, I was focused on tying up the loose ends of the mountain of Brick Mill Games, LLC code and the assignment of updated software copyright notices on the files. One of the major discussion points between Paul and me was the assignment of copyright and the future of code developed under the shared auspices of BMG. In the end, a fair compromise was reached (or so I thought): code that I had developed prior to the incorporation of Brick Mill Games would revert to my sole copyright, new code that provided a foundational platform would also fall under my sole copyright, while code that was developed for the game system itself would be under shared copyright. As far as the former is concerned, that included the Crux application service engine, the non-TOCS (TOCS being the game system) Ruby gems and Javascript variants of the Ruby gem logic.
Unfortunately, during the last few months of development, I neglected to separate game system code that would fall under the purview of joint ownership and application support code which would not. Simply put, I mixed both types of code within a TOCS-labeled library. So I spent three months separating the appropriate files out into Mill #6 libraries as well as cleaning up the tattered state of the TOCS code.
There was a lot of work to do and it involved a lot of the project’s 10-year development history. First, I converted the slew of standalone Ruby scripts into a Ruby gem and a Rakefile that can be used to build the appropriate generated files. An example of this would the conversion script that would convert an Order-of-Battle spreadsheet CSV file into an XML file for post-processing. Another example would be a script to generate counter graphics from the OoB XML file.
The second major piece was the removal of support code and test harnesses for the Javascript variants of my application support code: XAPI, PixMill, WebFX, etc. I had been using TOCS to develop these libraries and it only made sense to include the development apparatus within the TOCS infrastructure. With the dissolution came the separation. Mill #6 now handles the design, development and testing of those foundational support libraries. TOCS now receives copies of the developed and tested libraries for its development. In essence, Mill #6 is now a technology supplier to the TOCS project, should it continue.
The third major piece involved the installation and porting of technology updates to the BMG servers. The intense pressures to deliver the TOCS platform required me to ignore issues within the supporting technologies. The Crux platform needed some updates. The Javascript support libraries needed some updates. The separation of some code from the TSL (TOCS System Library) into Mill #6 libraries also required changes to the API to improve its usability. The sum total of these changes was not insignificant and the TOCS code itself needed to be updated to account for these changes.
An example of this was the namespace pollution fix for Crux. While Crux currently supports multiple application handlers to handle URL requests for each application, it all runs as a monolithic process. Worse yet, each application handler and its associated libraries shared the same namespace when it came to naming classes. I discovered this when I tried to build a RegistryService class for two different applications. The loading of one caused the loading of the other to fail in ways that were mysterious at the time. Forcing applications to encapsulate their classes within an overarching namespace class of their own fixed this problem, but it meant that all of the TOCS application code had to be modified to account for this new architecture. That took time, and patience, and tedious, repetitive code changes.
Finally, at the time of dissolution, the state of some of the TOCS functionality was in tatters. We were in the middle of an architectural change with regard to OoB (Order of Battle) definitions and editing and this code was clearly broken. While the project may be considered dead, or “mostly dead”, it could still serve as a reference platform for future work and broken code hardly makes for a good reference platform. So, in addition to separating code out and reworking the API changes and fixing some design limitations, I repaired the interrupted functionality.
And so, as of 09-Jun-2026, the TOCS project became stable enough to continue work on it, assuming someone wants to take up that mantle.
It Reaches Out From the Grave
Once I got the TOCS application code in a stable state, I decided to port it to the Mill #6 server. While I certainly don’t want to continue working on it on my own, it does serve as an excellent test bed for Crux work and I also don’t want to introduce incompatible changes to Crux which would break TOCS. While TOCS won’t ever make it to my production server, it is an excellent real-world test application on my development server.
And the damned thing bit me on the ass almost immediately.
Hang on… it gets a bit technical.
Crux is written in Ruby. As such, it relies on some Ruby gems (code libraries) for some of its functionality. Ruby gems come from one of three source groups: those bundled with the installed Ruby package, those stored at the gem repository at rubygems.org, and those stored in a private Ruby repository. As Ruby is a scripted language, all scripts that require gems require access to the gem’s source code. So, if you store your gem on a public server, everyone gets to see your code. If you have cool tricky code that you’d like to keep private, you will need a private Ruby repository.
Brick Mill Games had a private gem repository. Or, should I say, I built one, though “built” is pretty strong. I built a website with a Ruby front-end which relied on a public gem called Geminabox which was a Ruby gem repository packaged as a gem. All you needed to do was build a back-end that could handle URL requests as well as CLI (command-line interface) calls via a well-documented API and, boom, private gem repository behind a username/password authentication wall. Sweet!
That is, until the Ruby language evolved to a new version, which modified its gem API and Geminabox ceased to work. Worse still, and this is a common problem with 3rd-party code, the original author stopped maintaining the project.
Now what? Do I fix Geminabox and take on ownership and maintenance responsibilities or do I do my own thing? If you have been following my blog, you know what the answer is.
Enter Gemz

This is why I wrote the Gemz application within the Crux application framework. I built my own gem repository and I’ve been using it for months now. It’s great for storing, retrieving and managing gems. It does not, however, know how to handle the CLI interfaces that the Ruby community uses for gem installation and management.
The TOCS application needs the Mill #6 Cartesia and PixMill gems to be on the server to do some of its work. As the Geminabox-based service supported this, all I needed to do was add the following lines in a file named “Gemfile”:
source "https://rubygems.brickmillgames.com" do
gem 'cartesia'
gem 'pixmill'
end
Gemfile is used by “bundler”, a Ruby gem installation and maintenance automation engine. As bundler uses the tools that are standard within the Ruby gem universe, this is an easy way to register the TOCS requirements with the Crux application server.
Except that Geminabox doesn’t work anymore and Gemz is ignorant of the CLI (Command Line Interface).
Gemz/CLI
So the next thing I worked on is the CLI interface to Gemz. Thankfully, the interface is, as I said, well documented at https://guides.rubygems.org/rubygems-org-api/.
First things first, though. While the original rubygems.brickmillgames.com had an authentication system built in, it was live. Gemz is going to rely on the API to serve authentication tokens. Unfortunately, while the documentation seems to give excellent details regarding how each call behaves, it doesn’t describe all the calls that bundler uses as it does its magic.
As an example, this is how, I believe, authentication is handled with the rubygems API and bundler. First, the Gemfile:
source "https://username:password@crux.mill6.com/gemz" do
gem 'cartesia'
gem 'pixmill'
end
With this change, we are telling bundler that a private gem repository exists at crux.mill6.com/gemz and that the given username:password combination must be used to get an authentication token for subsequent calls. At least, that is what I think is going to happen.
As of mid-June, I was able to confirm part of that. After probing the system, I had full support for “/api/v1/api_key.json”. From the documentation:
Retrieve your API key using HTTP basic auth.
$ curl -u "nick@gemcutter.org:schwwwwing" https://rubygems.org/api/v1/api_key.json
{ "rubygems_api_key": "701243f217cdf23b1370c7b66b65ca97" }
If you use “curl -u myname:mypw https://crux-devx.mill6.com/gemz/api/v1/api_key.json” you will receive:
{"rubygems_api_key":"apiToken..."}
(Note that names, passwords and tokens were not provided due to obvious security concerns. Duh.)
It’s a start, but there’s still more to do.
But… the Crux Authentication System Can’t Do That
Yeah. It couldn’t. Crux was designed to serve the needs of web-based applications running in a browser. You login; you do stuff; you log out. Command-line tools that require access tokens do the following: get a token, do stuff by passing that token with every operation, just leave.
If I used the same system with CLI interfaces, I would have a lot of open tokens sitting in the authentication database waiting to be used and abused. So now, tokens expire.
I had the vestiges of such a system in place, but never tested it nor relied on it. As of June, tokens expire after a set amount of minutes. For login sessions, it’s a full day. For CLI access, it’s fifteen minutes. CLI processes should be able to do what they need to do in fifteen minutes. In an interactive setting, if your token expires, you will be able to refresh it. In a CLI setting: nope.
For the first time in years, I did a major overhaul of the Crux authentication system, which required changes to the application interface, which required updates to all of my Crux-based applications, including Gemz and TOCS. It was a lot of work, but the interface is simpler and, yet, more robust.
Speaking of Authentication
Bitbucket, which is the code repository service I use, warned me about a year ago about changes in their authentication system. I did the bare minimum to live with that knowledge until it also bit me on the ass.
I tried to do things using Bitbucket’s new way a few months ago, but I couldn’t get it to work and didn’t spend anymore time on it. Finally, I had no choice and I found myself locked out of my code repositories. Panic immediately set in.
Long story short, after perusing their documentation and relying on lots of trial & error, I was able to generate an API token on the Bitbucket site and was able to download and upload code from the repository using the token to gain access. As TOCS sits in its own repo with a separate login account, I had to go through this exercise again to be able to access the TOCS code.
Multiple hours later, reconfiguration by desktop and laptop systems to account for all of the changes I needed to make and code to download, all is well again at Mill #6.
Epilog: A Grinding Slow Death to the Present
After doing all of the above work, according to an agreement that I thought was in place, Paul decided that no such agreement was finalized. Complicating this seeming about face was four months of radio silence from him that was only broken after I sent him a status report of the work I did.
His response to my email detailing said work was… how should I put it… less than professional. I could go into more detail, but I’m going to consider the nuts and bolts of our discussions to be a private matter. I am not in the habit of bad-mouthing people, especially when they are neither prepared nor in a position to defend themselves. Suffice it say that I was not pleased. Weeks later, I’m still not pleased, to put it lightly. We’re currently trying to schedule a video call to sort this out.
The Delights: Consimworld Expo & WBC (July)
In July, I attended two large game conventions with my friend, Mark Hinkle. Consimworld Expo is a game convention set in Tempe, AZ which focuses on large (aka: monster) wargames. It is primarily a wargame convention, though it does not limit people into playing such games. There is an open gaming area, albeit small. WBC is the World Boardgaming Championships and it is a huge tournament-style convention set in Seven Springs, PA.
The reason for attending both conventions was to showcase the upcoming NES release of On Hell’s Highway, an updated version of Victory Games’ Hell’s Highway, both designed by John Butterfield. As each convention is a week-plus-long affair, Mark and I usually choose only one to attend in any given year. However, while OHH’s core audience is in Tempe, John Butterfield was attending WBC and going to this convention would provide all of us a final opportunity to play test the game using the latest and greatest rules, maps and materials. Plus, Mark, being the proprietor of NES, would be able to discuss some business-oriented topics with John in person.
As neither of us could really reserve two full weeks away from our homes, we opted for 4-5 day stints each, not including the 9+ hour drive back and forth to PA. While I enjoyed myself at each convention, I probably won’t make the same plan again. It was like drinking two half-glasses of water instead of one full one. At both conventions, it was difficult to align my limited schedule with other people who were attending the convention and/or the game tournament schedules. In one case, there were five games I was interested in and they were all being played on Tuesday at 2pm. What are the odds?
Regardless of the challenges, the time spent was a welcome respite from the albatrosses I was strangling at home. I got to see folks I only see at conventions and I got to play new games. Plus, Mark is an excellent traveling companion, so there’s that. But, again, I don’t think I’ll do the split. I’d rather pick one convention and enjoy my whole time there.
A Delightful Getaway (September)
With September being our anniversary month, Claire and I decided to not wait until the end of the month to go away, but, instead, we went up to Rangeley, Maine for a few days of R&R. After our first summer without hiking in quite a long time, it was good to go to a new place and explore.
We stayed at the Loon Lodge Inn and had a very relaxing time. While I did enjoy the trip, I am going to consider other accommodations next time. While the area was between their busy summer and winter seasons, the lodge was a little too hands-off, perhaps a remnant from the Covid-19 days of trying to run an inn w/o contaminating people. As an example, as we were arriving on Labor Day, the staff left the place at noon. Our room information was tacked to the front door when we arrived. While I could have blamed our Labor Day arrival, the condition of the door, pockmarked with tack holes, told a different story. We didn’t meet any of the inn staff in a meaningful way until their on-site bar was open on Wednesday. While it was nice to have the place to ourselves on one hand, we weren’t able to get any guidance from the innkeepers on where to eat or other attractions. It was a little cold, to be honest.
Still, the area stuck with me. We will definitely be going back.
Delightful Transitions: Killing Ground 2.0 (June to Present)
The On Hell’s Highway project is heading into production. The months of playing the game and tweaking the rules, counters, charts and other components is coming to an end. I’m very happy with how it is all turning out.
In the meantime, I have been slowly taking on my role as developer for the Killing Ground reprint. I have been hard at work in the background writing and organizing the combined Killing Ground / Overlord rules set. I’m not at liberty to discuss the details because, frankly, it is morphing beyond a simple edit job. While most of the game’s systems will remain the same, the NES crew will be trying out some new ideas and/or incorporating some ideas from the Jaws of Victory game. Some fans of the existing game will balk; others will welcome the changes and accept them as improvements. That said, we will be testing the new ideas behind closed doors until we think they have merit. Why get everyone riled up for no reason.
Crux 2.0
The recent changes to some underlying elements of the Crux architecture has given rise to long-dormant ideas and improvements.
Websockets
The namespace pollution issue that I uncovered with Crux should not have surprised me. On the surface, the design lends itself to distributed application support. However, it’s all one modular, monolithic application sitting on one HTTP port. If the Gemz app aborts, it will take down everything else: the dice roller, the ToDo application, the credentials authenticator, all of it.
Secondly, the stateless HTTP model for service API requests does not allow for server-based push notifications. It is primarily a “do something and let me know how it went” model. If the “do something” is time consuming, the request will wait and the web page and/or other type of client will become sluggish. I added the idea of “fire and forget” API calls to Crux where the “do something” simply sets the process in motion and the client keeps polling the system with “how’d it go?” questions. It works, but it’s clumsy. What you really want is for the client to fire off a “do something” and have it set up a listener in the background for the asynchronous result.
Websockets will allow this. It differs from HTTP requests in that it establishes a server connection and maintains it throughout client execution. The HTTP request lifecycle is: establish a connection, send the request, receive a response, close the connection. Websockets allows the one connection to stay active and send/receive data at will, including receiving data when no request was sent, aka push notifications.
Websockets management is a bit closer to the metal than the usual HTTP request protocol, such as that offered by the Javascript fetch API. One can mimic the HTTP method using Websockets, but one can also add other messaging methodologies alongside it.
Queues and Services
As detailed above, the current Crux system is more of a modular monolithic beast, vulnerable to any one module bringing down the entire system.
Instead, one can redesign the system such that each module is now its own independent service, tied to the central architecture via message queues. The central module will be the Crux authenticator and app registry service. All Websockets-based connections to Crux-based apps will be made to this one access point. From there, Crux will communicate with each detached application via messages sent to application message queues. If one of the applications dies, the others can continue. If the administrator needs to shut one application down, or suspend service, it won’t have to take everything else down.
Migratory Paths
The central Crux Authenticator and Registry Service Environment (ARSE)… No, no, no, no. No. Just kidding.
Crux User and Registry Service Environment (CURSE)? Still no.
Whatever we choose to call it, as the authenticator isn’t tied to HTTP, it doesn’t have to sit on port 80, or the other usual suspects. We can still, for migratory reasons, still have an auxiliary process listening on port 80 and have it simply(?) channel data to and from the new Websockets interface. That is, until we build the new client-side APIs for WS-oriented comms.
Related to this is having support for a CLI-interface pathway tied to HTTP. Even if we move to a Websockets-based system, I think we will still need to handle HTTP requests.
The Crystal Language
Crux is built using Ruby. It is a scripted language, meaning that there is overhead involved with the constant parsing and execution of the code logic as it runs. With a scripted language, it is not the code logic that “runs” per se, it is the language interpreter that is running and is reading the code logic and translating it and managing the language environment repeatedly. All of that is execution overhead that a compiled language doesn’t have.
Crystal is a programming language that looks like Ruby, but is compiled. Therefore, no overhead. However, while it looks like Ruby, the language designers did not support everything that Ruby supports and has changed how some elements of the language work. For example: ‘s’ in Ruby is a 1-letter character string. In Crystal, it is a character, which is NOT a character string. The two languages treat some character and character string syntax and operations in different ways and migrating code between the two will be a chore.
Another issue revolves around Ruby code libraries, known as gems. Crystal uses something similar called shards. There are public shard repositories. I will have to convert my gems into shards and probably build a private shard repository site.
Even with all of that, I will probably write Crux 2.0 in Crystal. I think the benefits will outpace the difficulties. We’ll see…
New Crux Apps: Bookmarks and Messages
Being a software engineer of some skill can be a burden. When I find a bug or some productivity hurdle in other people’s software, it sets my teeth on edge. I can do it better.
You would think that importing and exporting bookmarks from one browser to another would be dirt simple. But, no. The reason is dirt simple: each browser manufacturer doesn’t want you to use a rival’s product. So, importing gets all the bells and whistles and exporting doesn’t.
Over the past two years, I’ve been changing browsers often. Sometimes, it’s for testing purposes. Sometimes, I watch a YouTube video detailing privacy concerns. Regardless, I have a tree of bookmarks and folders that I keep having to export and import and it almost never goes smoothly. Finally, I’d had enough.

Enter BMrk
The BMrk Crux application is a bookmarks manager. It is a database of folders and bookmarks tied to a specific user. Right now, I’ve mostly completed the server-side API. A user, via an app or browser extension, can add, move and delete bookmarks and folders. It can also receive the HTML files generated via browser export functions. It has been tested with both Safari and Vivaldi browser exports; Vivaldi is a Chromium-based browser that isn’t Chrome.
The hardest part was writing that import function for the very simple and frustrating reason that the HTML produced by each browser is different. I mean… it’s similar enough where both have DOCTYPE tags with “Netscape” within them. But the layout is different. Regardless, I got it to work.
Browser Extensions
While a user such as myself may use the new Crux app and manage bookmarks manually, it would serve the user better to use a browser extension that was bookmark-aware and communicate with the Crux back-end by using each browser’s bookmark controls. Sadly, Safari’s extension support does not include bookmarks management. Chromium and Firefox browsers do, unless they’re on an Android device. As I’ve been using Safari for a while now, I may have to switch to another browser again.
That said, I did delve into the murky world of browser extensions and I was surprised at how easy it all seemed to be. I may write one yet. Stay tuned…

Enter Mail/Msgs
The Thunderbird mail application that I’ve been using for years for email pissed me off a couple of weeks ago. What I found was not a bug, but it was an issue that soured me on how emails are managed.
I have multiple devices. I have the email systems set to not automatically delete messages so that I can access them from all devices. If your message stays in your Inbox, this is not a problem.
If you use folders and filters, and have messages moved from the Inbox to the folder of your choice, then the message is downloaded and moved into the folder and then deleted from the server. When you access your account from the second device, the email is not seen. It had been deleted.
Now, if you used the cloud for your storage, this might not be a problem, but fuck the cloud! I don’t want my personal messages on someone else’s server. And since I use a plethora of folders and filters to organize my messages, I cannot reliably use Thunderbird on my secondary devices. I have to use a browser-based email app.
And they’re not that good. As my emails are managed by DreamHost, I use their webmail site and, again, it’s not that good. I mean, it works, but it lacks quite a few features. Hmmm…. if only there was someone who can write web apps in Javascript…
I’ve written email clients before. When I was working at Pixel Magic, the corporate email system stored all emails, sent and received, in a database. As I didn’t want any personal emails to wind up in there, I didn’t configure the email app to communicate with my personal email server. But I also didn’t want to be isolated from it either; these were the days before ubiquitous cell phones.
So I wrote a command-line Perl script to ping my email server and show me the subject lines of emails I’d received during the day. If it was important enough, I’d download it and read it without deleting it from the main server. It was crude, it was all text-based, but it served its purpose and it allowed me to stay in touch while at work.
So, I’m going to build a webmail access client and server. The code on the app server will ping my email server and store messages into its own database. From there, the messages application that I write will read messages that are in the database and will send messages through the server to the email server. The server-side code will also support filters and folders as well.
Initially, I was going to call this Mail, but I am expanding the scope of this app to manage Facebook Messenger comms as well as text messages via SMS. Hence: Messages.
Right now, the entire thing is a fever dream in my head. We’ll see how far I can take this.