contacts: mint web-created contact ids with ChangeId
The web form's contacts get twelve letters, not a UUID's thirty-six;
put overwrites a match, and 48 bits keeps that out of the mix.

Assisted-by: Claude Opus 5 via Claude Code
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
change kwzzzqwkzwxupoqsxzyusrkrpmmzwqxq
commit 012829a0351d6fcaa6f9ce97ee3bbe0ac90dfda1
author Alpha Chen <alpha@kejadlen.dev>
date
parent kzmmrmwp
diff --git a/lib/pro_tacts/web/contacts.rb b/lib/pro_tacts/web/contacts.rb
index 1066d81..b7f95f1 100644
--- a/lib/pro_tacts/web/contacts.rb
+++ b/lib/pro_tacts/web/contacts.rb
@@ -1,10 +1,9 @@
-require "securerandom"
-
 require "pro_tacts/admin/card_form"
 require "pro_tacts/admin/contact_dialog"
 require "pro_tacts/admin/contacts_edit"
 require "pro_tacts/admin/contacts_index"
 require "pro_tacts/admin/contacts_show"
+require "pro_tacts/change_id"
 
 module ProTacts
   class Web < Roda
@@ -37,7 +36,9 @@ module ProTacts
           if first.empty? && last.empty?
             dashboard(query: r.params["q"], notice: "A contact needs a name.")
           else
-            id = SecureRandom.uuid
+            # Store#put overwrites, so the width has to make a collision
+            # unthinkable rather than caught: 48 bits, for a family's book.
+            id = ChangeId.mint(12)
             store.put(id, Admin::CardForm.new_card(id, first, last))
             r.redirect "/contacts/#{id}", 303
           end
diff --git a/test/pro_tacts/admin/test_contacts_pages.rb b/test/pro_tacts/admin/test_contacts_pages.rb
index 1bc5f57..8edd47c 100644
--- a/test/pro_tacts/admin/test_contacts_pages.rb
+++ b/test/pro_tacts/admin/test_contacts_pages.rb
@@ -857,7 +857,7 @@ class AdminContactsPagesTest < Minitest::Test
 
       assert_equal 303, last_response.status
       id = last_response["Location"].delete_prefix("/contacts/")
-      assert_match(/\A[\w-]+\z/, id)
+      assert_match(/\A[k-z]{12}\z/, id)
 
       follow_redirect!
       assert_equal 200, last_response.status