// Package domains is the platform-domains machinery: the account-sqid // encoder and the agent's reconcile pass that mints platform domains, stamps // DNS/TLS health, and materializes bucket account manifests into the // registry. See docs/superpowers/specs/2026-08-02-custom-domains-design.md. package domains import "strings" // sqidAlphabet is FROZEN FOREVER: lowercase base-23 with the lookalikes // i, l, o removed. Every platform domain ever minted embeds a sqid over this // alphabet — changing it (or the offset below) re-homes every one of them. // The golden test (sqid_test.go) exists to make that impossible to do by // accident. Deliberately not configurable: vanity account names in the // platform domain invite squatting; custom domains are the vanity mechanism. const sqidAlphabet = "abcdefghjkmnpqrstuvwxyz" // SqidAlphabet exports the frozen alphabet for one purpose: an error message // that tells someone which letters a sqid may contain (the CLI's -account-id // refusal) should read those letters from the encoder itself, so it can // never drift from the truth it is describing. const SqidAlphabet = sqidAlphabet // sqidOffset guarantees a minimum length of 3: encoding id+23² in plain // base-23 means every id ≥ 1 needs at least three digits, with no padding // case-split (a single strictly-monotonic bijection, so distinct ids can // never collide). Frozen with the alphabet, for the same reason. const sqidOffset = 23 * 23 // Sqid encodes an account's registry row id as its frozen domain label — // e.g. the built-in ops account (id 1) is Sqid(1) forever, on every // deployment. func Sqid(id int64) string { n := id + sqidOffset var buf [16]byte // 23^16 dwarfs int64; never grows i := len(buf) for n > 0 { i-- buf[i] = sqidAlphabet[n%23] n /= 23 } return string(buf[i:]) } // ValidSqid reports whether s is shaped like something Sqid could have // emitted: 3 to 16 letters, every one of them in the frozen alphabet. // // This is STRICTER than release.ValidAccount (^[a-z]{3,16}$), and the // difference is the whole point. ValidAccount gates what may become a bucket // path segment, so it accepts any lowercase word — including account NAMES // like "ops" or "amadan". A name is not a sqid: the frozen alphabet omits i, // l and o, so "ops" is a string Sqid can never produce for any id. Anything // that means "this value IS an account's identity, matched as a sqid and // never as a name" — the CLI's -account-id, above all — must ask THIS // question, because accepting "ops" there resolves to an account that does // not exist, and writes under it without ever failing (the real ops account // is Sqid(1), "bab"). // // The 3 floor is sqidOffset's guarantee and the 16 ceiling is Sqid's buffer; // both are frozen with the alphabet. func ValidSqid(s string) bool { if len(s) < 3 || len(s) > 16 { return false } for i := 0; i < len(s); i++ { if !strings.ContainsRune(sqidAlphabet, rune(s[i])) { return false } } return true }