Thomas Cannon

warden 0.3.0 released

A new version of warden-webauthn is out (the foundation for devise-passkeys)

This one ensures that the underlying credentials must be discoverable by default; but provides hooks to override in edge cases where you need to allow non-discoverable credentials. Check out the Github issue for more info!

Check it out! And, as always, we need maintainers!

devise-passkeys 0.2.0 released

The next alpha for devise-passkeys is out!

This includes:

There's still a long ways to go, but check it out! And, as always, we need maintainers!

I stand corrected…

What’s the over/under on GitHub being down system-wide twice in as many weeks due to running Edge Rails on arguably one of the most mission-critical bits of internet infrastructure?

Devise-passkeys 0.1.0 is out

👋 Updating with some news! I've cut an initial alpha of devise-passkeys

Note that this is an alpha build, so it should be used with experimental projects. I wanted to get this version cut as soon as the test coverage was finished so that folks could start providing some concrete feedback.

There's still a long ways to go, but check it out! And, as always, we need maintainers!

One small step for man, one giant leap for mankind 🎉 🎉 🎉…

Huge, huge congrats to the Google team for making it happen 💪

This incredibly cursed meme came to me today


A version of the "They don't know meme", with someone in the corner saying "They don't know passkeys replace passwords + MFA, are platform independent, free, and safer for everyone", while everyone else is talking about incorrect passkeys implementations

Oops, wrote 1,000 words about what I've been working on for Little CRM (in reality, the design system I'm building for Practical Computer; and why that's the first thing I'm doing)


Also look at this little feller! 

The mascot for Little CRM: Tangelo. They are orange, have a computer screen for a face, glasses, and are wearing a sporty bow-tie

First draft of the Little CRM landing page!

Love that my internet went out right as I go to share the first draft of my landing page for Little CRM. 🫠

Want a privacy-first CRM that will allow you to:

  • Focus on your best customers
  • Reflects the modern ways indie creators are supported
  • Helps you stay focused on the marketing efforts that are actually working for you

I’m building it out in public! Sign up for updates here:

Building in public 1

👋 I’m stuck waiting on laundry to finish, so carving out some time for an announcement!

I’ve been wanting to build something in public for a while, and there’s no time like the present.

I’ve had an idea kicking around in my head for a privacy-first CRM that’s aimed at very small companies/operations. It’s directly informed by my own experiences working in Noko, and publicizing my music.

The audience is very focused on small operations. Stuff like my music, smaller SaaSes/service businesses. Where you want *some* place to keep track of leads & seeing who your most valuable customers are, but you specifically don’t want to track a ton of data.

And there are ancillary/modern assumptions, like tracking different product purchases by default, tracking influencers/promo efforts, and some way of ranking how effective you find particular marketing channels.

Some implementation notes:

  • It’ll also be a real-world example of a passkeys first application; because right now there are way too few of those
  • It’s a chance to really use Web Push!
  • I know it’ll be a vanilla/minimal JS app; to prove again that you don’t need a ton to make a great, useful app.
  • I think I’ll also be working on a vanilla JS/HTML variant of Standerd, made by my friends over at Nicer Studios. Have to try it out before I make that call

What if I told you this was only ~10% of them?

a memento wall of kira's report cards for daycamp, even back when she was a puppy

Mesh Network made it to an art show!

Last night was the first art show at Atlas Local, and I was lucky enough that two different people wanted to collaborate!

First up, my friend Dorcas Lanyero and I collaborated in a giant Mesh Network inspired painting! It turned out incredibly; and there are still some bits we want to improve (such as actually painting on the photovolic shading/projections onto the vertical greenhouses)

A photograph of the Mesh Network painting: a verdant town ensconsed in a mountain with a waterfall nearby, a maglev train running behind the waterfall, and vertical greenhouses


Also: Em Blitstein embraced the inner 90s punk in us all and made a zine; with some of the liner notes and a poster design I’ve been toying around with!

A spread of Mesh Network inside Em Blitstein's zine; which includes some comments from the liner notes and a promotional poster I've been working on for the album

Ruby Passkeys Update

Posted a quick update about the Ruby Passkeys organization in the passkeys issue for Devise


The gist is:

  • There are very early alpha implementations for Devise and Warden, including a template repo
  • Once again, I am asking for desperately needed maintainers for this

City Skylines 2 really has to ship with proper transit & walkability 🤞🤞 DLCing that is ridiculous…


a photo of my dog smiling at the camera in a camping scene

👋 Hey y’all! Unfortunately, I got laid off from my job. I’m actively looking for work; if you’re interested in hiring someone with 16+ years of practical, real-world, customer-focused development work; please reach out! 😄

I also love doing customer support, developer relations, build-chain improvements, and engineering management.

I’ve put together a “I’m for hire” page below

I am delighted to inform you that this riiiiips…

HTTPS, Subdomained System Tests in Ruby on Rails

Getting puma to use self-signed certificates in Test

Install the localhost gem, which allows Puma to use self-signed certificates in your test environment:

group(:test) do
  gem 'localhost'

It’s not documented anywhere in Capybara, but Capybara’s built-in Puma handler allows you to issue a custom bind

Capybara.run_server = true
Capybara.server = :puma, { Host: "ssl://#{Capybara.server_host}"}

I found that you do need to explicitly pass the Capybara.run_server = true argument in your system tests

You also need to have Selenium Webdriver explicitly accept insecure hosts:

For example:

Capybara.register_driver :chrome do |app|
  options =
  options.accept_insecure_certs = true, browser: :chrome, options: options)

With that, Capybara runs with self-signed certificates in development, and the WebDriver will accept them.

Running subdomained tests

Because of how macOS does not handle wildcard DNS resolution for localhost by default, if you need to run your tests using subdomains, you’ll need to use a loopback DNS service like
For example:

Capybara.app_host = ""

Depending on how your existing tests are setup, you might also need to setup a custom initializer block in config/environments/test.rb to override the tld_length

Rails.application.configure do

config.hosts << “”

if ENV[“PREP_SYSTEM_TESTS”].present? config.action_dispatch.tld_length = 5 # = 5 top-level host details to throw out Rails.application.routes.default_url_options[:host] = “” # Necessary for routes to play nicely # … end end

The next project I’m working on: Data-augmented composition. In essence: a way to use data as an input for composition. It won’t drive the entire piece, because I still want a human elements but the transcendent nature of generative music is appealing to me

A diagram of my next project: data-augmented composition, to transform data into components that can be used for composition

I am now the proud owner of the most cumbersome sampler out there, thanks to #SuperMIDIPak (

A photof of a SuperMIDIPak cartridge

Rate Sheets are in general beta for Noko!…

See how you’re doing in 2023, and make sure you’re spending your work time on the most valuable projects

Which, upon reflection, is reaaaallllllyyyyyyyy fuckin shitty after the Super Bowl

Listening to Off The Wall for the first time, uh, and 2010s Justin Timberlake was really just copying the answers over MJ’s shoulder, wasn’t he?

The UJS pattern that Rails has (had? The Rails JS & documentation story is messy) is arguably the best bridge that’s been implemented between client & server.

It can be rigged up with basic data attributes, it is powered by the browser’s native event-handling. That makes it easy to extend/customize, it doesn’t get in your way, and there isn’t a deadly tight coupling between the client & server codebases