schema

package
v1.15.0 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package schema adds optional, dependency-free per-URN payload validation to a babelqueue producer or consumer (ADR-0024). A Provider supplies a JSON Schema for a message URN — typically read from a babelqueue-registry registry.json — and the message's data block is validated against it. It is opt-in: a URN with no registered schema is never validated.

The validator is an intentionally small subset of JSON Schema (draft-07) — enough to describe a message's data, mirroring the subset babelqueue-registry and php-sdk's envelope validator enforce. It is NOT a full draft-07 implementation; unknown keywords are ignored. It lives in the core module (stdlib only, zero dependencies) so it ships with every SDK.

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidPayload = errors.New("babelqueue/schema: message data does not match its URN schema")

ErrInvalidPayload is returned (wrapped) when a message's data does not match the schema registered for its URN. Detect it with errors.Is.

Functions

func Check

func Check(provider Provider, urn string, data map[string]any) error

Check validates a (urn, data) pair against the schema registered for urn. It is the producer-side guard: call it before publishing so invalid data never enters the queue. It returns nil when the data is valid OR when no schema is registered for the URN (opt-in); a provider lookup error is returned wrapped (transient — e.g. the registry file is briefly unavailable during a deploy).

func Validate

func Validate(provider Provider, env babelqueue.Envelope) error

Validate is the envelope form of Check: it validates env.Data against env.URN()'s schema.

func Wrap

func Wrap(provider Provider, handler babelqueue.Handler) babelqueue.Handler

Wrap returns handler decorated to validate each message's data against its URN schema before the handler runs (consumer-side safety net). It composes with the App's ack-on-return / retry-on-error contract:

  • valid data (or no schema registered for the URN) → the handler runs unchanged;
  • invalid data → ErrInvalidPayload is returned, so the message takes the retry / dead-letter path. Because invalid data will not become valid on retry, such a poison message exhausts its attempts and is dead-lettered — prefer Check producer-side to keep invalid data out of the queue entirely;
  • a provider lookup error → returned, so the message is retried once the source recovers.

Register it like any handler: app.Handle(urn, schema.Wrap(provider, handler)).

Types

type DirProvider

type DirProvider struct {
	// contains filtered or unexported fields
}

DirProvider reads schemas from a babelqueue-registry manifest (registry.json): a list of {urn, schema} entries mapping each URN to a draft-07 schema file for its data block. This is the bridge that makes the registry's governed schemas enforceable at runtime. The manifest is read once; schema files are parsed lazily and cached.

func NewDirProvider

func NewDirProvider(manifestPath string) (*DirProvider, error)

NewDirProvider loads the registry manifest at manifestPath (e.g. ".../registry.json").

func (*DirProvider) Schema

func (p *DirProvider) Schema(urn string) (*Schema, bool, error)

Schema implements Provider, reading and caching the schema file on first use.

type MapProvider

type MapProvider struct {
	// contains filtered or unexported fields
}

MapProvider is an in-memory Provider, suitable for tests and for embedding schemas in code. It is read-only after construction and therefore safe for concurrent use.

func NewMapProvider

func NewMapProvider(raw map[string][]byte) (*MapProvider, error)

NewMapProvider builds a MapProvider from URN → raw JSON Schema bytes, parsing each.

func (*MapProvider) Schema

func (m *MapProvider) Schema(urn string) (*Schema, bool, error)

Schema implements Provider.

type Provider

type Provider interface {
	// Schema returns the schema registered for urn. found is false when the URN has no
	// registered schema, in which case the caller skips validation (opt-in).
	Schema(urn string) (sch *Schema, found bool, err error)
}

Provider is a source of per-URN data schemas. The reference MapProvider is in-memory; DirProvider reads a babelqueue-registry registry.json. A production provider (a service client, an embedded bundle) implements the same single method.

type Schema

type Schema struct {
	Type                 string             // object|string|integer|number|boolean|array|null; "" = unconstrained
	Required             []string           // object: required property names
	Properties           map[string]*Schema // object: per-property schemas
	AdditionalProperties *bool              // object: nil = open (draft-07 default true)
	Items                *Schema            // array: item schema
	Enum                 []any              // allowed values (nil = any)
	Const                any                // fixed value when HasConst
	HasConst             bool
	MinLength            *int     // string (counted in Unicode code points)
	Minimum              *float64 // integer|number

	// GDPRSensitive marks a property as carrying personal/sensitive data
	// ("x-gdpr-sensitive": true). It is a JSON-Schema extension keyword (ADR-0030):
	// validation ignores it entirely (it never makes a value valid or invalid), so a registry
	// can declare sensitivity without changing how data is validated — adding it is never a
	// breaking change (GR-1). GDPRCategory carries the optional free-form category form
	// ("x-gdpr-sensitive": "email") for documentation; it is "" when the keyword was the
	// boolean true. The gdpr subpackage consumes these marks to encrypt/decrypt the matching
	// values at runtime; this mirrors babelqueue-registry's internal/schema model.
	GDPRSensitive bool
	GDPRCategory  string
}

Schema is a parsed (subset) JSON Schema node.

func Parse

func Parse(raw []byte) (*Schema, error)

Parse decodes a (subset) JSON Schema document.

func (*Schema) SensitivePaths added in v1.8.0

func (s *Schema) SensitivePaths() []SensitivePath

SensitivePaths walks the schema and returns every property marked x-gdpr-sensitive, in sorted path order. It descends into nested objects (dotted paths) and array item schemas ("field[]"). A mark on the root schema itself (path "") is reported as a path of "". It is the value-level counterpart to the registry's inventory: the gdpr subpackage uses these paths to locate the leaves it must encrypt on produce and decrypt on consume.

func (*Schema) Validate

func (s *Schema) Validate(value any) []string

Validate checks value against the schema and returns a sorted list of human-readable violations. An empty result means the value is valid.

type SensitivePath added in v1.8.0

type SensitivePath struct {
	Path     string
	Category string
}

SensitivePath is one property marked x-gdpr-sensitive, located by its dotted path from the schema root (array elements use the "field[]" segment the validator/compat use). Category is the optional "x-gdpr-sensitive": "<category>" string, or "" when it was the boolean true.

Jump to

Keyboard shortcuts

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