Documentation
¶
Overview ¶
Package id mints, validates, and splits docsync block identifiers.
An id is `<prefix>-<suffix>` (docs/SPEC.md §8). The prefix is a human slug chosen so grep finds it; the suffix is generated from a 32-symbol alphabet and is the actual identity. Renaming the prefix never changes identity, which is why Split exists and why equality of two ids is decided by suffix alone (see Same).
Why eight characters: 32^8 ≈ 1.1×10^12 values, the same class as a short git sha, so tens of thousands of ids across a workspace never collide in practice. Four was rejected: 32^4 is about a million and birthday collisions appear in the low thousands. Length is a workspace setting and every repo in a workspace must agree, so it is a parameter here, never a package default that silently differs between callers.
Randomness comes from crypto/rand. Ids are not secrets, but math/rand would make collisions across machines seeded at the same instant far more likely than the birthday math assumes.
Index ¶
- Constants
- Variables
- func CheckShape(id string) error
- func Derive(c Config, seed []byte) (string, error)
- func Mint(c Config) (string, error)
- func New(c Config, prefix string) (string, error)
- func NewDerived(c Config, prefix string, seed []byte) (string, error)
- func Same(c Config, a, b string) bool
- func Slug(s string) string
- func Split(c Config, id string) (prefix, suffix string, err error)
- func Valid(c Config, id string) bool
- type Config
Constants ¶
const DefaultAlphabet = "23456789abcdefghjkmnpqrstuvwxyz"
DefaultAlphabet is the 32-symbol suffix alphabet: lowercase letters and digits with the glyphs that are confused in print removed (0/o, 1/l/i). Callers may configure another alphabet; it must be ASCII lowercase letters and digits with no repeats, which Config.validate enforces.
const DefaultSuffixLength = 8
DefaultSuffixLength is the workspace default. See the package comment for why eight.
Variables ¶
var ( ErrEmpty = errors.New("id: empty") ErrNoSeparator = errors.New("id: missing '-' between prefix and suffix") ErrBadPrefix = errors.New("id: prefix must be lowercase words separated by dashes") ErrBadSuffix = errors.New("id: suffix must be exactly the configured length from the alphabet") ErrBadAlphabet = errors.New("id: alphabet must be unique lowercase ASCII letters and digits, at least 16 symbols") ErrBadLength = errors.New("id: suffix length out of range") ErrEntropySource = errors.New("id: reading random bytes failed") // ErrBadShape is an id outside the §8 character rule: lowercase letters // and digits in at least two words joined by single dashes. ErrBadShape = errors.New("id: must be lowercase letters and digits in words joined by single dashes, label-suffix") )
Sentinel errors.
Functions ¶
func CheckShape ¶ added in v0.1.3
CheckShape reports whether id keeps the §8 character rule every reader of ids relies on: lowercase ASCII words of letters and digits joined by single dashes, at least two of them -- `<label>-<suffix>`.
It is looser than Split on purpose. Split holds an id to the minting config, the suffix length and alphabet, and ids are also written by hand: the spec's own `oncall-lead-r9k1w5zb` uses a digit the alphabet leaves out, and short hand-made ids like `sess-ttl` cite and render correctly. Reporting those would bury the ids that actually break things -- `Foo_Bar` (bug 55), which a slug never matches, `ds rename` cannot relabel and a suffix lookup cannot split -- under ones that work.
func Derive ¶ added in v0.1.3
Derive returns the suffix seed determines: the same seed always gives the same suffix, and different seeds give suffixes as uniform as Mint's, by the same rejection sampling over a sha256 chain.
Why it exists: a writer with a dry run has to show the ids the real run will write. Minting at random gave `ds adopt --dry-run` one set of ids and `ds adopt` another, so the preview could not be checked against the result (bug 33). A writer seeds from what it is about to bind -- repository, file, line, the file's bytes -- so a preview and its run over the same tree agree, and two different blocks never share a seed.
func Mint ¶
Mint returns a fresh suffix for the config. It does not check for collisions: the caller owns the merged workspace index and re-mints on a hit (§8). Mint is uniform over the alphabet by rejection sampling, so a 32-symbol alphabet gets exactly 5 bits per character with no modulo bias.
func New ¶
New mints a full id from a prefix. The prefix is normalized with Slug first, so callers may pass a symbol name or a title.
func NewDerived ¶ added in v0.1.3
NewDerived is New with a suffix from Derive.
func Same ¶
Same reports whether two ids denote the same block: identical suffixes. This is the rule that makes `ds rename` safe — a relabelled prefix is still the same identity. Both ids must be valid; an invalid id is never Same as anything, including itself.
func Slug ¶
Slug lowercases s and collapses every run of characters outside [a-z0-9] into a single dash, trimming dashes at both ends. "Store.SaveSession" becomes "store-savesession"; "Session policy" becomes "session-policy". It is used both for id prefixes and for the default id of a markdown block that has no explicit id.