id

package
v0.1.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 11, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

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

View Source
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.

View Source
const DefaultSuffixLength = 8

DefaultSuffixLength is the workspace default. See the package comment for why eight.

Variables

View Source
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

func CheckShape(id string) error

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

func Derive(c Config, seed []byte) (string, error)

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

func Mint(c Config) (string, error)

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

func New(c Config, prefix string) (string, error)

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

func NewDerived(c Config, prefix string, seed []byte) (string, error)

NewDerived is New with a suffix from Derive.

func Same

func Same(c Config, a, b string) bool

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

func Slug(s string) string

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.

func Split

func Split(c Config, id string) (prefix, suffix string, err error)

Split separates an id into prefix and suffix and validates both against the config. The suffix is the last dash-separated segment; everything before it is the prefix, which may itself contain dashes.

func Valid

func Valid(c Config, id string) bool

Valid reports whether id parses under the config.

Types

type Config

type Config struct {
	Alphabet     string
	SuffixLength int
}

Config carries the two workspace settings that shape every id. Zero value is not usable; use Default or fill both fields.

func Default

func Default() Config

Default returns the spec defaults.

func (Config) Validate

func (c Config) Validate() error

Validate reports whether the config can mint and check ids.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL