Files
etalon 976f5238f8 feat: scaffold app skeleton with config, ULID, health endpoints, compose stack (phase 1)
- internal .env loader (real env wins) + strictly validated config struct
- ULID package: 48-bit ms timestamp + 80-bit crypto randomness, sortable
- HTTP server with recovery/request-id/trusted-proxy/access-log middleware
- /healthz, /readyz (pluggable checkers), /metricsz (counter registry)
- multi-stage Dockerfile (alpine, non-root) + compose with healthchecks,
  app bound to 127.0.0.1:8787, mongo unpublished, graceful 15s shutdown

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:10:30 +02:00

95 lines
2.5 KiB
Go

// Package ulid generates ULIDs (https://github.com/ulid/spec): 26-character
// Crockford-base32 strings of a 48-bit millisecond timestamp followed by
// 80 bits of cryptographic randomness. Lexicographic order equals creation
// order at millisecond resolution, which the schema relies on for cursor
// pagination and time-ordered message ids.
package ulid
import (
"crypto/rand"
"fmt"
"time"
)
const alphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
// Len is the length of the canonical string form.
const Len = 26
var decode [256]byte
func init() {
for i := range decode {
decode[i] = 0xFF
}
for i := 0; i < len(alphabet); i++ {
decode[alphabet[i]] = byte(i)
// Crockford base32 is case-insensitive.
decode[alphabet[i]|0x20] = byte(i)
}
}
// New returns a fresh ULID for the current time.
func New() string { return At(time.Now()) }
// At returns a ULID whose timestamp component is t (randomness still fresh).
func At(t time.Time) string {
var b [16]byte
ms := uint64(t.UnixMilli())
b[0] = byte(ms >> 40)
b[1] = byte(ms >> 32)
b[2] = byte(ms >> 24)
b[3] = byte(ms >> 16)
b[4] = byte(ms >> 8)
b[5] = byte(ms)
if _, err := rand.Read(b[6:]); err != nil {
// crypto/rand never fails on supported platforms; if it does, the
// process cannot safely generate ids at all.
panic(fmt.Sprintf("ulid: crypto/rand failed: %v", err))
}
// Base32-encode 128 bits into 26 chars (130-bit capacity, top 2 bits 0):
// consume bytes from the least-significant end, emit 5-bit groups
// right-to-left, which yields the canonical big-endian representation.
var out [Len]byte
acc, nbits, j := uint32(0), 0, Len-1
for i := 15; i >= 0; i-- {
acc |= uint32(b[i]) << nbits
nbits += 8
for nbits >= 5 && j > 0 {
out[j] = alphabet[acc&31]
acc >>= 5
nbits -= 5
j--
}
}
out[0] = alphabet[acc&31] // remaining 3 timestamp bits
return string(out[:])
}
// IsValid reports whether s is a well-formed ULID.
func IsValid(s string) bool {
if len(s) != Len {
return false
}
for i := 0; i < Len; i++ {
if decode[s[i]] == 0xFF {
return false
}
}
// First char encodes the top 3 bits of a 48-bit value; > '7' overflows.
return decode[s[0]] <= 7
}
// Timestamp extracts the embedded creation time.
func Timestamp(s string) (time.Time, error) {
if !IsValid(s) {
return time.Time{}, fmt.Errorf("ulid: invalid id %q", s)
}
var ms uint64
for i := 0; i < 10; i++ { // first 10 chars = 50 bits, low 48 are the timestamp
ms = ms<<5 | uint64(decode[s[i]])
}
return time.UnixMilli(int64(ms)).UTC(), nil
}