This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
verax (Latin for "truthful") is a Go validation library for primitive types,
structs, slices, arrays, and maps. It produces human-readable and
JSON-serializable errors, and supports custom rules and conditional validation.
Module: github.com/ctx42/verax
# Run all tests
go test ./...
# Run tests with race detection (matches CI)
go test -v -race ./...
# Run a single test
go test -run Test_FunctionName ./pkg/verax/...
# Run linter (config at tmp/.golangci.yml)
golangci-lint run --config tmp/.golangci.yml ./...pkg/verax— Core package. Contains theValidateandValidateStructentry points, all built-in rules, the error types, and struct-tag handling.pkg/verax/rule— Specialized rules not suitable for the core package: Base64, network types (IP, email, URL, CIDR, domain), and SemVer.pkg/spec— Serialization layer. ProvidesSpec,Source,Registry, andBuildertypes so rules can be represented as data and reconstructed at runtime (useful for storing validation config in databases or APIs).pkg/abc— Empty package used only as a test fixture.internal/test— Shared test helpers.
// Rule is the fundamental unit of validation.
type Rule interface { Validate(have any) error }
// Validator allows a struct to validate itself.
type Validator interface { Validate() error }
// Specable allows a rule to be serialized into a Spec.
type Specable interface { Spec() spec.Spec }All errors use github.com/ctx42/xrr for structured, JSON-serializable errors
with error codes (EC prefix) and error domains (ED prefix). Validation
errors aggregate field-level errors and can be marshaled directly into API
responses.
verax.Validate(value, rules...)stops at the first failing rule.verax.ValidateStruct(s)validates all fields and collects all errors.verax.When(cond, rules...)andverax.Skip(cond, rules...)provide conditional execution.verax.Eachandverax.Maprecurse into slices/arrays and maps.verax.Setgroups rules;verax.Byandverax.Iswrap plain functions.
Spec is a language-agnostic rule description (name + typed args).
Source represents a language-specific instantiation hint. Registry
maps spec names to Builder functions that construct Rule values from
a Spec. Rules opt in to serialization by implementing Specable.
Not all rules can implement Specable. Rules that depend on Go-specific
constructs with no cross-language equivalent (e.g. TypeRule, which holds
a reflect.Type) are intentionally excluded — there is no portable way to
represent a Go type across language boundaries.
| Module | Role |
|---|---|
github.com/ctx42/xrr |
Structured errors with codes and fields |
github.com/ctx42/mirror |
Reflection helpers for struct field introspection |
github.com/ctx42/convert |
Type conversion utilities used in rules |
github.com/ctx42/jsontype |
JSON-aware type helpers |
github.com/ctx42/testing |
Test assertions (assert package) |
Code inside this package (the built-in rules, Validate, ValidateStruct,
Field, When, Each, Map, etc.) must only ever return one of the three
verax domain error types (*Error, *InternalError, or *FieldErrors) or nil.
Never return a raw errors.New, fmt.Errorf, or other non-domain error from
public API functions.
User-provided extension points (Validator, WithValidator, RuleFunc,
EqualFunc, CompareFunc, and custom rules) are currently the caller's
responsibility. Callers should return proper verax domain errors from these
hooks. For now the library does not automatically wrap foreign errors
returned from user callbacks.
This distinction exists because many callers want to return their own error
types (or errors from other libraries) from custom validation logic. The
strong invariant above applies to the library's own implementation and the
errors that ultimately come out of Validate* when only built-in rules are
used.
Follow the global CLAUDE.md conventions. Additionally for this repo:
- Rule types are typically defined as structs with a
Validate(any) errormethod and a constructor function (e.g.,func Min(n any) *Range). - Sentinel errors live at package level with
Errprefix; their codes useECprefix constants defined in the same file. Specableimplementations return aspec.Specdescribing how to reconstruct the rule; see existing rules for the pattern.forbidigobansprintandfmt.Print*everywhere exceptexamples_test.go.