diff --git a/.github/workflows/generate-structured-token.yml b/.github/workflows/generate-structured-token.yml
new file mode 100644
index 0000000..a56c4f9
--- /dev/null
+++ b/.github/workflows/generate-structured-token.yml
@@ -0,0 +1,123 @@
+name: Generate Structured Token
+
+
+on:
+ workflow_dispatch:
+ inputs:
+ system_id:
+ description: 'System abbreviation for the token.'
+ required: true
+ type: string
+ environment:
+ description: 'Target deployment environment for the token.'
+ required: true
+ type: choice
+ options:
+ - Preview
+ - Production
+ domain_purpose:
+ description: 'Domain purpose abbreviation for the token.'
+ required: true
+ type: string
+
+
+jobs:
+ generate_token:
+ name: Generate Token
+ runs-on: ubuntu-latest
+ steps:
+ - name: 🔍 Validate Inputs
+ id: validate_inputs
+ run: |
+ SYSTEM_ID='${{ inputs.system_id }}'
+ DOMAIN_PURPOSE='${{ inputs.domain_purpose }}'
+
+ if [[ -z "$SYSTEM_ID" ]]; then
+ echo "::error::System identifier must not be empty."
+
+ exit 1
+ fi
+
+ if [[ -z "$DOMAIN_PURPOSE" ]]; then
+ echo "::error::Domain purpose identifier must not be empty."
+
+ exit 1
+ fi
+
+ if [[ "$SYSTEM_ID" =~ [_\ ] ]]; then
+ echo "::error::System identifier must not contain underscores or spaces."
+
+ exit 1
+ fi
+
+ if [[ "$DOMAIN_PURPOSE" =~ [_\ ] ]]; then
+ echo "::error::Domain purpose identifier must not contain underscores or spaces."
+
+ exit 1
+ fi
+
+ if [ '${{ inputs.environment }}' = 'Preview' ]; then
+ echo "env_id=prev" >> "$GITHUB_OUTPUT"
+ else
+ echo "env_id=prod" >> "$GITHUB_OUTPUT"
+ fi
+
+ - name: 🎲 Generate Token
+ id: generate_token
+ run: |
+ SYSTEM_ID='${{ inputs.system_id }}'
+ ENV_ID='${{ steps.validate_inputs.outputs.env_id }}'
+ DOMAIN_PURPOSE='${{ inputs.domain_purpose }}'
+
+ # Generate 256-bit high-strength random entropy.
+ ENTROPY=$(openssl rand -hex 32)
+
+ # Assemble token body (without checksum).
+ TOKEN_BODY="${SYSTEM_ID}_${ENV_ID}_${DOMAIN_PURPOSE}_${ENTROPY}"
+
+ # Compute CRC32 checksum encoded as 6-char base62.
+ # Base62 alphabet: 0-9 A-Z a-z; 62^6 > 2^32 so the full CRC32 fits losslessly.
+ CHECKSUM=$(python3 - "$TOKEN_BODY" << 'PYEOF'
+ import binascii, sys
+ ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ data = sys.argv[1]
+ crc = binascii.crc32(data.encode("utf-8")) & 0xFFFFFFFF
+ result = []
+
+ for _ in range(6):
+ result.append(ALPHABET[crc % 62])
+ crc //= 62
+ print("".join(reversed(result)))
+
+ PYEOF
+ )
+
+ FINAL_TOKEN="${TOKEN_BODY}_${CHECKSUM}"
+
+ echo "system_id=${SYSTEM_ID}" >> "$GITHUB_OUTPUT"
+ echo "env_id=${ENV_ID}" >> "$GITHUB_OUTPUT"
+ echo "domain_purpose=${DOMAIN_PURPOSE}" >> "$GITHUB_OUTPUT"
+ echo "entropy=${ENTROPY}" >> "$GITHUB_OUTPUT"
+ echo "checksum=${CHECKSUM}" >> "$GITHUB_OUTPUT"
+ echo "final_token=${FINAL_TOKEN}" >> "$GITHUB_OUTPUT"
+
+ - name: '📝 Write Summary'
+ env:
+ FINAL_TOKEN: ${{ steps.generate_token.outputs.final_token }}
+ CHECKSUM: ${{ steps.generate_token.outputs.checksum }}
+ run: |
+ cat >> "$GITHUB_STEP_SUMMARY" << EOF
+ ## 🔑 Generated Structured Token
+
+ | Field | Value |
+ |---|---|
+ | System ID | \`${{ steps.generate_token.outputs.system_id }}\` |
+ | Environment ID | \`${{ steps.generate_token.outputs.env_id }}\` |
+ | Domain Purpose ID | \`${{ steps.generate_token.outputs.domain_purpose }}\` |
+ | Entropy | \`(masked — 256-bit random)\` |
+ | CRC32 Checksum (base62) | \`${CHECKSUM}\` |
+
+ \`\`\`
+ ${FINAL_TOKEN}
+ \`\`\`
+ EOF
diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml
index 64658b2..490dde9 100644
--- a/.github/workflows/prepare-release.yml
+++ b/.github/workflows/prepare-release.yml
@@ -1,16 +1,27 @@
name: Prepare Release
+
on:
push:
tags:
- 'v*'
+ - '*/v*'
+
permissions:
contents: write
pull-requests: write
+
jobs:
call-prepare:
uses: leoweyr/github-release-workflow/.github/workflows/reusable-prepare-release.yml@develop
+
+ with:
+ packages: |
+ {
+ "go": "go"
+ }
+
secrets:
ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/README.md b/README.md
index c13e710..ad40b9b 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,123 @@
# Tokenforge
One spec, every language — context-aware credential architecture for generating and verifying structured tokens with byte-identical layout and CRC32 tail checksums.
+
+```
+[SystemIdentifier]_[EnvironmentIdentifier]_[DomainPurposeIdentifier]_[Entropy][Checksum]
+```
+
+| Segment | Content | Width |
+|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------|
+| Prefix | System, environment, domain purpose identifiers, delimited by `_`
Restricts every semantic component to lowercase ASCII letters and decimal digits only. Underscores, uppercase letters, and any multi-byte non-ASCII characters are strictly forbidden.
`ALPHABET = 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz` | Variable (≥ 6) |
+| High-intensity Entropy | 24 Base62 characters
Strictly the 62-character GMP dictionary, ordered by ASCII code in ascending order. Third-party Base62 dialects that embed internal permutations are prohibited
`PREFIX_CHARSET = [a-z0-9]` | 24 |
+| Tail Checksum | 6 Base62 characters encoding CRC32-IEEE of Prefix + Entropy | 6 |
+
+**Physical Seamless Fusion** — No separator is permitted between the high-intensity entropy and the tail checksum. The full-stack slice cursor operates as a hard asymmetric dead-lock: the last 6 characters are always the checksum, everything before them is always the base string.
+
+**Absolute Unambiguous Prefix** — Each semantic component of the prefix is subject to strict character-set constraints that fundamentally eliminate cross-platform parsing ambiguity and the hash inconsistency introduced by Unicode normalization (NFC/NFD).
+
+**Unbiased Uniform Sampling** — Direct modulo on a low-bit-width integer is prohibited across all platforms. Every random index must be drawn from an OS-level cryptographically secure random number generator (CSPRNG) via rejection sampling, completely eliminating modulo bias.
+
+**Structured Threshold Assertion** — Perimeter length guards discard hard-coded magic numbers. Minimum valid lengths are derived dynamically from the credential's own topology formula.
+
+## 🚀 Quick Start
+
+### Go
+
+```bash
+go get go.leoweyr.com/tokenforge/go
+```
+
+## 🏗️ Generation Pipeline
+
+### 1. Prefix Construction
+
+Concatenate plaintext semantic segments for the given use case. Prefix length is variable and determined by system design, but must conform to a fixed topology.
+
+*Example*: `odc_prod_msk`
+
+### 2. Unbiased Entropy Generation
+
+Draw 24 characters from `ALPHABET` using an OS-level CSPRNG with a rejection-sampling loop to ensure each index is drawn uniformly from `[0, 61]`. Direct modulo on a raw random integer is forbidden — it introduces a statistical skew that taints the distribution. The output is a strictly fixed 24-character string.
+
+*Example*: `7xT2zP9qL4wK1mN8vV5cB3nA`
+
+### 3. Base String Concatenation
+
+Concatenate the prefix from step 1 and the high-intensity entropy string from step 2 directly:
+
+$$
+\text{BaseString} = \text{Prefix} + \text{HighIntensityEntropy}
+$$
+
+*Example*: `odc_prod_msk_7xT2zP9qL4wK1mN8vV5cB3nA`
+
+### 4. Mathematical CRC32 Mapping
+
+Compute the CRC32-IEEE (reflected form) checksum of `BaseString` encoded as a UTF-8 byte stream, yielding a 32-bit unsigned integer $\text{Value}$. Convert $\text{Value}$ to a 6-character Base62 string $\text{Checksum}$ using the following right-to-left modulo loop:
+
+$$
+\begin{array}{l}
+\text{for } i = 5 \rightarrow 0: \\
+\quad \text{Remainder} = \text{Value} \bmod 62 \\
+\quad \text{Checksum}[i] = \text{ALPHABET}[\text{Remainder}] \\
+\quad \text{Value} = \left\lfloor \dfrac{\text{Value}}{62} \right\rfloor
+\end{array}
+$$
+
+The loop fills from the last position backward. Any value that does not require all 6 digits is naturally zero-padded at the front — no explicit padding logic is needed.
+
+### 5. Final Assembly
+
+Append the 6-character checksum directly to the end of the base string with no separator:
+
+$$
+\text{Token} = \text{BaseString} + \text{TailChecksum}
+$$
+
+*Example*: `odc_prod_msk_7xT2zP9qL4wK1mN8vV5cB3nA4VHrHM`
+
+## 🛡️ Validation Pipeline
+
+### 1. Structural Guard & Asymmetric Slice
+
+At every network edge gateway or application entry point, perform hard physical boundary assertions before any business logic runs.
+
+Length check:
+
+$$
+\text{MinLength} = \text{len}(\text{Prefix}) + 24 + 6
+$$
+
+If the validator holds a known expected `Prefix`, the token length must equal exactly $\text{len}(\text{Prefix}) + 30$. Without a known prefix, the absolute minimum token length is 36 characters (each of the three prefix components must be at least 1 character, so the shortest valid prefix is 6 characters). Any token shorter than the derived threshold is discarded immediately.
+
+Atomic slice, ignoring internal underscore structure, using the fixed-width checksum cursor:
+
+$$
+\begin{matrix}
+\text{BaseString} = \text{Token}[0:\text{len}(\text{Token}) - 6] \\
+\text{ProvidedTailCheckSum} = \text{Token}[\text{len}(\text{Token}) - 6:\text{len}(\text{Token})]
+\end{matrix}
+$$
+
+### 2. Idempotent Verification
+
+Re-execute the generation pipeline step 4 mapping locally on the extracted `BaseString` to obtain `ExpectedTailChecksum`. If `ExpectedChecksum ≠ ProvidedChecksum`, the token is rejected immediately as corrupted or truncated — fail-fast, no further processing.
+
+### 3. Context Reification
+
+Only after passing step 2 may the system split the prefix portion of `BaseString` on `_`. Because `PREFIX_CHARSET` forbids underscores within any component, the split result is uniquely deterministic across every platform and encoding. Extract the system, environment, and domain purpose identifiers and inject them as a typed security context object into downstream operations.
+
+## ⚖️ Why 24 Characters
+
+On the cryptographic side, 24 Base62 characters carry:
+
+$$
+62^{24} \approx 2^{143} \text{ bits}
+$$
+
+The practical security floor for API tokens in cloud-native architecture is 128 bits. 24 characters delivers 143 bits — clearing the threshold with margin to spare.
+
+Some vendors push further: GitHub's personal access tokens use 30 entropy characters, reaching ~178 bits. From a pure cryptographic standpoint, that number is unimpeachable. From an engineering leverage standpoint, it is unnecessary — beyond ~140 bits, the marginal security return per additional character converges to zero. The cost, however, is real. Every extra character widens network payloads, inflates database index pages, and — on mobile — turns a token into a string too long to select cleanly with a long-press.
+
+Tokenforge locks high-intensity entropy at 24 characters: the precise point where cryptographic surplus meets transmission efficiency and human ergonomics, with nothing wasted on either side.
diff --git a/go/CHANGELOG.md b/go/CHANGELOG.md
new file mode 100644
index 0000000..b6ee6d2
--- /dev/null
+++ b/go/CHANGELOG.md
@@ -0,0 +1,18 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+# [unreleased]
+### Features
+
+* **go:** implement token generation and validation module ([42a2e00](https://github.com/leoweyr/tokenforge/commit/42a2e00d9419792fbc719d8e5b53cb0392b4009d)) [@leoweyr](https://github.com/leoweyr)
+
+
+### Refactor
+
+* **go:** align module path with `go/` subdirectory location in repository ([f507e51](https://github.com/leoweyr/tokenforge/commit/f507e51324b143d75d962eeeb02cb7c29e580331)) [@leoweyr](https://github.com/leoweyr)
+* batch CSPRNG reads and name components in validation errors ([bd322ad](https://github.com/leoweyr/tokenforge/commit/bd322adce4beb2ace1d1ef5fa9ad9121f43286ac)) [@leoweyr](https://github.com/leoweyr)
+
+
+
+
diff --git a/go/forge.go b/go/forge.go
new file mode 100644
index 0000000..4192570
--- /dev/null
+++ b/go/forge.go
@@ -0,0 +1,63 @@
+package tokenforge
+
+import (
+ "go.leoweyr.com/tokenforge/go/internal/checksum"
+ "go.leoweyr.com/tokenforge/go/internal/encoding"
+ "go.leoweyr.com/tokenforge/go/internal/entropy"
+ "go.leoweyr.com/tokenforge/go/internal/token"
+)
+
+// Forge is the public entry point of the Tokenforge module. It composes the
+// generation and validation pipelines and exposes them behind a small surface.
+type Forge struct {
+ generator *token.TokenGenerator
+ validator *token.TokenValidator
+}
+
+// NewForge builds a Forge by wiring the Base62 alphabet, the prefix alphabet, the
+// Base62 encoder, the CRC32 checksum calculator, and the secure entropy generator
+// into a generation pipeline and a validation pipeline.
+func NewForge() *Forge {
+ var base62Alphabet *encoding.Alphabet = encoding.NewAlphabet(encoding.Base62Characters)
+ var prefixAlphabet *encoding.Alphabet = encoding.NewAlphabet(encoding.PrefixCharacters)
+
+ var encoder *encoding.Base62Encoder = encoding.NewBase62Encoder(base62Alphabet)
+ var checksumCalculator *checksum.Crc32Calculator = checksum.NewCrc32Calculator(encoder)
+ var entropyGenerator *entropy.SecureGenerator = entropy.NewSecureGenerator(base62Alphabet)
+
+ var generator *token.TokenGenerator = token.NewTokenGenerator(prefixAlphabet, entropyGenerator, checksumCalculator)
+ var validator *token.TokenValidator = token.NewTokenValidator(prefixAlphabet, checksumCalculator)
+
+ return &Forge{
+ generator: generator,
+ validator: validator,
+ }
+}
+
+// Generate runs the full generation pipeline for the given semantic identifiers and
+// returns the rendered token string.
+func (forge *Forge) Generate(systemIdentifier string, environmentIdentifier string, domainPurposeIdentifier string) (string, error) {
+ var generated *token.Token
+ var generationError error
+ generated, generationError = forge.generator.Generate(systemIdentifier, environmentIdentifier, domainPurposeIdentifier)
+
+ if generationError != nil {
+ return "", generationError
+ }
+
+ return generated.String(), nil
+}
+
+// Validate runs the full validation pipeline against the raw token and returns the
+// reified security context when the token is structurally and cryptographically sound.
+func (forge *Forge) Validate(rawToken string) (*SecurityContext, error) {
+ var validated *token.Token
+ var validationError error
+ validated, validationError = forge.validator.Validate(rawToken)
+
+ if validationError != nil {
+ return nil, validationError
+ }
+
+ return newSecurityContext(validated.SystemIdentifier(), validated.EnvironmentIdentifier(), validated.DomainPurposeIdentifier()), nil
+}
diff --git a/go/go.mod b/go/go.mod
new file mode 100644
index 0000000..15835bf
--- /dev/null
+++ b/go/go.mod
@@ -0,0 +1,3 @@
+module go.leoweyr.com/tokenforge/go
+
+go 1.26.2
diff --git a/go/internal/checksum/calculator.go b/go/internal/checksum/calculator.go
new file mode 100644
index 0000000..fe74c82
--- /dev/null
+++ b/go/internal/checksum/calculator.go
@@ -0,0 +1,32 @@
+package checksum
+
+import (
+ "hash/crc32"
+
+ "go.leoweyr.com/tokenforge/go/internal/encoding"
+)
+
+// Calculator maps a token base string to its fixed-width Base62 tail checksum.
+type Calculator interface {
+ Calculate(baseString string) *Checksum
+}
+
+// Crc32Calculator derives the tail checksum from the CRC32-IEEE value of a base
+// string encoded as Base62.
+type Crc32Calculator struct {
+ encoder *encoding.Base62Encoder
+}
+
+// NewCrc32Calculator builds a Crc32Calculator backed by the given Base62 encoder.
+func NewCrc32Calculator(encoder *encoding.Base62Encoder) *Crc32Calculator {
+ return &Crc32Calculator{encoder: encoder}
+}
+
+// Calculate computes the CRC32-IEEE value of the base string interpreted as a UTF-8
+// byte stream and encodes it as a fixed-width Base62 checksum.
+func (crc32Calculator *Crc32Calculator) Calculate(baseString string) *Checksum {
+ var value uint32 = crc32.ChecksumIEEE([]byte(baseString))
+ var encoded string = crc32Calculator.encoder.Encode(value, Length)
+
+ return NewChecksum(encoded)
+}
diff --git a/go/internal/checksum/checksum.go b/go/internal/checksum/checksum.go
new file mode 100644
index 0000000..3267d10
--- /dev/null
+++ b/go/internal/checksum/checksum.go
@@ -0,0 +1,31 @@
+package checksum
+
+// Length is the fixed number of Base62 characters in the tail checksum segment,
+// wide enough to encode any 32-bit CRC value without truncation.
+const Length int = 6
+
+// Checksum is the fixed-width Base62 tail segment encoding the CRC32 integrity
+// value of a token base string.
+type Checksum struct {
+ value string
+}
+
+// NewChecksum wraps the given fixed-width Base62 string as a Checksum value.
+func NewChecksum(value string) *Checksum {
+ return &Checksum{value: value}
+}
+
+// Value returns the raw checksum characters.
+func (checksum *Checksum) Value() string {
+ return checksum.value
+}
+
+// Equals reports whether this checksum carries the same characters as the other checksum.
+func (checksum *Checksum) Equals(other *Checksum) bool {
+ return checksum.value == other.value
+}
+
+// String returns the raw checksum characters.
+func (checksum *Checksum) String() string {
+ return checksum.value
+}
diff --git a/go/internal/encoding/alphabet.go b/go/internal/encoding/alphabet.go
new file mode 100644
index 0000000..94caf4d
--- /dev/null
+++ b/go/internal/encoding/alphabet.go
@@ -0,0 +1,64 @@
+package encoding
+
+// Base62Characters is the canonical 62-symbol GMP dictionary ordered by ascending
+// ASCII code, used for high-intensity entropy and tail checksum encoding.
+const Base62Characters string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+
+// PrefixCharacters is the restricted symbol set permitted inside prefix semantic
+// components, limited to lowercase ASCII letters and decimal digits only.
+const PrefixCharacters string = "0123456789abcdefghijklmnopqrstuvwxyz"
+
+// Alphabet is an immutable ordered symbol set that maps between character values
+// and their positional indices.
+type Alphabet struct {
+ characters string
+ indexByCharacter map[byte]int
+}
+
+// NewAlphabet builds an Alphabet from the given ordered character set and indexes
+// every symbol for constant-time membership and lookup queries.
+func NewAlphabet(characters string) *Alphabet {
+ var indexByCharacter map[byte]int = make(map[byte]int, len(characters))
+
+ var position int
+
+ for position = 0; position < len(characters); position++ {
+ indexByCharacter[characters[position]] = position
+ }
+
+ return &Alphabet{
+ characters: characters,
+ indexByCharacter: indexByCharacter,
+ }
+}
+
+// Size returns the number of symbols contained in the alphabet.
+func (alphabet *Alphabet) Size() int {
+ return len(alphabet.characters)
+}
+
+// CharacterAt returns the symbol located at the given positional index.
+func (alphabet *Alphabet) CharacterAt(index int) byte {
+ return alphabet.characters[index]
+}
+
+// Contains reports whether the given character belongs to the alphabet.
+func (alphabet *Alphabet) Contains(character byte) bool {
+ var present bool
+ _, present = alphabet.indexByCharacter[character]
+
+ return present
+}
+
+// Permits reports whether every character in the text belongs to the alphabet.
+func (alphabet *Alphabet) Permits(text string) bool {
+ var position int
+
+ for position = 0; position < len(text); position++ {
+ if !alphabet.Contains(text[position]) {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/go/internal/encoding/base62_encoder.go b/go/internal/encoding/base62_encoder.go
new file mode 100644
index 0000000..c44f54c
--- /dev/null
+++ b/go/internal/encoding/base62_encoder.go
@@ -0,0 +1,30 @@
+package encoding
+
+// Base62Encoder converts unsigned integers into fixed-width Base62 strings using a
+// right-to-left modulo loop that yields natural front zero-padding.
+type Base62Encoder struct {
+ base62Alphabet *Alphabet
+}
+
+// NewBase62Encoder builds a Base62Encoder bound to the given Base62 alphabet.
+func NewBase62Encoder(base62Alphabet *Alphabet) *Base62Encoder {
+ return &Base62Encoder{base62Alphabet: base62Alphabet}
+}
+
+// Encode renders the given value as a Base62 string of exactly the requested width,
+// filling positions from the least significant digit backward.
+func (base62Encoder *Base62Encoder) Encode(value uint32, width int) string {
+ var radix uint32 = uint32(base62Encoder.base62Alphabet.Size())
+ var characters []byte = make([]byte, width)
+ var remaining uint32 = value
+
+ var position int
+
+ for position = width - 1; position >= 0; position-- {
+ var remainder uint32 = remaining % radix
+ characters[position] = base62Encoder.base62Alphabet.CharacterAt(int(remainder))
+ remaining = remaining / radix
+ }
+
+ return string(characters)
+}
diff --git a/go/internal/entropy/entropy.go b/go/internal/entropy/entropy.go
new file mode 100644
index 0000000..62586e9
--- /dev/null
+++ b/go/internal/entropy/entropy.go
@@ -0,0 +1,30 @@
+package entropy
+
+// Length is the fixed number of Base62 characters in the high-intensity entropy
+// segment, sized to deliver roughly 143 bits of randomness.
+const Length int = 24
+
+// Entropy is the fixed-width high-intensity random segment of a token.
+type Entropy struct {
+ value string
+}
+
+// NewEntropy wraps the given fixed-width random string as an Entropy value.
+func NewEntropy(value string) *Entropy {
+ return &Entropy{value: value}
+}
+
+// Value returns the raw entropy characters.
+func (entropy *Entropy) Value() string {
+ return entropy.value
+}
+
+// Length returns the number of characters in the entropy segment.
+func (entropy *Entropy) Length() int {
+ return len(entropy.value)
+}
+
+// String returns the raw entropy characters.
+func (entropy *Entropy) String() string {
+ return entropy.value
+}
diff --git a/go/internal/entropy/generator.go b/go/internal/entropy/generator.go
new file mode 100644
index 0000000..6cb5b08
--- /dev/null
+++ b/go/internal/entropy/generator.go
@@ -0,0 +1,58 @@
+package entropy
+
+import (
+ "crypto/rand"
+
+ "go.leoweyr.com/tokenforge/go/internal/encoding"
+)
+
+// Generator produces a fresh high-intensity entropy segment on demand.
+type Generator interface {
+ Generate() (*Entropy, error)
+}
+
+// SecureGenerator draws entropy from an operating-system CSPRNG and applies
+// rejection sampling to guarantee an unbiased uniform symbol distribution.
+type SecureGenerator struct {
+ base62Alphabet *encoding.Alphabet
+}
+
+// NewSecureGenerator builds a SecureGenerator bound to the given Base62 alphabet.
+func NewSecureGenerator(base62Alphabet *encoding.Alphabet) *SecureGenerator {
+ return &SecureGenerator{base62Alphabet: base62Alphabet}
+}
+
+// Generate produces a fixed-width entropy segment by drawing unbiased indices from the bound alphabet.
+// A 32-byte bulk read reduces CSPRNG syscall overhead to O(1).
+func (secureGenerator *SecureGenerator) Generate() (*Entropy, error) {
+ var characters []byte = make([]byte, Length)
+ var size int = secureGenerator.base62Alphabet.Size()
+ var ceiling int = 256 - (256 % size)
+ var buffer [32]byte
+ var bufferPosition int = len(buffer)
+
+ var position int = 0
+
+ for position < Length {
+ if bufferPosition >= len(buffer) {
+ var readError error
+ _, readError = rand.Read(buffer[:])
+
+ if readError != nil {
+ return nil, readError
+ }
+
+ bufferPosition = 0
+ }
+
+ var candidate int = int(buffer[bufferPosition])
+ bufferPosition++
+
+ if candidate < ceiling {
+ characters[position] = secureGenerator.base62Alphabet.CharacterAt(candidate % size)
+ position++
+ }
+ }
+
+ return NewEntropy(string(characters)), nil
+}
diff --git a/go/internal/fault/validation_error.go b/go/internal/fault/validation_error.go
new file mode 100644
index 0000000..64d7821
--- /dev/null
+++ b/go/internal/fault/validation_error.go
@@ -0,0 +1,17 @@
+package fault
+
+// ValidationError represents a structural or integrity failure detected while a
+// token is checked against the Tokenforge specification.
+type ValidationError struct {
+ reason string
+}
+
+// NewValidationError creates a ValidationError carrying the given human-readable reason.
+func NewValidationError(reason string) *ValidationError {
+ return &ValidationError{reason: reason}
+}
+
+// Error returns the underlying failure reason and satisfies the error interface.
+func (validationError *ValidationError) Error() string {
+ return validationError.reason
+}
diff --git a/go/internal/token/generator.go b/go/internal/token/generator.go
new file mode 100644
index 0000000..ad2475a
--- /dev/null
+++ b/go/internal/token/generator.go
@@ -0,0 +1,75 @@
+package token
+
+import (
+ "go.leoweyr.com/tokenforge/go/internal/checksum"
+ "go.leoweyr.com/tokenforge/go/internal/encoding"
+ "go.leoweyr.com/tokenforge/go/internal/entropy"
+ "go.leoweyr.com/tokenforge/go/internal/fault"
+)
+
+// TokenGenerator orchestrates the full generation pipeline, turning a set of
+// semantic identifiers into a verified, fully assembled token.
+type TokenGenerator struct {
+ prefixAlphabet *encoding.Alphabet
+ entropyGenerator entropy.Generator
+ checksumCalculator checksum.Calculator
+}
+
+// NewTokenGenerator wires a TokenGenerator to its prefix alphabet, entropy source,
+// and checksum calculator.
+func NewTokenGenerator(prefixAlphabet *encoding.Alphabet, entropyGenerator entropy.Generator, checksumCalculator checksum.Calculator) *TokenGenerator {
+ return &TokenGenerator{
+ prefixAlphabet: prefixAlphabet,
+ entropyGenerator: entropyGenerator,
+ checksumCalculator: checksumCalculator,
+ }
+}
+
+// validateComponent rejects an empty semantic identifier or one carrying any
+// character outside the permitted prefix alphabet.
+func (tokenGenerator *TokenGenerator) validateComponent(label string, value string) error {
+ if len(value) == 0 {
+ return fault.NewValidationError(label + " identifier must not be empty")
+ }
+
+ if !tokenGenerator.prefixAlphabet.Permits(value) {
+ return fault.NewValidationError(label + " identifier contains a character outside the permitted set")
+ }
+
+ return nil
+}
+
+// Generate validates the supplied identifiers, draws unbiased entropy, fuses the
+// base string, maps the checksum, and returns the assembled token.
+func (tokenGenerator *TokenGenerator) Generate(systemIdentifier string, environmentIdentifier string, domainPurposeIdentifier string) (*Token, error) {
+ var systemError error = tokenGenerator.validateComponent("System", systemIdentifier)
+
+ if systemError != nil {
+ return nil, systemError
+ }
+
+ var environmentError error = tokenGenerator.validateComponent("Environment", environmentIdentifier)
+
+ if environmentError != nil {
+ return nil, environmentError
+ }
+
+ var domainError error = tokenGenerator.validateComponent("Domain purpose", domainPurposeIdentifier)
+
+ if domainError != nil {
+ return nil, domainError
+ }
+
+ var entropySegment *entropy.Entropy
+ var generationError error
+ entropySegment, generationError = tokenGenerator.entropyGenerator.Generate()
+
+ if generationError != nil {
+ return nil, generationError
+ }
+
+ var baseString string = assembleBaseString(systemIdentifier, environmentIdentifier, domainPurposeIdentifier, entropySegment)
+ var checksumSegment *checksum.Checksum = tokenGenerator.checksumCalculator.Calculate(baseString)
+
+ return NewToken(systemIdentifier, environmentIdentifier, domainPurposeIdentifier, entropySegment, checksumSegment), nil
+}
diff --git a/go/internal/token/token.go b/go/internal/token/token.go
new file mode 100644
index 0000000..ef03e1c
--- /dev/null
+++ b/go/internal/token/token.go
@@ -0,0 +1,84 @@
+package token
+
+import (
+ "go.leoweyr.com/tokenforge/go/internal/checksum"
+ "go.leoweyr.com/tokenforge/go/internal/entropy"
+)
+
+// Separator is the single-byte delimiter placed between prefix semantic components
+// and between the prefix and the entropy segment.
+const Separator string = "_"
+
+// PrefixComponentCount is the exact number of semantic identifiers required inside
+// a well-formed prefix.
+const PrefixComponentCount int = 3
+
+// MinimumPrefixLength is the shortest legal prefix portion, reached when each of the
+// three semantic components holds a single character (Plus the three delimiters).
+const MinimumPrefixLength int = PrefixComponentCount * 2
+
+// MinimumLength is the shortest legal token, derived from the credential topology
+// rather than any hard-coded magic number.
+const MinimumLength int = MinimumPrefixLength + entropy.Length + checksum.Length
+
+// assembleBaseString concatenates the three prefix identifiers, separators, and the
+// entropy segment into the canonical base string used for checksum mapping.
+func assembleBaseString(systemIdentifier string, environmentIdentifier string, domainPurposeIdentifier string, entropy *entropy.Entropy) string {
+ return systemIdentifier + Separator + environmentIdentifier + Separator + domainPurposeIdentifier + Separator + entropy.Value()
+}
+
+// Token is a fully assembled credential storing the three prefix semantic identifiers,
+// a high-intensity entropy segment, and a tail checksum.
+type Token struct {
+ systemIdentifier string
+ environmentIdentifier string
+ domainPurposeIdentifier string
+ entropy *entropy.Entropy
+ checksum *checksum.Checksum
+}
+
+// NewToken composes a Token from its three prefix identifiers, entropy, and checksum.
+func NewToken(systemIdentifier string, environmentIdentifier string, domainPurposeIdentifier string, entropy *entropy.Entropy, checksum *checksum.Checksum) *Token {
+ return &Token{
+ systemIdentifier: systemIdentifier,
+ environmentIdentifier: environmentIdentifier,
+ domainPurposeIdentifier: domainPurposeIdentifier,
+ entropy: entropy,
+ checksum: checksum,
+ }
+}
+
+// SystemIdentifier returns the system identifier.
+func (token *Token) SystemIdentifier() string {
+ return token.systemIdentifier
+}
+
+// EnvironmentIdentifier returns the environment identifier.
+func (token *Token) EnvironmentIdentifier() string {
+ return token.environmentIdentifier
+}
+
+// DomainPurposeIdentifier returns the domain purpose identifier.
+func (token *Token) DomainPurposeIdentifier() string {
+ return token.domainPurposeIdentifier
+}
+
+// Entropy returns the high-intensity entropy segment.
+func (token *Token) Entropy() *entropy.Entropy {
+ return token.entropy
+}
+
+// Checksum returns the tail checksum segment.
+func (token *Token) Checksum() *checksum.Checksum {
+ return token.checksum
+}
+
+// BaseString returns the checksum-free base string (prefix + entropy, joined by separators).
+func (token *Token) BaseString() string {
+ return assembleBaseString(token.systemIdentifier, token.environmentIdentifier, token.domainPurposeIdentifier, token.entropy)
+}
+
+// String renders the complete token.
+func (token *Token) String() string {
+ return token.BaseString() + token.checksum.Value()
+}
diff --git a/go/internal/token/validator.go b/go/internal/token/validator.go
new file mode 100644
index 0000000..aa27302
--- /dev/null
+++ b/go/internal/token/validator.go
@@ -0,0 +1,119 @@
+package token
+
+import (
+ "strings"
+
+ "go.leoweyr.com/tokenforge/go/internal/checksum"
+ "go.leoweyr.com/tokenforge/go/internal/encoding"
+ "go.leoweyr.com/tokenforge/go/internal/entropy"
+ "go.leoweyr.com/tokenforge/go/internal/fault"
+)
+
+// TokenValidator orchestrates the validation pipeline: a structural guard, an
+// asymmetric checksum slice, idempotent integrity verification, and context
+// reification into the token's three prefix identifiers.
+type TokenValidator struct {
+ prefixAlphabet *encoding.Alphabet
+ checksumCalculator checksum.Calculator
+}
+
+// NewTokenValidator wires a TokenValidator to its prefix alphabet and checksum calculator.
+func NewTokenValidator(prefixAlphabet *encoding.Alphabet, checksumCalculator checksum.Calculator) *TokenValidator {
+ return &TokenValidator{
+ prefixAlphabet: prefixAlphabet,
+ checksumCalculator: checksumCalculator,
+ }
+}
+
+// verifyChecksum re-derives the expected checksum from the base string and rejects
+// the token when it diverges from the provided checksum.
+func (tokenValidator *TokenValidator) verifyChecksum(baseString string, provided *checksum.Checksum) error {
+ var expected *checksum.Checksum = tokenValidator.checksumCalculator.Calculate(baseString)
+
+ if !expected.Equals(provided) {
+ return fault.NewValidationError("Token checksum does not match its base string")
+ }
+
+ return nil
+}
+
+// validateComponent rejects an empty identifier or one bearing a character outside
+// the permitted prefix alphabet.
+func (tokenValidator *TokenValidator) validateComponent(componentName string, value string) error {
+ if len(value) == 0 {
+ return fault.NewValidationError("Token prefix " + componentName + " component is empty")
+ }
+
+ if !tokenValidator.prefixAlphabet.Permits(value) {
+ return fault.NewValidationError("Token prefix " + componentName + " component contains a character outside the permitted set")
+ }
+
+ return nil
+}
+
+// reifyContext splits the prefix portion into its three semantic identifiers,
+// enforcing the exact component count and the permitted prefix alphabet.
+func (tokenValidator *TokenValidator) reifyContext(prefixPortion string) (string, string, string, error) {
+ if !strings.HasSuffix(prefixPortion, Separator) {
+ return "", "", "", fault.NewValidationError("Token prefix is not terminated by a separator")
+ }
+
+ var core string = prefixPortion[:len(prefixPortion)-len(Separator)]
+ var components []string = strings.Split(core, Separator)
+
+ if len(components) != PrefixComponentCount {
+ return "", "", "", fault.NewValidationError("Token prefix does not contain exactly three semantic components")
+ }
+
+ var systemError error = tokenValidator.validateComponent("system", components[0])
+
+ if systemError != nil {
+ return "", "", "", systemError
+ }
+
+ var environmentError error = tokenValidator.validateComponent("environment", components[1])
+
+ if environmentError != nil {
+ return "", "", "", environmentError
+ }
+
+ var domainPurposeError error = tokenValidator.validateComponent("domain purpose", components[2])
+
+ if domainPurposeError != nil {
+ return "", "", "", domainPurposeError
+ }
+
+ return components[0], components[1], components[2], nil
+}
+
+// Validate enforces the structural guard, performs the asymmetric checksum slice,
+// verifies integrity idempotently, and reifies the semantic context into a token.
+func (tokenValidator *TokenValidator) Validate(rawToken string) (*Token, error) {
+ if len(rawToken) < MinimumLength {
+ return nil, fault.NewValidationError("Token is shorter than the minimum derived length")
+ }
+
+ var baseString string = rawToken[:len(rawToken)-checksum.Length]
+ var providedChecksum *checksum.Checksum = checksum.NewChecksum(rawToken[len(rawToken)-checksum.Length:])
+
+ var verificationError error = tokenValidator.verifyChecksum(baseString, providedChecksum)
+
+ if verificationError != nil {
+ return nil, verificationError
+ }
+
+ var prefixPortion string = baseString[:len(baseString)-entropy.Length]
+ var entropyValue string = baseString[len(baseString)-entropy.Length:]
+
+ var system string
+ var environment string
+ var domain string
+ var reificationError error
+ system, environment, domain, reificationError = tokenValidator.reifyContext(prefixPortion)
+
+ if reificationError != nil {
+ return nil, reificationError
+ }
+
+ return NewToken(system, environment, domain, entropy.NewEntropy(entropyValue), providedChecksum), nil
+}
diff --git a/go/security_context.go b/go/security_context.go
new file mode 100644
index 0000000..1b7dafe
--- /dev/null
+++ b/go/security_context.go
@@ -0,0 +1,40 @@
+package tokenforge
+
+import "strings"
+
+// SecurityContext exposes the three plaintext semantic identifiers reified from a
+// validated token: the system, the environment, and the domain purpose.
+type SecurityContext struct {
+ systemIdentifier string
+ environmentIdentifier string
+ domainPurposeIdentifier string
+}
+
+// newSecurityContext assembles a SecurityContext from its three semantic identifiers.
+func newSecurityContext(systemIdentifier string, environmentIdentifier string, domainIdentifier string) *SecurityContext {
+ return &SecurityContext{
+ systemIdentifier: systemIdentifier,
+ environmentIdentifier: environmentIdentifier,
+ domainPurposeIdentifier: domainIdentifier,
+ }
+}
+
+// SystemIdentifier returns the system identifier.
+func (securityContext *SecurityContext) SystemIdentifier() string {
+ return securityContext.systemIdentifier
+}
+
+// EnvironmentIdentifier returns the environment identifier.
+func (securityContext *SecurityContext) EnvironmentIdentifier() string {
+ return securityContext.environmentIdentifier
+}
+
+// DomainPurposeIdentifier returns the domain purpose identifier.
+func (securityContext *SecurityContext) DomainPurposeIdentifier() string {
+ return securityContext.domainPurposeIdentifier
+}
+
+// String renders the three identifiers joined by underscores.
+func (securityContext *SecurityContext) String() string {
+ return strings.Join([]string{securityContext.systemIdentifier, securityContext.environmentIdentifier, securityContext.domainPurposeIdentifier}, "_")
+}