carlos / platform Public

feat(domains): ValidAccountName pins the slug shape account names must take

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGdTfzwT492ysLPDaWfpvJ
Paul Campbell 3f7726acd93dd7a8347a82e01f842b4cdca869fe parent 084e16f
2 files changed, +39 −0
  • internal/domains/slugname.go +16 −0
  • internal/domains/slugname_test.go +23 −0
diff --git a/internal/domains/slugname.go b/internal/domains/slugname.go
new file mode 100644
index 000000000..59ea6ec10
--- /dev/null
+++ b/internal/domains/slugname.go
@@ -0,0 +1,16 @@
+package domains
+
+import "regexp"
+
+// accountNameRe pins what an account NAME may be so it can live in a URL
+// path segment and a CLI flag: 1–63 characters of lowercase a-z, 0-9 and
+// hyphen, no leading or trailing hyphen. Names are still deliberately
+// non-unique (identity is the sqid); this constrains shape, not ownership.
+var accountNameRe = regexp.MustCompile(`^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$`)
+
+// ValidAccountName reports whether name is usable as an account name.
+// Applied at the edges where a human TYPES a name (console new-account
+// form, POST /auth/cli/accounts, `carlos accounts create`) — never at
+// auto-mint, where the personal account is named by keymail address and a
+// refusal would strand a signed-in user.
+func ValidAccountName(name string) bool { return accountNameRe.MatchString(name) }
diff --git a/internal/domains/slugname_test.go b/internal/domains/slugname_test.go
new file mode 100644
index 000000000..bed2b1663
--- /dev/null
+++ b/internal/domains/slugname_test.go
@@ -0,0 +1,23 @@
+package domains
+
+import "testing"
+
+func TestValidAccountName(t *testing.T) {
+ valid := []string{"amadan", "a", "kass-2", "ops", "a-b-c", "0day", "x9"}
+ invalid := []string{
+ "", "Amadan", "-lead", "trail-", "two words", "paul@keymail.dev",
+ "dots.no", "unicode-é", "UPPER",
+ // 64 chars — one past the limit.
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ }
+ for _, name := range valid {
+ if !ValidAccountName(name) {
+ t.Errorf("ValidAccountName(%q) = false, want true", name)
+ }
+ }
+ for _, name := range invalid {
+ if ValidAccountName(name) {
+ t.Errorf("ValidAccountName(%q) = true, want false", name)
+ }
+ }
+}